如何在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); }