2015-02-08 38 views
-1

我想在c#中调用一个C方法,但它给出了错误; 试图读取或写入受保护的内存。这通常表明其他内存已损坏。在c#中的pInvoke(托管代码)

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); 

请帮帮忙,谢谢

+0

您需要构建具有显式大小的字符串生成器。这可能不是你的问题,但这让我后退了。 – BlamKiwi 2015-02-09 00:24:54

+0

@Morphing这将无济于事,因为缓冲区不是字符串,并且pinvoke是完全错误的 – 2015-02-09 14:40:59

回答

2

您的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翻译混淆。

+0

谢谢:)太棒了,它的所有工作都是在您提供的代码上稍微鸣叫一下。 – 2015-02-12 17:09:35