Я звоню SetupDiGetDeviceInterfaceDetail () здесь , а структура SP_DEVICE_INTERFACE_DETAIL_DATA неправильно маршалирует.Определение структур можно найти здесь .Я попытался использовать определение для этой структуры из PInvoke.net, здесь , но безрезультатно.
До сих пор, когда вызов функции завершается успешно (т.е. маршалер не 'выдает ошибку), возвращаемое значение равно 1784 (INVALID_USER_BUFFER).Главное, когда этот код выполняется из 32-битного процесса на моем компьютере, все это работает просто отлично.Когда он запускается в 64-битном процессе, у меня возникает эта проблема.
Моя текущая подпись SetupDiGetInterfaceDetailData () выглядит следующим образом:
[DllImport(@"c:\Windows\System32\SetupApi.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDeviceInterfaceDetail(
SafeHandleZeroOrMinusOneIsInvalid deviceInfoSet,
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
IntPtr deviceInterfaceDetailData,
uint deviceInterfaceDetailDataSize,
IntPtr requiredSize,
IntPtr deviceInfoData);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SP_DEVICE_INTERFACE_DETAIL_DATA
{
public UInt32 cbSize;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string DevicePath;
}
В настоящее время я выделяю память с помощью Marshal.AllocHGlobal() и запись / чтение данных из этого буфера с использованием семейства функций Marshal. *.
Для справки, вот что я делаю:
public string GetPathToDevice(SafeHandleZeroOrMinusOneIsInvalid hDevList,
SP_DEVICE_INTERFACE_DATA devIntfData)
{
uint sizeNeeded = 0;
// get's the size needed
SetupApi.SetupDiGetDeviceInterfaceDetailData(hDevList,
ref devIntfData,
IntPtr.Zero,
0,
ref sizeNeeded,
IntPtr.Zero);
IntPtr pBuffer = Marshal.AllocHGlobal((int)(sizeNeeded + 4)); // +4 for cbSize
SetupApi.SetupDiGetDeviceInterfaceDetailData(hDevList,
ref devIntfData,
pBuffer,
sizeNeeded,
IntPtr.Zero,
IntPtr.Zero);
// copy bytes from unmanaged space in pBuffer to a manged byte array
// free unmanaged memory
return theStringParsedFromByteArray;
}
Как я уже говорил, яЯ попытался определить структуру, описанную PInvoke.net для SP_DEVICE_INTERFACE_DETAIL_DATA (см. ссылку выше), и создал новую сигнатуру метода PInvoke для обработки этого.При запуске из 64-битной системы я получаю ту же проблему, то есть функция возвращает 1784. Причина, по-видимому, заключается в том, что ссылки в C # при работе в 64-битной среде выровнены по 8 байтов (обнаружено, что в другойСтатья StackOverflow).Я пробовал различные макеты для этой структуры, пытаясь заставить макет (используя явное смещение поля) в 4-байтовую выровненную структуру, но у меня это тоже не сработало.У меня были проблемы со временем компиляции.
Я пытался использовать различные декорации для параметров сигнатуры метода PInvoke.Например, MarshalAs (UnmanagedType.LPStruct), с которым я постоянно неправильно соединяюсь.Теперь я дошел до того, что мне нужна помощь в этом.
Что я действительно не понимаю, так это почему это вообще происходит.Даже если он работает на моем компьютере при работе в 32-битной среде, разве 64-битная среда просто не подключит меня к правильным 64-битным версиям Setup API?В чем проблема?
Спасибо за любую помощь, Энди
Проблема решена
Хорошая вещь, она решена сейчас, раздражающая вещьЯ не люблю исправлять вещи в течение часа или двух после публикации здесь.Итак, проблема заключалась в том, что это была проблема 64 бит.Код ошибки от Marshal.GetLastWin32Error () сообщал мне о проблеме.Значение cbSize было неверным.Я изменил его на 8, и теперь все работает.
Пожалуйста, кто-нибудь, объясните мне, почему размер теперь 8 на 64 бит?Структура теперь выше (комментатор попросил меня включить ее).Структура состоит из двух членов, одного DWORD и TCHAR [ANYSIZE_ARRAY].ANYSIZE_ARRAY оценивается как 1, TCHAR всегда является WCHAR, если Unicode и char в противном случае.DWORD - это всегда 32-битное количество (4 байта), а один TCHAR для Unicode - 2 байта.Итак, 4 + 2 = 6. Почему это 8?Это из-за выравнивания байтов для этой структуры в 64 битах?Мне бы очень хотелось это понять.
В любом случае, установка элемента cbSize на 8 для 64-битной и 6 для 32-битной работает, и я могу использовать структуру, определенную выше, вместоНеобработанное выделение / освобождение памяти и маршалинг.