c# 中的 pInvoke(托管代码)

pInvoke in c# (Managed code)

我正在尝试在 C# 中 pInvoke 一个 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
);

信息class实际上是一个枚举。在相应的头文件中查找它的值。快速网络搜索表明 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 翻译所混淆。