c# – Pinvoke DeviceIoControl参数

前端之家收集整理的这篇文章主要介绍了c# – Pinvoke DeviceIoControl参数前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用 DeviceIoControl的C#项目工作.我已经咨询了相关的 Pinvoke.net page作为我的签名:
[DllImport("Kernel32.dll",SetLastError = false,CharSet = CharSet.Auto)]
public static extern bool DeviceIoControl(
    SafeFileHandle hDevice,EIOControlCode IoControlCode,[MarshalAs(UnmanagedType.AsAny)]
    [In] object InBuffer,uint nInBufferSize,[MarshalAs(UnmanagedType.AsAny)]
    [Out] object OutBuffer,uint nOutBufferSize,out uint pBytesReturned,[In] IntPtr Overlapped
    );

以前我从来没有看到对象和[MarshalAs(UnmanagedType.AsAny)],但MSDN documentation听起来很有希望:

A dynamic type that determines the type of an object at run time and marshals the object as that type. This member is valid for platform invoke methods only.

我的问题是:使用此签名的“最佳”和/或“适当”方式是什么?

例如,IOCTL_STORAGE_QUERY_PROPERTY希望InBuffer成为一个STORAGE_PROPERTY_QUERY的结构.似乎我应该能够定义该结构,创建一个新的实例,并将其传递给我的Pinvoke签名:

var query = new STORAGE_PROPERTY_QUERY { PropertyId = 0,QueryType = 0 };
DeviceIoControl(...,query,Marshal.SizeOf(query),...);

但是,我刚刚得到一个System.ExecutionEngineException这样做,所以我改成如下:

int cb = Marshal.SizeOf(typeof(...));
IntPtr query = Marshal.AllocHGlobal(cb);
...
Marshal.PtrToStructure(...);
Marshal.FreeHGlobal(query);

当我打电话时,它至少没有抛出任何异常.那只是非常丑陋,而且对屁股的痛苦很大.处理器不能处理将数据复制到/从我的本地结构体,如我所希望的?

输出数据有时会很棘手,因为它们不是固定大小的结构.我知道编组者不能自动处理,我可以在做HGlobal并复制我需要的业务.

额外:

起初This question看起来很有帮助,但最终只是一个不正确的常数.

我不反对使用不安全的构造. (固定大小的struct成员需要这个.)

解决方法

DeviceIoControl是非常不友好的.但是你可以减少痛苦,你不必自己组织结构.你可以利用两件事情:C#支持方法重载,而pinvoke marshaller会相信你,即使你对这个声明说谎了.这对于结构是完美的,它们已经被封送成一串字节.什么DeviceIoControl()需要.

所以一般声明如下所示:

[DllImport("Kernel32.dll",SetLastError = true)]
public static extern bool DeviceIoControl(
    SafeFileHandle hDevice,int IoControlCode,byte[] InBuffer,int nInBufferSize,byte[] OutBuffer,int nOutBufferSize,out int pBytesReturned,IntPtr Overlapped
);

而且您会添加一个非常适合IOCTL_STORAGE_QUERY_PROPERTY的重载,假设您有兴趣返回STORAGE_DEVICE_DESCRIPTOR:

[DllImport("Kernel32.dll",ref STORAGE_PROPERTY_QUERY InBuffer,out STORAGE_DEVICE_DESCRIPTOR OutBuffer,IntPtr Overlapped
);

你会这样称呼:

var query = new STORAGE_PROPERTY_QUERY { PropertyId = 0,QueryType = 0 };
var qsize = Marshal.SizeOf(query);
STORAGE_DEVICE_DESCRIPTOR result;
var rsize = Marshal.SizeOf(result);
int written;
bool ok = DeviceIoControl(handle,EIOControlCode.QueryProperty,ref query,qsize,out result,rsize,out written,IntPtr.Zero);
if (!ok) throw new Win32Exception();
if (written != rsize) throw new InvalidOperationException("Bad structure declaration");

哪个应该比你所拥有的更漂亮,更可诊断.未经测试,应该很接近.

原文链接:https://www.f2er.com/csharp/93991.html

猜你在找的C#相关文章