C# 加载.net包装无法加载本机依赖项
情况:一个.net包装类的多个版本,都使用相同的签名命名。我们希望在wcf服务方法中动态加载1个包装器。我计划用每个包装器+依赖dll设置文件夹。我们将根据用户选择的运行版本使用switch或if语句 我已经获得了路径为Assembly.LoadFrom的文件,可以创建包装器类的实例。但在包装器中调用方法失败,出现“无法加载或查找CTV.dll” 如果我将机器或用户环境路径更改为指向CTV.dll,它将执行该方法。但这是全局的,只会指向一个版本文件夹中的特定CTV.dll。我试过很多次了 SetEnvironmentVariable(“路径”,[文件夹中ctv.dll的路径]、EnvironmentVariableTarget.Process) 但它没有效果,同样的错误也会发生 有什么我不知道的吗。看来会有答案的 是否有其他方法来处理此用例?解决方案1: 乍一看,在加载托管包装器之前自己加载目标本机dll似乎是一个很好的解决方案(通过使用带有绝对路径的调用) 发件人: 如果字符串指定完整路径,则函数仅搜索该路径 模块的路径 我还想谈谈另一种选择,我已经成功地尝试过了 解决方案2: 我们可以使用SetDllDirectory本机API将新路径注入LoadLibrary的搜索顺序 本机库是使用函数加载的,要加载的库有一定的限制 请参阅LoadLibrary函数文档中的本节: 可以使用SetDllDirectory函数更改搜索路径。 建议使用此解决方案,而不是使用SetCurrentDirectory或 硬编码DLL的完整路径 我向一个不存在的模块添加了一个符号互操作调用:C# 加载.net包装无法加载本机依赖项,c#,wrapper,.net-assembly,C#,Wrapper,.net Assembly,情况:一个.net包装类的多个版本,都使用相同的签名命名。我们希望在wcf服务方法中动态加载1个包装器。我计划用每个包装器+依赖dll设置文件夹。我们将根据用户选择的运行版本使用switch或if语句 我已经获得了路径为Assembly.LoadFrom的文件,可以创建包装器类的实例。但在包装器中调用方法失败,出现“无法加载或查找CTV.dll” 如果我将机器或用户环境路径更改为指向CTV.dll,它将执行该方法。但这是全局的,只会指向一个版本文件夹中的特定CTV.dll。我试过很多次了 Set
[DllImport("oguzozgul.dll")]
static extern uint InvokeOguzOzgul(IntPtr oguz, uint ozgul);
然后调用此函数并使用监视搜索行为
您可以清楚地看到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
希望这有帮助
Oguz,非常感谢您抽出时间向我解释这一点。我实现了方法2,它工作得很好。为其他人澄清。我需要加载的依赖dll是本机dll,不是托管的。
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetDllDirectory(string lpPathName);
// Calling SetDllDirectory:
SetDllDirectory("c:\\temp\\");