I am trying to use PowerShell v4.0 (x86/64) against one of our internal API's to do some fairly basic stuff, but I cannot seem to get past the dependency loading.
So far I have:
[Reflection.Assembly]::LoadFrom("C:\Users\David Shaw\Desktop\API\API.dll")
as per Dat Bui's blog post.
This works fine, I then try to use a type inside this DLL:
$a = New-Object API.API("", 1234)
This gives me the following error:
New-Object : Exception calling ".ctor" with "2" argument(s): "Unable to find assembly API.Dependency,
Version=1.2.5.0, Culture=neutral, PublicKeyToken=null'."
At line:1 char:6
+ $a = New-Object API.API("", 1234)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
Looking in FusionLog, the only places it looks for the dependency is:
C:\Windows\System32\WindowsPowerShell\v1.0
Things I've tried so far:
LoadFile
instead of LoadFrom
Add-Type -Path API.dll
CurrentDirectory
LoadFrom
on the dependency.From my Script:
$OnAssemblyResolve = [System.ResolveEventHandler] {
param($sender, $e)
$n = New-Object System.Reflection.AssemblyName($e.Name).Name
$fn = "C:\Users\David Shaw\Desktop\API\$n.dll"
return [Reflection.Assembly]::LoadFile($fn)
}
[System.AppDomain]::CurrentDomain.add_AssemblyResolve($OnAssemblyResolve)
Based on the comment, the API.dll is .Net 4.0 (AnyCPU) and the API.Dependency.dll is .Net 2.0 (AnyCPU). If this could be an issue, any idea's how to resolve it?
-ModuleInfoSpecifies the module objects to remove. Enter a variable that contains a module object (PSModuleInfo) or a command that gets a module object, such as a Get-Module command. You can also pipe module objects to Remove-Module .
Reflection. Assembly class. This means that you can pass it to the Get-Member Windows PowerShell cmdlet and see what methods, properties and events are available.
To uninstall the PowerShell module, we can directly use the Uninstall-Module command but the module should not be in use, otherwise, it will throw an error. When we use the Uninstall-Module command, it can uninstall the module from the current user profile or from the all users profile.
I had a similar problem with NuGet packages whereby I had two assemblies that both used a NuGet package (specifically, the Spring.NET libraries). My first C# project (My1stProject) used the .NET Framework v4.0, and thus included the NuGet package DLL specific to that Framework version. A second C# project (My2ndProject) targeted the .NET Framework v4.7, and thus got the v4.5 assembly from the NuGet package. Project My2ndProject had a dependency on My1stProject.
When I compiled the code, everything worked. Project My2ndProject compiled, but the included assembly from the NuGet package was for the v4.5 Framework.
Now, when I attempted - in My2ndProject's binary output directory - to use Powershell code to load and get types for the assembly: $assembly = [System.Reflection.Assembly]::LoadFrom($My1stProjectFullPath)
, followed by $assembly.GetTypes()
, this would fail due to the version discrepancy -- the v4.5 NuGet DLL was there, but it was expecting the v4.0 one.
So, following this excellent code example, my solution is to pre-load the binaries that I need to ignore the version for (so that they are loaded into the App Domain), then use some code that hooks into the assembly resolution process (similar to that in the OP question) and:
Here is the code:
$candidateAssembly = "C:\My2ndProject\bin\Debug\My1stProject.exe"
# Load your target version of the assembly (these were from the NuGet package, and
# have a version incompatible with what My2ndProject.exe expects)
[System.Reflection.Assembly]::LoadFrom("C:\My2ndProject\bin\Debug\Spring.Aop.dll")
[System.Reflection.Assembly]::LoadFrom("C:\My2ndProject\bin\Debug\Spring.Core.dll")
[System.Reflection.Assembly]::LoadFrom("C:\My2ndProject\bin\Debug\Spring.Data.dll")
# Method to intercept resolution of binaries
$onAssemblyResolveEventHandler = [System.ResolveEventHandler] {
param($sender, $e)
Write-Host "ResolveEventHandler: Attempting FullName resolution of $($e.Name)"
foreach($assembly in [System.AppDomain]::CurrentDomain.GetAssemblies()) {
if ($assembly.FullName -eq $e.Name) {
Write-Host "Successful FullName resolution of $($e.Name)"
return $assembly
}
}
Write-Host "ResolveEventHandler: Attempting name-only resolution of $($e.Name)"
foreach($assembly in [System.AppDomain]::CurrentDomain.GetAssemblies()) {
# Get just the name from the FullName (no version)
$assemblyName = $assembly.FullName.Substring(0, $assembly.FullName.IndexOf(", "))
if ($e.Name.StartsWith($($assemblyName + ","))) {
Write-Host "Successful name-only (no version) resolution of $assemblyName"
return $assembly
}
}
Write-Host "Unable to resolve $($e.Name)"
return $null
}
# Wire-up event handler
[System.AppDomain]::CurrentDomain.add_AssemblyResolve($onAssemblyResolveEventHandler)
# Load into app domain
$assembly = [System.Reflection.Assembly]::LoadFrom($candidateAssembly)
try
{
# this ensures that all dependencies were loaded correctly
$assembly.GetTypes()
}
catch [System.Reflection.ReflectionTypeLoadException]
{
Write-Host "Message: $($_.Exception.Message)"
Write-Host "StackTrace: $($_.Exception.StackTrace)"
Write-Host "LoaderExceptions: $($_.Exception.LoaderExceptions)"
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With