Hello,
I am trying to call a function from another .dll via domain so that I can unload the .dll.
Originally my function used Assembly.Load. However I could not update the .dll file whilst within AutoCAD.
Public SharedSub InvokeAutoCADCommand(ByVal strCommandName AsString,
ByVal fullPathDllName AsString)
'Dim adevidence As Evidence = AppDomain.CurrentDomain.Evidence
Dim appDomSetup As New AppDomainSetup
Dim domain As AppDomain = AppDomain.CreateDomain("MyDomain", Nothing, appDomSetup)
'Dim assemblyBytes As Byte() = File.ReadAllBytes(fullPathDllName)
'Dim objAssembly As Assembly = Assembly.Load(assemblyBytes)
Dim objAssembly AsAssembly = domain.Load(fullPathDllName)
For Each objType AsTypeIn objAssembly.GetTypes()
If objType.IsClass = True Then
If objType.Name.ToLower = strCommandName.ToLower Then
Dim ibaseObject AsObject = Activator.CreateInstance(objType)
Dim arguments AsObject() = NewObject() {}
Dim mi As MethodInfo = objType.GetMethod(strCommandName)
mi.Invoke(ibaseObject, arguments)
'objType.InvokeMember(Nothing, Nothing, Nothing, Nothing, Nothing)
'objType.InvokeMember(strCommandName, BindingFlags.[Default] Or BindingFlags.InvokeMethod, Nothing, ibaseObject, arguments)
'objType.InvokeMember(strCommandName, BindingFlags.[Default] Or BindingFlags.InvokeMethod, Nothing, Nothing, arguments)
Exit For
End If
End If
Next
AppDomain.Unload(domain)
End Sub
Hi David,
Unless you have time to loose, I would discourage you trying to create your own AppDomain in order to make your AutoCAD dll unloadable. I personally tried to achieve that, and succeeded to some extent, as I was able to perform cross domain calls involving AutoCAD.Net API, however doing so, even using very simple APIs, just made AutoCAD unstable and reliably crashing at shutdown. I was told by the .Net development team that there are some globals variable in AutoCAD .Net core that would prevent cross domain workflow to work properly.
Concerning your code, you need to use "CreateInstanceAndUnwrap" if you want to perform cross domain calls. Also your current approach is wrong straight from the beginning: you have to realize that even accessing the existing types of an assembly from your command, which is run from the default domain, will cause that assembly to be loaded in that domain, and therefore making it unloadable. You need to use proxies for anything you want to access from the default domain to the one you created, you need to derive your custom proxy classes from "MarshalByRefObject". I would suggest you take a look at some Microsoft documentation concerning "CreateInstanceAndUnwrap" and "MarshalByRefObject" if you are curious and not familiar with those concepts.
Regards,
Philippe.
Thank you very much for your reply,
I am beginning to come to the same conclusion as you have, it looks pretty difficult. I have done some investigation into "CreateInstanceAndUnwrap" and "MarshalByRefObject". However the only examples I could find are using a class which exists within the same dll so I can't find how to reference a class which is in the new dll.
If you have an example of what you did it would be most appreciated.
Kind Regards
David
Here is my test project, it contains a test assembly to be loaded and the AcadDotNetLoader.
There are couple of commands that illustrates how to access existing AppDomains and loaded assemblies, some of this code was tricky to put together.
You can check how "DoNetLoad" command works and how I used the proxies to isolate the loaded dll types and methods from being loaded in the default appdomains.
If you can make progress in this area, you are welcome to share;)
Regards,
Philippe.
Can't find what you're looking for? Ask the community or share your knowledge.