pInvoke in c#(托管代码)

pInvoke in c# (Managed code)

本文关键字:托管代码 in pInvoke      更新时间:2023-10-16

我试图在C#中调用一个C方法,但它给出了错误;尝试读取或写入受保护的内存。这通常表示其他内存已损坏。

C方法;

HRESULT FilterVolumeInstanceFindFirst(
_In_   LPCWSTR lpVolumeName,
_In_   INSTANCE_INFORMATION_CLASS dwInformationClass,
_Out_  LPVOID lpBuffer,
_In_   DWORD dwBufferSize,
_Out_  LPDWORD lpBytesReturned,
_Out_  LPHANDLE lpVolumeInstanceFind
);
typedef struct _INSTANCE_BASIC_INFORMATION {
ULONG  NextEntryOffset;
USHORT InstanceNameLength;
USHORT InstanceNameBufferOffset;
} INSTANCE_BASIC_INFORMATION, *PINSTANCE_BASIC_INFORMATION;

这是我的代码

  [DllImport("FltLib", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto)]
    public static extern int FilterVolumeInstanceFindFirst([MarshalAs(UnmanagedType.LPWStr)]           
        string lpVolumeName,
        _INSTANCE_BASIC_INFORMATION dwInformationClass,
       // IntPtr dwInformationClass,
        out StringBuilder lpBuffer,
        int dwBufferSize,
        out UInt32 lpBytesReturned,
        ref IntPtr lpVolumeInstanceFind);

[StructLayout(LayoutKind.Sequential)]
public struct _INSTANCE_BASIC_INFORMATION
{
    public uint NextEntryOffset;
    public uint InstanceNameLength;
    public uint InstanceNameBufferOffset;
}

调用代码为;

_INSTANCE_BASIC_INFORMATION ins = new _INSTANCE_BASIC_INFORMATION();
            StringBuilder sb1 = new StringBuilder();
            uint ret = 512;
            IntPtr vol = new IntPtr(100);
            int res = FilterVolumeInstanceFindFirst("H:", ins, out sb1, 516, out ret, ref vol);

请帮忙,感谢

您的p/invoke翻译是错误的。你的结构中有错误的类型。应该是:

[StructLayout(LayoutKind.Sequential)]
public struct INSTANCE_BASIC_INFORMATION
{
    public uint NextEntryOffset;
    public ushort InstanceNameLength;
    public ushort InstanceNameBufferOffset;
}

功能本身也有点偏离。它应该是:

[DllImport("FltLib")]
public static extern uint FilterVolumeInstanceFindFirst(
    [MarshalAs(UnmanagedType.LPWStr)]           
    string lpVolumeName,
    uint dwInformationClass,
    out INSTANCE_BASIC_INFORMATION lpBuffer,
    uint dwBufferSize,
    out uint lpBytesReturned,
    out IntPtr lpVolumeInstanceFind
);

信息类实际上是一个枚举。在相应的头文件中查找其值。快速网络搜索表明InstanceBasicInformation的值为0。不过,请查阅头文件,亲自检查一下。将结构的大小作为dwBufferSize传递。

电话应该是这样的:

INSTANCE_BASIC_INFORMATION basicInfo;
uint bytesReturned;
IntPtr volumeInstanceFind;
uint res = FilterVolumeInstanceFindFirst("H:", InstanceBasicInformation,
    out basicInfo, (uint)Marshal.SizeOf(typeof(INSTANCE_BASIC_INFORMATION)), 
    out bytesReturned, volumeInstanceFind);

这些翻译总是通过首先编写C++代码来完成的。然后,您就知道什么是正确的调用序列,而不会被错误的p/invoke转换所混淆。