Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 加载.net包装无法加载本机依赖项_C#_Wrapper_.net Assembly - Fatal编程技术网

C# 加载.net包装无法加载本机依赖项

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

情况:一个.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的完整路径

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

[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\\");