64-битная Windows 7 и доступ к вызовам Win32 API через проблемы P / Invoke и Marshal - PullRequest
5 голосов
/ 24 августа 2011

Я относительно новичок в .net / C # (хотя и очень опытен в Win32 / MFC и других платформах) и мне нужно написать утилиту для общения с пользовательским USB HID-устройством.Протокол довольно прост, и у меня уже есть рабочая утилита, написанная на MFC, но я бы предпочел написать утилиту на .Net / C #, так как я пытаюсь идти в ногу со временем и оставить MFC позади.

Я провел некоторое исследование и наткнулся на эту статью, которая, кажется, помогла мне понять, как получить доступ к HID-устройствам из .Net / C #, тем более что он просто вызывает вызовы Win32 API, с которыми я уже знаком:

http://www.developerfusion.com/article/84338/making-usb-c-friendly/

Приведенный пример кода дал мне отличное представление о том, как получить доступ к вызовам Win32 API для общения с USB-устройством (как это делал мой предыдущий код MFC), и все это прекрасно работает в 32-битной установке.Windows Vista или 7, но когда я пытаюсь запустить тот же код на 64-битной установке, это не удается.Даже если я попытаюсь создать выделенное 64-битное приложение, оно все равно не получится.

Я почти уверен, что проблема в том, как маршал передает параметры (в стеке?) В Win32 API, но мои знанияи опыт .Net / C # на данном этапе не достаточно хорош, чтобы точно понять, в чем проблема и как ее решить - проблема, вероятно, более продвинута, чем уровень, на котором я сейчас нахожусь.

Кажется, всеработать нормально в коде, пока я не достигну инструкции ...

while (SetupDiEnumDeviceInterfaces(hInfoSet, 0, ref gHid, (uint)nIndex, ref oInterface))    // this gets the device interface information for a device at index 'nIndex' in the memory block

Где SetupDI ... возвращает значение true в 32-разрядных системах, а затем повторяет все подключенные устройства USB, но возвращает значение false в 64-разрядныхсистемы.Я почти уверен, что это может быть проблемой с передачей параметров в функцию Win32 API, но я не понимаю, в чем именно заключается проблема.Определение DLLImport для этой функции:

[DllImport("setupapi.dll", SetLastError = true)] protected static extern bool SetupDiEnumDeviceInterfaces(IntPtr lpDeviceInfoSet, uint nDeviceInfoData, ref Guid gClass, uint nIndex, ref DeviceInterfaceData oInterfaceData);

Интересно, кто-нибудь может подсказать, что может быть нарушающим параметром и как я могу это исправить?

Заранее спасибо за любую помощьпредлагается, если требуется дополнительная информация, пожалуйста, попросите об этом!Рич

Ответы [ 2 ]

5 голосов
/ 24 августа 2011

С MSDN :

BOOL SetupDiEnumDeviceInterfaces(
  __in      HDEVINFO DeviceInfoSet,
  <b>__in_opt  PSP_DEVINFO_DATA DeviceInfoData,</b>
  __in      const GUID *InterfaceClassGuid,
  __in      DWORD MemberIndex,
  __out     PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
);
DeviceInfoData [in, необязательно]
Указатель на структуру SP_DEVINFO_DATA ...

Обратите внимание, что DeviceInfoData является указателем - поэтому должно быть IntPtr, а не uInt:

    [DllImport("setupapi.dll", SetLastError = true)] protected static
    extern bool SetupDiEnumDeviceInterfaces(IntPtr lpDeviceInfoSet,
        <b>IntPtr pDeviceInfoData</b>, ref Guid gClass,
        uint nIndex, ref DeviceInterfaceData oInterfaceData);

И при вызове его передайте IntPtr.Zero вместо 0.

2 голосов
/ 24 августа 2011

Возможно, вы сможете отследить проблему с ошибочным параметром (если это так), проверив значение из GetLastError, которое можно получить из Marshal.GetLastWin32Error() в приложении .NET.

Одной из возможных проблем может быть инициализация переменной oInterface. Элемент cbSize должен быть установлен. И 64-разрядная версия этой структуры (SP_DEVICE_INTERFACE_DATA) может быть больше, чем 32-разрядная версия. Я только что кратко посмотрел и посчитал в голове (всегда подвержен ошибкам), и похоже, что 32-битная версия будет 28 байтов, а 64-битная версия будет 32 байта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...