2011-08-23 12 views
5

Jestem względnie nowym użytkownikiem .net/C# (choć bardzo doświadczony w Win32/MFC i innych platformach) i muszę napisać narzędzie, aby porozmawiać z niestandardowe urządzenie USB HID. Protokół jest dość prosty i już mam działające narzędzie napisane w MFC, ale wolałbym napisać to narzędzie w .Net/C#, ponieważ próbuję poruszać się z czasami i pozostawić MFC w tyle.Windows 7 64-bitowy i dostęp do wywołań Win32 API za pośrednictwem problemów P/Invoke & Marshal

zrobiłem kilka badań i natknąłem się na ten artykuł, który wydawał mi pomóc zrozumieć, w jaki sposób uzyskać dostęp do urządzeń HID z .NET/C#, zwłaszcza jak to tylko wołając do Win32 API Jestem już zaznajomieni z:

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

Podany kod przykładowy dostarczył mi znakomitego wprowadzenia do tego, jak uzyskać dostęp do wywołań Win32 API, aby porozmawiać z urządzeniem USB (tak jak zrobił to mój poprzedni kod MFC) i wszystko działa dobrze na 32-bitowej instalacji systemu Windows Vista lub 7, ale kiedy próbuję uruchomić ten sam kod na 64-bitowej instalacji, to się nie powiedzie. Nawet jeśli spróbuję utworzyć dedykowaną aplikację 64-bitową, nadal nie działa.

Jestem prawie pewien, że problem polega na tym, jak marszałek przekazuje parametry (na stosie?) Do interfejsu Win32 API, ale moja wiedza i doświadczenie .Net/C# na tym etapie nie jest wystarczająco dobra, aby dokładnie rozumiesz, na czym polega problem i jak go rozwiązać - problem jest prawdopodobnie bardziej zaawansowany niż poziom, na którym obecnie się znajduję.

Wszystko wydaje się działać prawidłowo w kodzie aż dojdę do instrukcji ...

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 

Jeżeli SetupDI ... zwraca true na systemach 32-bitowych i następnie iterację wszystkich podłączonych urządzeń USB, ale zwraca false w systemach 64-bitowych. Jestem prawie pewien, że może to być problem z przekazywaniem parametrów do funkcji Win32 API, ale nie rozumiem, jaki jest dokładny problem. Definicja dllimport dla funkcji jest następująca:

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

Zastanawiam się, czy ktoś jest w stanie zaproponować, co może być parametr wykraczająca i jak mogę to naprawić?

Z góry dziękujemy za pomoc, jeśli potrzebujesz więcej informacji, poproś o nią! Rich

+1

Czy na pewno jesteś ładowanie 64-bitowa wersja pliku setupapi.dll podczas uruchamiania programu 64-bitowego? –

+2

Niestety, mam nadzieję, że pomocna będzie tylko [link] (http://msdn.microsoft.com/en-us/library/ms973190.aspx). – dowhilefor

+0

@Philipp - prawdopodobnie nie - będę dalej badał to. Czy masz jakiś pomysł, w jaki sposób chciałbym iść o wyborze odpowiedniej biblioteki dll? –

Odpowiedz

2

Możesz być w stanie wyśledzić problem parametru wykraczająca (jeśli to, co to jest), sprawdzając wartość od GetLastError, które mogą być uzyskane z Marshal.GetLastWin32Error() w aplikacji .NET.

Jednym z możliwych problemów może być inicjowanie zmiennej oInterface. Element cbSize powinien zostać ustawiony. 64-bitowa wersja tej struktury (SP_DEVICE_INTERFACE_DATA) może być większa niż wersja 32-bitowa. Spojrzałem na to teraz krótko i policzyłem w głowie (zawsze skłonny do błędów) i wygląda na to, że wersja 32-bitowa będzie miała 28 bajtów, a wersja 64-bitowa będzie miała 32 bajty.

+1

To naprawdę wydaje się być problemem. Jeśli sprawdzę ostatni błąd, otrzymam kod 0x6f8, dostarczony bufor nie jest prawidłowy dla żądanej operacji. Rozmiar przekazywanego bufora wynosi rzeczywiście 28 bajtów, jeśli naprawię błąd w kodzie przykładowym, tak aby zadeklarowana wartość była zadeklarowana tak długo, jak na definicję win32 (zamiast int) to naprawia rozmiar i wykonuje przykładowy kod, przynajmniej do momentu, w którym przypada kolejna rozmowa - więc musisz to teraz ustalić. Dzięki za pomoc. –

+0

to wskaźnik, nie długo! Zamiast tego użyj IntPtr! – JCH2k

5

Od MSDN:

 
BOOL SetupDiEnumDeviceInterfaces(
    __in  HDEVINFO DeviceInfoSet, 
    __in_opt PSP_DEVINFO_DATA DeviceInfoData, 
    __in  const GUID *InterfaceClassGuid, 
    __in  DWORD MemberIndex, 
    __out  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData 
); 
DeviceInfoData [w, opcjonalnie]
wskaźnik do struktury SP_DEVINFO_DATA ...

Zauważ, że DeviceInfoData jest wskaźnikiem - tak powinno być IntPtr, nie Uint:

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

A kiedy nazywając ją przechodzą IntPtr.Zero zamiast 0.

+1

+1 Ludzie źle to rozumieją. –

+1

Spojrzałem na to i zgadzam się, że to, co mówisz, ma sens, ale nie wydaje się, żeby to miało jakiś wpływ na mój problem, ale dzięki za pomoc. –