I want to use DllExport, in a dll which has a broker-function: routing some calls from external code (VBA) to other .NET dll's behind.
I got the DllExport working on a single dll: the dll is generated, and I can use it. But... only with code from that single dll. When I call code from another (in .NET referenced) dll, the solution still builds, I still can use the code from the dll with dllexport, but when calling a method that routes to the referenced dll, VBA gives me a 'Could not load file or assembly 'myseconddllname, version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of iets dependencies. The system cannot find the file specified.
I also tried to add DllExport to the second dll (which shouldn't be necessary, no objects/info from the second dll should be exposed to Unmanaged code). This didn't help.
Any ideas how to solve this?
Edit: registered an issue on github: Calling referenced .NET assembly
For others reference: with help from here and github-issue found the solution:
Having two projects:
In ClassLibrary1 we've a static class UnmanagedExport:
static class UnmanagedExport
{
static UnmanagedExport()
=> AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
=> Assembly.LoadFrom($@"{new FileInfo(args.RequestingAssembly.Location).DirectoryName}\{args.Name.Split(',')[0]}.dll");
[DllExport]
[return: MarshalAs(UnmanagedType.IDispatch)]
static object CreateBroker()
=> new Class1();
}
CreateBroker() creates an instance of Class1 (which is supposed to be the broker between VBA and ClassLibrary2). ClassLibrary1.Class1:
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class Class1
{
public void DoNothingOnClass2Typed()
=> new Class2().DoNothing();
public void CreateClass2aFromClass2Typed()
=> new Class2().CreateClass2a();
}
Class2 (and Class2a) are both in ClassLibrary2 (which is referenced by ClassLibrary1):
namespace ClassLibrary2
{
public class Class2
{
public void DoNothing()
{
return;
}
public void CreateClass2a()
{
var class2a = new Class2a();
}
}
}
From VBA this is called as:
Declare Function CreateBroker Lib "C:\source\repos\DllExportTest\ClassLibrary1\bin\Debug\ClassLibrary1.dll" () As Object
Public Sub RunTest()
Dim class1 As Object
Set class1 = CreateBroker()
class1.DoNothingOnClass2Typed
class1.CreateClass2aFromClass2Typed
Set class1 = Nothing
End Sub
Works like a charm!
Note: ClassLibrary2 can also be a .NET Standard dll, so the solution is compatible with .NET Core also.