I have this situation:
- Two C++ applications that load plugin DLLs at runtime.
- A Plugin DLL with CLR\CLI support, with a reference to a managed (C#) DLL.
- The managed (C#) DLL.
It is ordered like this:
- The first app stored in app1 dir
- The second app stored in app2 dir
- All the plugin DLLs, with dependencies (CLR and managed) are in plugin dir, which is parallel to app1 and app2
The problem is that if the managed DLL can't be loaded from the plugin DLL unless it is in the executable dir (app1, app2). I really prefer it will be located in the plugin dir since logically it should be used from the plugin and not from the apps, and I want to avoid duplications, the plugin directory can't be located as a subdirectory of the app since I have two apps.
.NET applications can be configured with a .config file to enable Assembly Binding from other directories, but again, this is a C++ application. In addition, I've read about the config files, and it wrote it can be used only for subdirectories. I quote: (from this link)
privatePath Required attribute.
Specifies subdirectories of the application's base directory that might contain assemblies. Delimit each subdirectory with a semicolon.
Just to clarify: I don't have a problem running other DLLs from the plugin (the plugin directory is in the %PATH% environment), I have a problem only loading the managed DLLs.
So, my question is: how can I enable the managed DLL to run from a custom dir, which is not a sub-directory of the executable?
I'm looking for a working solution, without duplications of files or directories.
Example:
C# (managed) DLL
using System;
namespace PrintSample
{
public class CPrintSample
{
void print()
{
Console.WriteLine("Hello");
}
}
}
CLR DLL (with reference to C# PrintSample added and CLR_PRINT_SAMPLE_EXPORT defined in preprocessor)
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++ (console app) (linked with the clr project)
#include "clr_sample.h"
int main()
{
IPrintSample* ps = Factory();
ps->Print();
delete ps;
return 0;
}
- When all binaries are in the same dir, it works.
- When the CLR DLL is in another dir (which is in the PATH, but not a subdirectory of app dir) and managed in the current app dir, it works.
- When both, CLR and managed, are in the other dir it doesn't work.