Я переписываю этот вопрос, так как теперь я понимаю немного больше. Первоначально то, что у меня было, было слишком расплывчатым. Я обнаружил, что меня направляет что-то под названием «Безопасность доступа к коду». Это старая шляпа для всех, кто это читает, я уверен, но не для меня.Безопасность доступа к коду предотвращает вызовы API PInvoking Setup
Приложение очень большое, поэтому в двух словах у меня есть две сборки. Одна из них - сборка утилит с различными «инструментами», используемыми во всей программе. Другой призвал эти инструменты для того, чтобы функционировать.
В сборке утилит есть много функций, которые являются PInvoked, но тот, который дает мне печаль: SetupDiGetDeviceInterfaceDetail() (see here). Мой прототип функции выглядит следующим образом:
[DllImport("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);
В сборку, которая использует эту функцию, я использую два этапа, изложенные в замечаниях, с тем, чтобы получить представление о том, сколько места мне нужно хранить DevicePath который находится в структуре SP_DEVICE_INTERFACE_DETAIL_DATA (see here). Например:
string GetDevicePath(SafeHandleSeroOrMinusOneIsInvalid hList, SP_DEVICE_INTERFACE_DATA infoSet)
{
IntPtr pReqSize = Marshal.AllocHGlobal(4);
Marshal.WriteInt32(pReqSize, 0);
uint reqSize;
// get the size needed
PInvoke.SetupDiGetDeviceInterfaceDetail(hList,
ref infoSet,
IntPtr.Zero,
0,
pReqSize,
IntPtr.Zero);
reqSize = (uint)Marshal.ReadInt32(pReqSize, 0);
IntPtr pDevInfoDetail = Marshal.AllocHGlobal((int)reqSize + 4); // +4 for cbSize
// call again, this time getting the actual data wanted
PInvoke.SetupDiGetDeviceInterfaceDetail(hList,
ref infoSet,
pDevInfoDetail,
reqSize,
IntPtr.Zero,
IntPtr.Zero);
string path;
// work .NET magic to read from unmanaged memory the path string and assign it
// to the above variable. Deallocate both unmanaged memory blocks.
return path;
}
Самое сложное, что эти сборки используются двумя различными программами. Один из них - графический интерфейс с использованием изолированной оболочки Visual Studio. Другой - просто программа командной строки. Когда GUI запущен, вызывается вышеупомянутый код и выполняется, как ожидалось. Однако в инструменте командной строки они терпят неудачу (как описано в ссылке MSDN для этой функции API установки) с некоторыми данными о том, что произошло. На этом этапе я могу только восстановить часть возвращаемых данных. Это то, что возвращается из среды выполнения: «stem.Security.PartialTrustVisibilityLevel, mscorlib, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089».
Я знаю, что это имеет какое-то отношение к безопасности доступа кодов, но я совсем не уверен, как это исправить. Используя некоторые предложения, которые я нашел до сих пор, я пробовал этот атрибут для сборки (я разместил его перед блоком пространства имен кода): [сборка: AllowPartiallyTrustedCallers]
Но это вызвало другие проблемы с компиляцией.
Пожалуйста, что-нибудь было бы очень полезно и с благодарностью.
Andy
Не могли бы вы предоставить полные данные об исключительных деталях, возвращенные его методом ToString()? –
@Nicole Насколько я могу судить, никакого исключения не генерируется. Visual Studio не нарушает никаких необработанных исключений, и мой код не завернут в блоки try/catch. Единственное, что я вижу, это то, что функция API установки возвращается с кодом ошибки 1784 (Invalid user buffer) и помещает детали устройства, которое предоставляет интерфейс в элемент пути.К сожалению, когда я увеличиваю размер буфера, чтобы захватить все это, я получаю бессмысленные данные. –
Где вы находите ссылку на PartialTrustVisibilityLevel? –