Powershell 2 new-object exception "Cannot find type ..." when creating .net class interface from external library

I found a problem that is pretty easy to reproduce. Please advise if there is any work for this?

There are two library libraries .Net.dll and library.B.dll.Net. And each library has one InterfaceA and InterfaceB interface. ClassAA implements InterfaceA and lives in libraryA. ClassAB implements interface B and lives in the same library. Similarly, ClassBB - LibraryB - InterfaceB; ClassBA - LibraryB - InterfaceA

The new object works correctly when ClassAA and ClassBB are created, but not ClassAB or ClassBA. They do not constantly create an instance.

Here you are powershell code

[System.Reflection.Assembly]::LoadFile('c:\LibraryA.dll') [System.Reflection.Assembly]::LoadFile('c:\LibraryB.dll') $obj1 = new-object -typeName ClassAA (IT WORKS) $obj2 = new-object -typeName ClassBB (IT WORKS) $obj3 = new-object -typeName ClassAB (EXCEPTION THROWN) $obj4 = new-object -typeName ClassBA (EXCEPTION THROWN) 

Thank you very much,

Andrew

+4
source share
2 answers

Instead of ::LoadFile use:

 [System.Reflection.Assembly]::LoadFrom('c:\LibraryA.dll') [System.Reflection.Assembly]::LoadFrom('c:\LibraryB.dll') 

When you use :: LoadFrom , the assembly will be loaded into the context of the directory from which it was loaded, with links to assemblies in the same directory will be automatically resolved. :: LoadFile is designed to load assemblies that share an identity but are located in different directories and do not support any load context, so referenced assemblies are not allowed.

+6
source

The answer to this question solves your problem: How can I get PowerShell Added-Types to use added types

The key is to use the AppDomain.CurrentDomain.AssemblyResolve event.

You can, for example, add the AssemblyResolver class (from the above message) to your library, and then use [Utils.AssemblyResolver] :: AddAssemblyLocation ("LibraryB.dll") to use the LibraryB link if necessary.

Or just to prove the point:

 [System.AppDomain]::CurrentDomain.add_assemblyResolve({ If ($args[1].Name.StartsWith("LibraryB")) { Return [System.Reflection.Assembly]::LoadFile("C:\LibraryB.dll") } Else { Return $Null } }) 

Note that you have a circular dependency in the above example: LibraryA refers to libraries LibraryB and LibraryB. You will probably want to fix this in the first place - if you have the same thing in your real project ...

+3
source

All Articles