Loading .net wrapper fails to load native dependency

烂漫一生 提交于 2021-02-11 06:30:58

问题


Situation: multiple versions of a .net wrapper class, all named the same with same signature. We want to dynamically load 1 of the wrappers in a wcf service method. I plan to setup folders with each wrapper + dependant dll. We'll use switch or if statements per user choice of version to run.

I've got Assembly.LoadFrom with path and can create an instance of the wrapper class. But calling a method in the wrapper fails with "cannot load or find CTV.dll".

If I change the machine or user Environment path to point to the CTV.dll, it will execute the method. But this is global and will only point to a specific CTV.dll in one version folder. I have tried many times

Environment.SetEnvironmentVariable("Path", [path to ctv.dll in the folder], EnvironmentVariableTarget.Process);

But is has no effect, the same error occurs.

Is there something I am missing. It seems there would be an answer to this.

Is there another way to handle this use case?


回答1:


Solution 1:

At first glance, loading the target native dll yourself before loading the managed wrapper seems to be a good solution (By using a LoadLibrary call with an absolute path)

[DllImport("kernel32", SetLastError=true, CharSet = CharSet.Ansi)]
static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);

From docs.microsoft.com:

If the string specifies a full path, the function searches only that path for the module.

I want to talk about an alternative also, which I tried with success.

Solution 2:

We can inject a new path into the search order of LoadLibrary by using the SetDllDirectory native API.

The native libraries are loaded using LoadLibrary function and there is a certain directory search order for the libraries to be loaded.

See this section taken from the documentation of LoadLibrary function:

The search path can be altered using the SetDllDirectory function. This solution is recommended instead of using SetCurrentDirectory or hard-coding the full path to the DLL.

I added a symbolic interop call to a non-existent module:

[DllImport("oguzozgul.dll")]
static extern uint InvokeOguzOzgul(IntPtr oguz, uint ozgul);

Then called this function and monitored the search behavior with ProcMon

You can clearly see in what order LoadLibrary looks for the native image. (On my system)

And then, before any calls to this non-existent module, I invoked [SetDllDirectory]:

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetDllDirectory(string lpPathName);

// Calling SetDllDirectory:
SetDllDirectory("c:\\temp\\");

And called the method again. The result is as follows.

Right after checking the process' folder, LoadLibrary checks the injected path.

So if you call SetDllDirectory and add the correct directory path to the search order of LoadLibrary, the desired version of the native dll should be loaded from there automatically when demanded by the managed wrapper.

Hope this helps.



来源:https://stackoverflow.com/questions/61281867/loading-net-wrapper-fails-to-load-native-dependency

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!