如何在WINCE7 C#.net中将结构指针发送到DeviceIoControl API
我正在使用WIN CE平台,在C#.Net中开发Windows窗体。
DeviceIoControl API可以正常使用c ++控制台应用程序中的参数(如下所述)。
nuiouser.h中的PNIC_STATISTICS结构
global declarations : TCHAR PCI1_NAME[] = _T("PCI\\ManiXX1"); TCHAR *AUB_NAME = NULL; AUB_NAME = PCI1_NAME; pNICStat = (PNIC_STATISTICS)malloc(sizeof(NIC_STATISTICS)) ; pNICStat->ptcDeviceName = AUB_NAME ; //wchar_t* ptcDeviceName DeviceIoControl( hUB94Port, //void* IOCTL_NDISUIO_NIC_STATISTICS, pNICStat, //PNIC_STATISTICS 0, pNICStat, //PNIC_STATISTICS sizeof(NIC_STATISTICS), &dwReturnedBytes, NULL );
但是我在使用C#.Net CF为WIN-CE7实现相同的问题
我的WIN-CE代码如下:
C#中的修改结构:
[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Unicode)] public struct __NIC_STAT { ulong Size; // Of this structure. public Char[] ptcDeviceName; // The device name to be queried.. ulong DeviceState; // DEVICE_STATE_XXX above ulong DeviceState; // DEVICE_STATE_XXX above ulong MediaType; // NdisMediumXXX ulong MediaState; // MEDIA_STATE_XXX above ulong PhysicalMediaType; ulong LinkSpeed; // In 100bits/s. 10Mb/s = 100000 UInt64 PacketsSent; UInt64 PacketsReceived; ulong InitTime; // In milliseconds ulong ConnectTime; // In seconds UInt64 BytesSent; // 0 - Unknown (or not supported) UInt64 BytesReceived; // 0 - Unknown (or not supported) UInt64 DirectedBytesReceived; UInt64 DirectedPacketsReceived; ulong PacketsReceiveErrors; ulong PacketsSendErrors; ulong ResetCount; ulong MediaSenseConnectCount; ulong MediaSenseDisconnectCount; } ;
从这个结构我只是填充ptcDeviceName并尝试发送。
__NIC_STAT NIC_STAT = new __NIC_STAT(); Char[] toBytes = {'P','C','I','\\','M','a','n','i','X','X','1','\0'} NIC_STAT.ptcDeviceName = toBytes; //public Char[] ptcDeviceName; in structure // __NIC_STAT this is the same structure as //in nuiouser.h int sz = Marshal.SizeOf(NIC_STAT.GetType());//sometimes Getting exception here intptr ptr = Marshal.AllocHGlobal(sz); Marshal.StructureToPtr((__NIC_STAT)NIC_STAT, ptr, false); unsafe { DeviceIoControl(hFileHandle, IOCTL_NDISUIO_NIC_STATISTICS, ref ptr, 0, ref ptr, sz, ref dwReturnedBytes, 0); }//unsafe
这是相应的原型
[DllImport("coredll.dll", CharSet = CharSet.Auto, SetLastError = true)] unsafe public static extern bool DeviceIoControl( int hDevice, int dwIoControlCode, ref intptr InBuffer, int nInBufferSize, ref intptr OutBuffer, int nOutputBufferSize, ref int pBytesReturned, int pOverlapped );
在Win-CE中,DeviceIoControl()失败,exception并且不显示任何错误代码。 有时会将错误代码设为87(无效参数)。
我觉得ptcDeviceName正在创建问题,或者可能是因为为指针(ptr)分配内存?
在控制台应用程序中,我们将ptcDeviceName作为Wchar_t *发送,但在WIN-CE中,所以我使用了
public Char[] ptcDeviceName;
谁能告诉我我做错了什么?
你有几个问题在这里发生。
首先,你似乎认为在C#中ulong
是32位,但事实并非如此。 它是64位,所以你的结构完全映射错误。
其次,我确定你需要在将结构Size
成员传递给调用之前设置它。
第三,该ptcDeviceName
成员是指向宽字符串的指针。 这意味着在结构本身中它是4个字节。 我可能会把它变成IntPtr
。 然后,您需要单独分配字符串,将其固定,并将指针指向该成员插槽。 由于`StringToHGlobal在CF中不存在,它看起来像这样:
public struct __NIC_STAT { public uint Size; public IntPtr ptcDeviceName; public uint DeviceState; public uint DeviceState; public uint MediaType; public uint MediaState; public uint PhysicalMediaType; public uint LinkSpeed; public ulong PacketsSent; public ulong PacketsReceived; public uint InitTime; public uint ConnectTime; public ulong BytesSent; public ulong BytesReceived; public ulong DirectedBytesReceived; public ulong DirectedPacketsReceived; public uint PacketsReceiveErrors; public uint PacketsSendErrors; public uint ResetCount; public uint MediaSenseConnectCount; public uint MediaSenseDisconnectCount; }; .... var myStruct = new __NIC_STAT(); myStruct.Size = (15 * 4) + (6 * 8); var name = "PCI\\Manixx1\0"; var nameBytes = Encoding.Unicode.GetBytes(name); myStruct.ptcDeviceName = Marshal.AllocHGlobal(nameBytes.Length); try { Marshal.Copy(nameBytes, 0, myStruct.ptcDeviceName, nameBytes.Length); // make the IOCTL call, a-la NativeMethods.DeviceIoControl(...., ref myStruct, ....); } finally { Marshal.FreeHGlobal(myStruct.ptcDeviceName); }