2

I've managed to boil down my test to a simple command:

PS C:\Users\CpUser> [System.Reflection.Assembly]::LoadFrom("C:\Users\CpUser\.nuget\packages\njsonschema\10.4.0\lib\net45\NJsonSchema.dll")
MethodInvocationException: Exception calling "LoadFrom" with "1" argument(s): "Could not load file or assembly 'NJsonSchema, Version=10.4.0.0, Culture=neutral, PublicKeyToken=c2f9c3bdfae56102'."

I'm using 64-bit Powershell v7.1.3 on Windows 10. Ran as administrator. It's not able to load the DLL I gave it, which is very odd to me. It also does not give me any detail as to why it cannot load it. When I try a lower version of NJsonSchema.dll, it works, but it loads it from an unexpected location:

PS C:\Users\CpUser> [System.Reflection.Assembly]::LoadFrom("C:\Users\CpUser\.nuget\packages\njsonschema\9.10.52\lib\net45\NJsonSchema.dll")

GAC    Version        Location
---    -------        --------
False  v4.0.30319     C:\Program Files\PowerShell\7\NJsonSchema.dll

It's loading it from C:\Program Files\Powershell\7 which seems wrong to me. I sent to the Properties -> Details of that DLL and it says it is version 10.2.2. What it seems like is happening here is:

  1. Powershell takes the version of the assembly I provided in the LoadFrom() call
  2. It searches C:\Program Files\PowerShell\7 for the same DLL with a version equal to or greater than the version obtained in the previous step
  3. If not found, fail.

What I expect is for it to load the DLL using the absolute path I gave it.

As a workaround, I found another solution that does seem to work:

$AssemblyPath = "C:\Users\CpUser\.nuget\packages\njsonschema\10.4.0\lib\net45\NJsonSchema.dll"
$bytes = [System.IO.File]::ReadAllBytes($AssemblyPath)
[System.Reflection.Assembly]::Load($bytes)

I get a successful result when I run the above in a script:

PS C:\Users\CpUser> .\testLoadDll.ps1

GAC    Version        Location
---    -------        --------
False  v4.0.30319

So I feel like this rules out any issues with the DLL itself. I'm completely lost here. Can someone explain the behavior I'm seeing and how to get the behavior I expect?

void.pointer
  • 24,859
  • 31
  • 132
  • 243
  • *It does not give me any details why it cannot load it* Try turning on [assembly binding failure logs](https://stackoverflow.com/questions/255669/how-to-enable-assembly-bind-failure-logging-fusion-in-net) – John Wu May 06 '21 at 21:33

1 Answers1

1

According to the documentation, for Assembly.LoadFrom Method

The LoadFrom method has the following disadvantages. Consider using Load instead.

                 ...

If an assembly is loaded with LoadFrom, and the probing path includes an assembly with the same identity but a different location, an InvalidCastException, MissingMethodException, or other unexpected behavior can occur.

Update:

According to Resolving PowerShell module assembly dependency conflicts,

PowerShell and .NET

PowerShell runs on the .NET platform. NET is ultimately responsible for resolving and loading assembly dependencies, so we must understand how .NET operates here to understand dependency conflicts.

We must also confront the fact that different versions of PowerShell run on different .NET implementations. In general, PowerShell 5.1 and below run on .NET Framework, while PowerShell 6 and above run on .NET Core. These two implementations of .NET load and handle assemblies differently. This means that resolving dependency conflicts can vary depending on the underlying .NET platform.

Therefore, ensure you are loading the DLL in the netstandard2.0 folder, if using Powershell version 6 and above.

Try the following:

Open PowerShell version 7.1.3:

  • In "Type here to search" box, enter pwsh
  • Right-click PowerShell 7 (x64)
  • Select Run as administrator

Get PowerShell version:

Get-Host | Select-Object Version

enter image description here

Get Loaded Assemblies:

[System.AppDomain]::CurrentDomain.GetAssemblies()

Load NJsonSchema.dll:

Note: Since we're using PowerShell 7.x.x, use the NJsonSchema.dll file in the netstandard2.0 folder.

$Assembly = [System.Reflection.Assembly]::Loadfile('C:\Users\CpUser\.nuget\packages\njsonschema\10.4.0\lib\netstandard2.0\NJsonSchema.dll')

Get Loaded Assemblies (again):

[System.AppDomain]::CurrentDomain.GetAssemblies()

enter image description here

Check the version of NJsonSchema.dll:

$Assembly.GetName()

enter image description here

Tu deschizi eu inchid
  • 4,117
  • 3
  • 13
  • 24
  • I set `$env:PATH` and `$env:PSModulePath` to a single directory (the location of the DLL I'm loading) and it *STILL* fails. When I call `Load("NJsonSchema")`, it *still* loads it from the Program Files location. This is driving me nuts. – void.pointer May 06 '21 at 13:33