2015-02-08 42 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