CLR dll 无法运行托管 DLL,除非它位于 exe 目录(或其子目录)内

CLR dll cant run Managed DLL unless it locate inside the exe directory (or its subdirectory)

本文关键字:目录 exe 子目录 运行 dll DLL CLR      更新时间:2023-10-16

>我有这种情况:

  1. 两个C++应用程序,用于在运行时加载插件 DLL。
  2. 具有 CLR\CLI 支持的插件 DLL,引用托管 (C#) DLL。
  3. 托管 (C#) DLL。

它的顺序是这样的:

  • 存储在app1目录中的第一个应用
  • 存储在app2目录中的第二个应用程序
  • 所有具有依赖项(CLR 和托管)的插件 DLL 都在插件目录中,它与 app1 和 app2 并行

问题是,如果托管 DLL 无法从插件 DLL 加载,除非它位于可执行目录(app1、app2)中。我真的更喜欢它位于插件目录中,因为从逻辑上讲,它应该从插件而不是从应用程序中使用,并且我想避免重复,插件目录不能作为应用程序的子目录定位,因为我有两个应用程序。

可以使用 .config 文件配置 .NET 应用程序以启用来自其他目录的程序集绑定,但同样,这是一个C++应用程序。 此外,我已经阅读了有关配置文件的信息,它写道它只能用于子目录。我引用:(来自此链接)

"专用路径 必需"属性。

指定应用程序基目录的子目录 可能包含程序集。用分号分隔每个子目录。

澄清一下:从插件运行其他 DLL 没有问题(插件目录位于 %PATH% 环境中),仅加载托管 DLL 时出现问题。

所以,我的问题是:如何使托管 DLL 从自定义目录运行,该目录不是可执行文件的子目录?

我正在寻找一个可行的解决方案,没有重复的文件或目录。

例:

C# (托管) DLL

using System;
namespace PrintSample
{
public class CPrintSample
{
void print()
{ 
Console.WriteLine("Hello");
} 
}
}

CLR DLL(参考在预处理器中添加和CLR_PRINT_SAMPLE_EXPORT定义的 C# PrintSample)

clr_sample.h

#pragma once
#ifdef CLR_PRINT_SAMPLE_EXPORT
#define CLR_PS_API __declspec(dllexport)
#else
#define CLR_PS_API __declspec(dllimport)
#endif
class IPrintSample
{
public:
virtual void Print()=0;
};
CLR_PS_API IPrintSample* Factory();

clr_sample.cpp

#include <msclr/marshal.h>
#include <msclr/auto_gcroot.h>
#include "clr_sample.h"
using namespace System;
using namespace System::Runtime::InteropServices;
using namespace msclr::interop;
using namespace PrintSample;
class CClrPrintSample : public IPrintSample
{
msclr::auto_gcroot<PrintSample::CPrintSample^> bridge;
public:
CClrPrintSample ()
{
bridge = gcnew PrintSample::CPrintSample();
}
~CClrPrintSample ()
{
delete bridge;
GC::Collect(); 
}
void Print()
{
bridge->print();
}
};
IPrintSample* CLR_PS_API Factory()
{
return new CClrPrintSample();
}

C++(控制台应用)(与 CLR 项目链接)

#include "clr_sample.h"
int main()
{
IPrintSample* ps = Factory();
ps->Print();
delete ps;
return 0;
}
  • 当所有二进制文件都位于同一目录中时,它可以工作。
  • 当 CLR DLL 位于另一个目录(位于 PATH 中,但不是应用程序目录的子目录中)并在当前应用程序目录中管理时,它将起作用。
  • 当 CLR 和托管都位于另一个目录中时,它不起作用。

您可以将插件的符号链接创建到 app1/plugins & app2/plugins。 但它仅在 NTFS 上可用。见 mklink.exe doc。

这是您可接受的解决方案吗?