加载.net包装程序无法加载本地依赖项

问题描述 投票:1回答:1

情况:.net包装器类的多个版本,所有版本都具有相同的签名,并且具有相同的签名。我们想以wcf服务方法动态加载包装器中的1个。我计划使用每个包装器+依赖dll来设置文件夹。我们将根据用户选择的版本使用switch或if语句来运行。

我具有带有路径的Assembly.LoadFrom,并且可以创建包装器类的实例。但是在包装器中调用方法失败,并显示“无法加载或找到CTV.dll”。

如果更改计算机或用户环境路径以指向CTV.dll,它将执行该方法。但这是全局的,并且只会指向一个版本文件夹中的特定CTV.dll。我已经尝试了很多次

Environment.SetEnvironmentVariable(“ Path”,[文件夹中ctv.dll的路径],EnvironmentalVariableTarget.Process);

但是无效,会发生相同的错误。

我是否缺少某些东西。似乎会有答案。

还有另一种方法来处理此用例吗?

c# wrapper .net-assembly
1个回答
0
投票

解决方案1:

乍看之下,在加载托管包装程序之前先加载目标本机dll似乎是一个很好的解决方案(通过使用带有绝对路径的LoadLibrary调用)

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

来自docs.microsoft.com

如果字符串指定完整路径,则该函数仅搜索模块的路径。

我也想谈一谈我成功尝试过的替代方法。

解决方案2:

我们可以使用SetDllDirectory本机API将新路径注入LoadLibrary的搜索顺序。

使用LoadLibrary函数加载本机库,并且要加载的库具有特定的directory search order

请参阅本节,摘自LoadLibrary函数的文档:

可以使用SetDllDirectory函数更改搜索路径。建议使用此解决方案,而不要使用SetCurrentDirectory或硬编码DLL的完整路径。

我向不存在的模块添加了符号互操作调用:

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

然后调用此函数并使用ProcMon监视搜索行为>

enter image description here

您可以清楚地看到LoadLibrary以什么顺序查找本机映像。 (在我的系统上)

然后,在对该不存在的模块进行任何调用之前,我调用了[SetDllDirectory]:

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

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

并再次调用该方法。结果如下。

检查进程的文件夹后,LoadLibrary将立即检查注入的路径。

因此,如果您调用SetDllDirectory并将正确的目录路径添加到LoadLibrary的搜索顺序中,则在托管包装程序要求时,应从那里自动加载所需版本的本机dll。

希望这会有所帮助。

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.