I have union inside structure and the structure looks like
struct tDeviceProperty {
DWORD Tag;
DWORD Size;
union _DP value;
};
typedef union _DP
{
short int i;
LONG l;
ULONG ul;
float flt;
double dbl;
BOOL b;
double at;
FILETIME ft;
LPSTR lpszA;
LPWSTR lpszW;
LARGE_INTEGER li;
struct tBinary bin;
BYTE reserved[40];
} __UDP;
struct tBinary {
ULONG size;
BYTE * bin;
};
from the tBinary structure bin has to be converted to tImage (structure is given below)
struct tImage {
DWORD x;
DWORD y;
DWORD z;
DWORD Resolution;
DWORD type;
DWORD ID;
diccid_t SourceID;
const void *buffer;
const char *Info;
const char *UserImageID;
};
to use the same in c# I have done marshaling but not giving proper values when converting the pointer to structure. The C# code is follows,
tBinary tBin = new tBinary();
IntPtr tBinbuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(tBin));
Marshal.StructureToPtr(tBin.bin, tBinbuffer, false);
tDeviceProperty tDevice = new tDeviceProperty();
tDevice.bin = tBinbuffer;
IntPtr tDevicebuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(tDevice));
Marshal.StructureToPtr(tDevice.bin, tDevicebuffer, false);
Battary tbatt = new Battary();
tbatt.value = tDevicebuffer;
IntPtr tbattbuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(tbatt));
Marshal.StructureToPtr(tbatt.value, tbattbuffer, false);
result = GetDeviceProperty(ref tbattbuffer);
Battary v = (Battary)Marshal.PtrToStructure(tbattbuffer, typeof(Battary));
tDeviceProperty v2 = (tDeviceProperty)Marshal.PtrToStructure(tDevicebuffer, typeof(tDeviceProperty));
tBinary v3 = (tBinary)Marshal.PtrToStructure(tBinbuffer, typeof(tBinary));
[StructLayout(LayoutKind.Explicit)]
public struct tDeviceProperty
{
[FieldOffset(0)]
[MarshalAs(UnmanagedType.U2)]
public ushort i;
[FieldOffset(2)]
[MarshalAs(UnmanagedType.I4)]
public int l;
[FieldOffset(6)]
[MarshalAs(UnmanagedType.U4)]
public uint ul;
[FieldOffset(10)]
[MarshalAs(UnmanagedType.R4)]
public float flt;
[FieldOffset(14)]
[MarshalAs(UnmanagedType.R8)]
public double dbl;
[FieldOffset(22)]
[MarshalAs(UnmanagedType.I4)]
public int b;
[FieldOffset(26)]
[MarshalAs(UnmanagedType.R8)]
public double at;
[FieldOffset(34)]
//[MarshalAs(UnmanagedType.Struct)]
public IntPtr ft;
[FieldOffset(42)]
//[MarshalAs(UnmanagedType.Struct)]
public IntPtr lpszA;
[FieldOffset(43)]
//[MarshalAs(UnmanagedType.Struct)]
public IntPtr lpszW;
[FieldOffset(45)]
[MarshalAs(UnmanagedType.U8)]
public ulong li;
[FieldOffset(53)]
[MarshalAs(UnmanagedType.Struct)]
public IntPtr bin;
[FieldOffset(61)]
//[MarshalAs(UnmanagedType.Struct)]
public IntPtr reserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct tBinary
{
public int size;
public IntPtr bin;
}
[StructLayout(LayoutKind.Sequential)]
public struct Battary
{
public uint Tag;
public uint Size;
public IntPtr value;
}
[StructLayout(LayoutKind.Sequential)]
public struct tDiccBatteryStatus
{
public uint RefreshWear;
public uint TotalWear;
public ushort Voltage;
public ushort Battery;
public int BatteryOK;
public int NeedRefresh;
public int NeedChange;
public ushort Temperature;
public int Charge;
public byte State;
public byte ExternalPowered;
public int CapacityLeft;
}
I think that the reason of the failure is the tDeviceProperty declaration. Infact, its member value is an union, but in the tDeviceProperty you apply constatly increasing offset, while they shall have the same value.
This is because the union members start at the same offset, sharing the same space of the other members. The size of the union is determines by the maximum size of the fields declared in the union.
Indeed, using your code:
[StructLayout(LayoutKind.Explicit, Size = )]
public struct tDeviceProperty
{
[FieldOffset(0)]
[MarshalAs(UnmanagedType.U2)]
public ushort i;
[FieldOffset(2)]
[MarshalAs(UnmanagedType.I4)]
public int l;
[FieldOffset(6)]
[MarshalAs(UnmanagedType.U4)]
public uint ul;
[FieldOffset(6)]
[MarshalAs(UnmanagedType.R4)]
public float flt;
[FieldOffset(6)]
[MarshalAs(UnmanagedType.R8)]
public double dbl;
[FieldOffset(6)]
[MarshalAs(UnmanagedType.I4)]
public int b;
[FieldOffset(6)]
[MarshalAs(UnmanagedType.R8)]
public double at;
[FieldOffset(6)]
//[MarshalAs(UnmanagedType.Struct)]
public IntPtr ft;
[FieldOffset(6)]
//[MarshalAs(UnmanagedType.Struct)]
public IntPtr lpszA;
[FieldOffset(6)]
//[MarshalAs(UnmanagedType.Struct)]
public IntPtr lpszW;
[FieldOffset(6)]
[MarshalAs(UnmanagedType.U8)]
public ulong li;
[FieldOffset(6)]
[MarshalAs(UnmanagedType.Struct)]
public IntPtr bin;
[FieldOffset(6)]
//[MarshalAs(UnmanagedType.Struct)]
public IntPtr reserved;
}
Check also my recent question/answer.
Related
I'm trying to map a bytearray in c#, which is of 56 bytes and the struct i got for it is like this in C
struct cequivalentstruct{
uint32_t Descriptor;
uint32_t Value;
uint32_t Minimum;
uint32_t Maximum;
uint32_t Default;
uint16_t Next;
uint16_t Previous;
char Units[4];
uint16_t Multiplier;
uint16_t Divisor;
uint16_t Base;
uint16_t Offset;
char Link[3];
char pad;
char Name[16];
}
and i have coverted that to
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct ParameterResponse
{
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public uint Descriptor;
[MarshalAs(UnmanagedType.I4, SizeConst = 4)]
public uint Value;
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public uint Minimum;
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public uint Maximum;
[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
public uint Default;
[MarshalAs(UnmanagedType.U4, SizeConst = 2)]
public uint Next;
[MarshalAs(UnmanagedType.U4, SizeConst = 2)]
public uint Previous;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public char[] Units;
[MarshalAs(UnmanagedType.U4, SizeConst = 2)]
public uint Multiplier;
[MarshalAs(UnmanagedType.U4, SizeConst = 2)]
public uint Divisor;
[MarshalAs(UnmanagedType.U4, SizeConst = 2)]
public uint Base;
[MarshalAs(UnmanagedType.U4, SizeConst = 2)]
public uint Offset;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public char[] Link;
[MarshalAs(UnmanagedType.U1, SizeConst = 1)]
public char pad;
[MarshalAs(UnmanagedType.ByValArray)]
public byte[] Name;
public ParameterResponse(uint descriptior, uint value, uint maximum, uint minimum, uint defaultvalue, uint next, uint previous,
char[] units, uint multiplier, uint divisor, uint baseValue, uint offset, char[] link, char padValue, byte[] name)
{
Descriptor = descriptior;
Value = value;
Maximum= maximum;
Minimum= minimum;
Default = defaultvalue;
Next= next; Previous= previous;
Units = units;
Multiplier = multiplier;
Divisor = divisor;
Base = baseValue; Offset = offset;
Link = link;
pad = padValue;
Name = name;
}
}
}
I'm not sure if I'm missing something in this, because when I try to convert my byteArray to this struct, but the struct is not exactly taking the appropriate sizeconst defined, any inputs would be helpful.
Try this.
uint16_t should map to ushort, char should map to byte or sbyte, The Name field need a SizeConst attribute, Using the default pack size.
[StructLayout(LayoutKind.Sequential)]
public struct ParameterResponse
{
public uint Descriptor;
public uint Value;
public uint Minimum;
public uint Maximum;
public uint Default;
public ushort Next;
public ushort Previous;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] Units;
public ushort Multiplier;
public ushort Divisor;
public ushort Base;
public ushort Offset;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] Link;
public byte pad;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] Name;
}
I am using NVAPI.dll to change gpu's core clock. using NvAPI_GPU_SetPstates20 function in nvapi.dll
The struct in C# for nvapi.dll is this:
[StructLayout(LayoutKind.Explicit, Pack = 8)]
internal struct dataStruct
{
[FieldOffset(0)]
public singleStruct single;
[FieldOffset(0)]
public rangeStruct range;
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal struct valuerange
{
public int min;
public int max;
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal struct NV_GPU_PSTATE20_BASE_VOLTAGE_ENTRY
{
public uint domainId;
public uint editable;//1
public uint reserved;//31
public uint voltageUV;
public NV_GPU_PERF_PSTATES20_PARAM_DELTA voltageDeltaUV;
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal struct NV_GPU_PERF_PSTATES20_PARAM_DELTA
{
public int value;
public valuerange valueRanges;
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal struct pstateStruct
{
public uint pStateId;
public uint editable;//1
public uint reserved;//31
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public NV_GPU_PSTATE20_CLOCK_ENTRY[]clocks;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public NV_GPU_PSTATE20_BASE_VOLTAGE_ENTRY[]baseVoltages;
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal struct singleStruct
{
public uint frequencyKHz;
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal struct rangeStruct
{
public uint minFrequencyKHz;
public uint maxFrequencyKHz;
public uint domainId;
public uint minVoltageUV;
public uint maxVoltageUV;
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal struct overVoltageStruct
{
public uint numVoltages;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public NV_GPU_PSTATE20_BASE_VOLTAGE_ENTRY []voltages;//[4]
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal struct NV_GPU_PSTATE20_CLOCK_ENTRY
{
public uint domainId;
public uint typeId;
public uint editable;//1
public uint reserved;//31
public NV_GPU_PERF_PSTATES20_PARAM_DELTA frequencyDeltaKHz;
public dataStruct data;
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal struct NV_GPU_PERF_PSTATES20_INFO
{
public uint version;
public uint editable;//1
public uint reserved;//31
public uint numPStates;
public uint numClocks;
public uint numBaseVoltages;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public pstateStruct[] pStates;
public overVoltageStruct overVoltage;
}
This is my function:
public static void SetCoreClock(NvPhysicalGpuHandle handle,int clock)
{
NV_GPU_PERF_PSTATES20_INFO pStatesInfo=new NV_GPU_PERF_PSTATES20_INFO();
pStatesInfo.version = (uint) Marshal.SizeOf(typeof(NV_GPU_PERF_PSTATES20_INFO)) | 0x10000;
pStatesInfo.numPStates = 1;
pStatesInfo.numClocks = 1;
pStatesInfo.editable = 1;
pStatesInfo.reserved = 31;
pStatesInfo.pStates = new pstateStruct[16];
pStatesInfo.overVoltage.voltages = new NV_GPU_PSTATE20_BASE_VOLTAGE_ENTRY[4];
pStatesInfo.pStates[0].baseVoltages = new NV_GPU_PSTATE20_BASE_VOLTAGE_ENTRY[4];
pStatesInfo.pStates[0].clocks = new NV_GPU_PSTATE20_CLOCK_ENTRY[8];
pStatesInfo.pStates[0].clocks[0].editable = 1;
pStatesInfo.pStates[0].clocks[0].reserved = 31;
pStatesInfo.pStates[0].pStateId = 0;
pStatesInfo.pStates[0].clocks[0].domainId = 0;
pStatesInfo.pStates[0].clocks[0].typeId = 0;
pStatesInfo.pStates[0].clocks[0].frequencyDeltaKHz.value = clock;
pStatesInfo.pStates[0].clocks[0].frequencyDeltaKHz.valueRanges.max = 0;
pStatesInfo.pStates[0].clocks[0].frequencyDeltaKHz.valueRanges.min = 0;
a = NVAPI.NvAPI_GPU_SetPstates20(handle,ref pStatesInfo);
}
when I run the function "SetCoreClock". The value a return "INCOMPATIBLE_STRUCT_VERSION".
Is my struct wrong?
I found a C++ code. the code's struct is:
struct NV_GPU_PERF_PSTATES20_PARAM_DELTA
{
int value;
struct
{
int min;
int max;
} valueRange;
};
struct NV_GPU_PSTATE20_BASE_VOLTAGE_ENTRY
{
unsigned int domainId;
unsigned int editable : 1;
unsigned int reserved : 31;
unsigned int voltageUV;
NV_GPU_PERF_PSTATES20_PARAM_DELTA voltageDeltaUV;
};
struct NV_GPU_PSTATE20_CLOCK_ENTRY
{
unsigned int domainId;
unsigned int typeId;
unsigned int editable : 1;
unsigned int reserved : 31;
NV_GPU_PERF_PSTATES20_PARAM_DELTA frequencyDeltaKHz;
union
{
struct
{
unsigned int frequencyKHz;
} single;
struct
{
unsigned int minFrequencyKHz;
unsigned int maxFrequencyKHz;
unsigned int domainId;
unsigned int minVoltageUV;
unsigned int maxVoltageUV;
} range;
} data;
};
struct NV_GPU_PERF_PSTATES20_INFO
{
unsigned int version;
unsigned int editable : 1;
unsigned int reserved : 31;
unsigned int numPStates;
unsigned int numClocks;
unsigned int numBaseVoltages;
struct
{
unsigned int pStateId;
unsigned int editable : 1;
unsigned int reserved : 31;
NV_GPU_PSTATE20_CLOCK_ENTRY clocks[8];
NV_GPU_PSTATE20_BASE_VOLTAGE_ENTRY baseVoltages[4];
} pStates[16];
struct
{
unsigned int numVoltages;
NV_GPU_PSTATE20_BASE_VOLTAGE_ENTRY voltages[4];
} overVoltage;
};```
Thanks for helping me solved the problem.
it means you have the struct the incorrect size. a example I found said the version should be 0x11c94. things like reserved IMHO need to be removed. I had same issue and I did this to find the version:
uint GPUVER3 = (uint)Marshal.SizeOf(typeof(NV_GPU_PERF_PSTATES20_INFO_V1)) | 0x20000;
Once you get the version the same as 0x11c94 it should work.
C code I used to work this out
https://github.com/suppai/nvidia-overclock
i have some complex structure in c++
typedef struct
{
long Length;
short Type;
union
{
MMTPConxReq ConxReq;
MMTPConxAck ConxAck;
MMTPConxNack ConxNack;
MMTPErrInd ErrInd;
MMTPDcnxReq DcnxReq;
MMTPDcnxAck DcnxAck;
MMTPDataMsg DataMsg;
MMTPSyncAck SyncAck;
MMTPStartReq StartReq;
MMTPStartAck StartAck;
MMTPStartNack StartNack;
MMTPSrvcMsg SrvcMsg;
MMTPDsptchMsg DsptchMsg;
MMTPRcnxReq RcnxReq;
} Data;
Ticks TimeStamp;
} MMTPMsg;
typedef struct
{
char SubsId[FIELD_SIZE_SUBS_ID+1];
int Level;
char Options[FIELD_SIZE_OPTIONS+1];
char AuthData[FIELD_SIZE_AUTH_DATA+1];
} MMTPConxReq;
// Contents of CONX-ACK message.
typedef struct
{
char Options[FIELD_SIZE_OPTIONS+1];
} MMTPConxAck;
// Contents of DATA-MSG message.
typedef struct
{
int SeqNb;
int DataSize;
MMTPAdminData AD;
char Data[FIELD_SIZE_DATA+1];
} MMTPDataMsg;
// Administrative data.
typedef struct
{
int Type;
int Size;
union
{
MMTPAdminDataA1 A1;
MMTPAdminDataA2 A2;
MMTPAdminDataE0 E0;
MMTPAdminDataE1 E1;
MMTPAdminDataG0 G0;
MMTPAdminDataM0 M0;
MMTPAdminDataRR RR;
MMTPAdminGeneric Generic;
} Data;
char Unknown[FIELD_SIZE_ADMIN];
} MMTPAdminData;
in conver to c# (step to step) i create this structs:
[StructLayout(LayoutKind.Sequential)]
internal struct MMTPMsg
{
public Int32 Length;
public MessageType Type;
//[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10060)]
//public fixed byte Data[10060];
public MMTPMsgData Data;
public Int64 TimeStamp;
}
[StructLayout(LayoutKind.Explicit)]//,Size =10060)]
internal struct MMTPMsgData
{
[FieldOffset(0)]
public MMTPConxReq ConxReq;//12+4+17+9
[FieldOffset(0)]
public MMTPConxAck ConxAck;//17
//[FieldOffset(0)]
//public MMTPConxNack ConxNack;//e
//[FieldOffset(0)]
//public MMTPErrInd ErrInd;//e+4+4+4+(9500+256+24+1)
//[FieldOffset(0)]
//public MMTPDcnxReq DcnxReq;//e+4
//[FieldOffset(0)]
//public MMTPDcnxAck DcnxAck;//4
[FieldOffset(0)]
public MMTPDataMsg DataMsg;//4+4+(4+4+()+256)+9501
//[FieldOffset(0)]
//public MMTPSyncAck SyncAck;
//[FieldOffset(0)]
//public MMTPStartReq StartReq;
[FieldOffset(0)]
public MMTPStartAck StartAck;
//[FieldOffset(0)]
//public MMTPStartNack StartNack;
//[FieldOffset(0)]
//public MMTPSrvcMsg SrvcMsg;
//[FieldOffset(0)]
//public MMTPDsptchMsg DsptchMsg;
//[FieldOffset(0)]
//public MMTPRcnxReq RcnxReq;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]//, CharSet = CharSet.Ansi)]
unsafe internal struct MMTPConxReq
{
public fixed byte SubsId[Constants.FIELD_SIZE_SUBS_ID + 1];
public int Level;
public fixed byte Options[Constants.FIELD_SIZE_OPTIONS + 1];
public fixed byte AuthData[Constants.FIELD_SIZE_AUTH_DATA + 1];
}
internal struct MMTPConxAck
{
//[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.FIELD_SIZE_OPTIONS + 1)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.FIELD_SIZE_OPTIONS + 1)]
public string Options;//[Constants.FIELD_SIZE_OPTIONS + 1];
}
internal struct MMTPDataMsg
{
public int SeqNb;
public int DataSize;
public MMTPAdminData AD;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = Constants.FIELD_SIZE_DATA + 1)]
public byte[] Data;
}
when run the c# app, i get this error
System.TypeLoadException: 'Could not load type 'TestSle.MMTPMsgData' from assembly 'TestSle, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because it contains an object field at offset 0 that is incorrectly aligned or overlapped by a non-object field.'
if i comment
this line from MMTPMsgData struct:
[FieldOffset(0)]
public MMTPConxReq ConxReq;//12+4+17+9
no error happen but i need this data.
what is wrong
i can not understand problem
help me please
I have been trying to convert this struct to C# for the last couple of days, but to no avail...
https://msdn.microsoft.com/en-us/library/windows/desktop/bb736369(v=vs.85).aspx
typedef struct _WTSCLIENT {
TCHAR ClientName[CLIENTNAME_LENGTH + 1];
TCHAR Domain[DOMAIN_LENGTH + 1 ];
TCHAR UserName[USERNAME_LENGTH + 1];
TCHAR WorkDirectory[MAX_PATH + 1];
TCHAR InitialProgram[MAX_PATH + 1];
BYTE EncryptionLevel;
ULONG ClientAddressFamily;
USHORT ClientAddress[CLIENTADDRESS_LENGTH + 1];
USHORT HRes;
USHORT VRes;
USHORT ColorDepth;
TCHAR ClientDirectory[MAX_PATH + 1];
ULONG ClientBuildNumber;
ULONG ClientHardwareId;
USHORT ClientProductId;
USHORT OutBufCountHost;
USHORT OutBufCountClient;
USHORT OutBufLength;
TCHAR DeviceId[MAX_PATH + 1];
} WTSCLIENT, *PWTSCLIENT;
This is my attempt so far:
[StructLayout( LayoutKind.Sequential )]
public struct _WTSCLIENT {
[MarshalAs( UnmanagedType.LPTStr )]
public String ClientName;
[MarshalAs( UnmanagedType.LPTStr )]
public String Domain;
[MarshalAs( UnmanagedType.LPTStr )]
public String UserName;
[MarshalAs( UnmanagedType.LPTStr )]
public String WorkDirectory;
[MarshalAs( UnmanagedType.LPTStr )]
public String InitialProgram;
public Byte EncryptionLevel;
public uint ClientAddressFamily;
[MarshalAsAttribute( UnmanagedType.ByValArray)]
public byte[] ClientAddress;
public ushort HRes;
public ushort VRes;
public ushort ColorDepth;
[MarshalAs( UnmanagedType.LPTStr )]
public String ClientDirectory;
public uint ClientBuildNumber;
public uint ClientHardwareId;
public ushort ClientProductId;
public ushort OutBufCountHost;
public ushort OutBufCountClient;
public ushort OutBufLength;
[MarshalAs( UnmanagedType.LPTStr )]
public String DeviceId;
}
I use it like this:
WTSQuerySessionInformation( serverHandle, si.SessionID, WTS_INFO_CLASS.WTSClientInfo, out clientInfoPtr, out bytes );
clientInfo = (_WTSCLIENT)Marshal.PtrToStructure( clientInfoPtr, typeof( _WTSCLIENT ) );
...but it bombs out silently, so obviously I have not matched the structure...
Can anyone help me with the struct conversion to C#
TIA...
--
Dag.
Try
[StructLayout(LayoutKind.Sequential)]
public struct WTSCLIENT
{
private const int CLIENTNAME_LENGTH = 20;
private const int DOMAIN_LENGTH = 17;
private const int USERNAME_LENGTH = 20;
private const int MAX_PATH = 260;
private const int CLIENTADDRESS_LENGTH = 30;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CLIENTNAME_LENGTH + 1)]
public string ClientName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = DOMAIN_LENGTH + 1)]
public string Domain;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = USERNAME_LENGTH + 1)]
public string UserName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
public string WorkDirectory;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
public string InitialProgram;
public byte EncryptionLevel;
public uint ClientAddressFamily;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = CLIENTADDRESS_LENGTH + 1)]
public ushort[] ClientAddress;
public ushort HRes;
public ushort VRes;
public ushort ColorDepth;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
public string ClientDirectory;
public uint ClientBuildNumber;
public uint ClientHardwareId;
public ushort ClientProductId;
public ushort OutBufCountHost;
public ushort OutBufCountClient;
public ushort OutBufLength;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
public string DeviceId;
}
It should work. Its Marshal.SizeOf is the "right" one, both at 32 and 64 bits, both Ansi and Unicode.
If you are using the Unicode version of the methods change the first line to:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
You could try the P/Invoke Interop Assistant
For your ULONG ClientBuildNumber; and all other ULONG s in C++, you have used the C# type uint. It could be an error that your definition of ULONG is a different size than uint.
Maybe you can try using ulong in C# (unsigned 64-bit, 0 to 18,446,744,073,709,551,615). This should match the standard Microsoft C++ ULONG definition.
MSDN C++
MSDN C# ulong
I am able to send special keys on local machine but the same thing is not working on remote machine. I referred to many articles but could not find the code to send special keys to remote desktop connection. Please help on this. Below is the code.
static void Main(string[] args)
{
Thread.Sleep(3000);
//char[] keyboardStrokes = { (char)Keys.LWin, (char)Keys.R };
char[] keyboardStrokes = { (char)Keys.LMenu, (char)Keys.F4 };
SendData(keyboardStrokes);
}
struct INPUT
{
public INPUTType type;
public INPUTUnion Event;
}
[StructLayout(LayoutKind.Explicit)]
struct INPUTUnion
{
[FieldOffset(0)]
internal MOUSEINPUT mi;
[FieldOffset(0)]
internal KEYBDINPUT ki;
[FieldOffset(0)]
internal HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT
{
public int dx;
public int dy;
public int mouseData;
public int dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT
{
public short wVk;
public short wScan;
public KEYEVENTF dwFlags;
public int time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
public int uMsg;
public short wParamL;
public short wParamH;
}
enum INPUTType : uint
{
INPUT_KEYBOARD = 1
}
[Flags]
enum KEYEVENTF : uint
{
EXTENDEDKEY = 0x0001,
KEYUP = 0x0002,
SCANCODE = 0x0008,
UNICODE = 0x0004
}
[DllImport("user32.dll", SetLastError = true)]
static extern UInt32 SendInput(int numberOfInputs, INPUT[] inputs, int sizeOfInputStructure);
[DllImport("user32.dll")]
static extern IntPtr GetMessageExtraInfo();
private static void SendData(char[] c)
{
ProcessKey(c);
}
private static void ProcessKey(char[] key)
{
// create input events as unicode with first down, then up
INPUT[] inputs = new INPUT[key.Length + 1];
for (int i = 0; i < key.Length; i++)
{
inputs[i].type = INPUTType.INPUT_KEYBOARD;
inputs[i].Event.ki.dwFlags = KEYEVENTF.UNICODE;
inputs[i].Event.ki.wScan = (short)key[i];
inputs[i].Event.ki.wVk = (short)key[i];
}
//Thread.Sleep(3000);
inputs[key.Length].type = INPUTType.INPUT_KEYBOARD;
inputs[key.Length].Event.ki.dwFlags = KEYEVENTF.KEYUP;
inputs[key.Length].Event.ki.dwExtraInfo = GetMessageExtraInfo();
// inputs[key.Length].Event.ki.wScan =
// inputs[key.Length].Event.ki.dwFlags |= KEYEVENTF.KEYUP;
uint cSuccess = SendInput(inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));
if (cSuccess != inputs.Length)
{
throw new Win32Exception();
}
}
Thanks in advance.
Finally I am able to send most of the special keys to remote machine by using following code. The only issue is that special keys remain pressed after the operation is completed. please let me know how to release the special keys.
class Program
{
static void Main(string[] args)
{
Thread.Sleep(3000);
int[] keyboardStrokes = { (int)Keys.LMenu, (int)Keys.Tab, (int)Keys.Tab };
ProcessKey(keyboardStrokes);
Console.Read();
}
struct INPUT
{
public INPUTType type;
public INPUTUnion Event;
}
[StructLayout(LayoutKind.Explicit)]
struct INPUTUnion
{
[FieldOffset(0)]
internal MOUSEINPUT mi;
[FieldOffset(0)]
internal KEYBDINPUT ki;
[FieldOffset(0)]
internal HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT
{
public int dx;
public int dy;
public int mouseData;
public int dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public KEYEVENTF dwFlags;
public int time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
public int uMsg;
public short wParamL;
public short wParamH;
}
enum INPUTType : uint
{
INPUT_KEYBOARD = 1
}
[Flags]
enum KEYEVENTF : uint
{
EXTENDEDKEY = 0x0001,
KEYUP = 0x0002,
SCANCODE = 0x0008,
UNICODE = 0x0004
}
[DllImport("user32.dll", SetLastError = true)]
static extern UInt32 SendInput(int numberOfInputs, INPUT[] inputs, int sizeOfInputStructure);
[System.Runtime.InteropServices.DllImport("user32.dll")]
internal static extern uint MapVirtualKey(uint uCode, uint uMapType);
private static void ProcessKey(int[] key)
{
INPUT[] inputs = new INPUT[key.Length + 1];
for (int i = 0; i < key.Length; i++)
{
uint skey = MapVirtualKey((uint)key[i], (uint)0x0);
inputs[i].type = INPUTType.INPUT_KEYBOARD;
inputs[i].Event.ki.dwFlags = KEYEVENTF.SCANCODE;
inputs[i].Event.ki.wScan = (ushort)skey;
}
inputs[key.Length].type = INPUTType.INPUT_KEYBOARD;
inputs[key.Length].Event.ki.dwFlags = KEYEVENTF.UNICODE;
inputs[key.Length].Event.ki.dwFlags |= KEYEVENTF.KEYUP;
uint cSuccess = SendInput(inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));
}
}