Изменяет ли System.Reflection.Assembly.LoadFrom собственный порядок поиска в DLL? - PullRequest
0 голосов
/ 12 июня 2018

У меня следующая ситуация:

base\C_sharp.exe -> base\sub\CPPCLI.dll -> base\sub\CPPnative.dll

, где у меня есть исполняемый файл C #, загружающий DLL C ++ / CLI (.NET) через System.Reflection.Assembly.LoadFrom, который статически связан сCPPnative.dll.

Теперь Стандартный порядок поиска Dll в Windows:

  1. Каталог , из которого загружено приложение .
  2. Системный каталог.Используйте функцию GetSystemDirectory, чтобы получить путь к этому каталогу.
  3. 16-разрядный системный каталог.(...)
  4. Каталог Windows.(...)
  5. Текущий каталог.
  6. Каталоги, перечисленные в переменной среды PATH.

Очевидно, если я вызову

System.Reflection.Assembly.LoadFrom("D:\....\base\sub\cppcli.dll");

сборка .NET будет найдена, но затем произойдет следующее: транзитивная нагрузка cppnative.dll будет успешной!

1618:3088 @ 1557218328 - LdrLoadDll - ENTER: DLL name: D:\....\base\sub\cppcli.dll DLL path: D:\....\base\sub\;;C:\Windows\system32;...
...
1618:3088 @ 1557218328 - LdrpHandleOneOldFormatImportDescriptor - INFO: DLL "D:\....\base\sub\cppcli.dll" imports "cppnative.dll"
...
1618:3088 @ 1557218328 - LdrpLoadImportModule - ENTER: DLL name: cppnative.dll DLL path: D:\....\base\sub;;C:\Windows\system32;

TL; DR : каксобственный загрузчик NT неожиданно начинает искать в каталоге sub?

Нормальное поведение LoadLibrary предполагает, что сначала выполняется поиск исполняемого каталога.

1 Ответ

0 голосов
/ 14 июня 2018

Существует вероятность того, что .NET Framework использует внутренне LOAD_WITH_ALTERED_SEARCH_PATH, когда в конечном итоге выполняет вызов LoadLibrary для сборки C ++ / CLI.

По крайней мере, я ясно вижу в своих стеках вызововчто фреймворк это с использованием LoadLibraryEx внутри для загрузки смешанного режима cppcli.dll в процесс.

Сначала:

>   cppnative1.dll!DllMain(HINSTANCE__ * hModule, unsigned long ul_reason_for_call, void * lpReserved) Line 13  C++ Symbols loaded.
    cppnative1.dll!dllmain_dispatch(HINSTANCE__ * const instance, const unsigned long reason, void * const reserved) Line 199   C++ Symbols loaded.
    ntdll.dll!LdrpRunInitializeRoutines()  Unknown Symbols loaded.
    ntdll.dll!LdrpLoadDll()    Unknown Symbols loaded.
    ntdll.dll!LdrLoadDll() Unknown Symbols loaded.
    KernelBase.dll!LoadLibraryExW()    Unknown Symbols loaded.
    [Managed to Native Transition]      Annotated Frame
    mscorlib.dll!System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(System.Reflection.AssemblyName assemblyRef, System.Security.Policy.Evidence assemblySecurity, System.Reflection.RuntimeAssembly reqAssembly, ref System.Threading.StackCrawlMark stackMark, System.IntPtr pPrivHostBinder, bool throwOnFileNotFound, bool forIntrospection, bool suppressSecurityChecks)    Unknown No symbols loaded.

Затем:

>   cppcli.dll!DllMain(HINSTANCE__ * hModule, unsigned long ul_reason_for_call, void * lpReserved) Line 17  C++ Symbols loaded.
    cppcli.dll!dllmain_dispatch(HINSTANCE__ * const instance, const unsigned long reason, void * const reserved) Line 199   C++ Symbols loaded.
    mscoreei.dll!000007fef3ec0e64() Unknown No symbols loaded.
    mscoree.dll!000007fef5fd3281()  Unknown No symbols loaded.
    mscoree.dll!000007fef5fd32cf()  Unknown No symbols loaded.
    ntdll.dll!LdrpRunInitializeRoutines()  Unknown Symbols loaded.
    ntdll.dll!LdrpLoadDll()    Unknown Symbols loaded.
    ntdll.dll!LdrLoadDll() Unknown Symbols loaded.
    KernelBase.dll!LoadLibraryExW()    Unknown Symbols loaded.
    [Managed to Native Transition]      Annotated Frame
    mscorlib.dll!System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(System.Reflection.AssemblyName assemblyRef, System.Security.Policy.Evidence assemblySecurity, System.Reflection.RuntimeAssembly reqAssembly, ref System.Threading.StackCrawlMark stackMark, System.IntPtr pPrivHostBinder, bool throwOnFileNotFound, bool forIntrospection, bool suppressSecurityChecks)    Unknown No symbols loaded.

Я также могу заметить, что исполняемый путь больше не ищется при разрешении зависимостей переходного (собственного) модуля во время этого вызова LoadLibraryEx.

То есть всеНЕОБХОДИМО, чтобы транзитивные (собственные) зависимости находились в каталоге вызова LoadFrom, а не в каталоге приложения.

(Между прочим, CWD "." ищется , поэтому его можно добавить впутаница, а также.)

...