2015-02-08 2 views
-1

Я пытаюсь pInvoke метод C в 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); 

Пожалуйста, помогите, Спасибо

+0

Вам нужно построить строковый построитель с явным размером. Возможно, это не ваша проблема, но это уже укусило меня в тылу. – BlamKiwi

+0

@Morphing, что не поможет, потому что буфер не является строкой, а pinvoke полностью ошибочен –

ответ

2

Your 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

Спасибо :) отлично, все это работает после небольшого твита на вашем предоставленном коде. –

Смежные вопросы