Below is a small sample of the script that I am making. I need it to work in PowerShell 5.1 At the moment it only works in PS7. I installed the package "System.IdentityModel.Tokens.Jwt 7.0.3" and copied the dll's I am referencing in the script folder. When I run this script in PS7 I get ouput from "new-object Microsoft.IdentityModel.Tokens.X509SigningCredentials($x509cert)" On PS5.1 I get the error:
System.Management.Automation.MethodInvocationException: Exception calling ".ctor" with "1" argument(s): "The type initializer for 'PerTypeValues`1' threw an exception." ---> System.TypeInitializationException: The type initializer for 'PerTypeValues`1' threw an exception. ---> System.IO.FileNotFoundException: Could not load file or assembly 'System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
at System.SpanHelpers.PerTypeValues`1.MeasureArrayAdjustment()
at System.SpanHelpers.PerTypeValues`1..cctor()
--- End of inner exception stack trace ---
at Microsoft.IdentityModel.Tokens.Base64UrlEncoder.Encode(Byte[] inArray, Int32 offset, Int32 length)
at Microsoft.IdentityModel.Tokens.X509SecurityKey..ctor(X509Certificate2 certificate)
at Microsoft.IdentityModel.Tokens.SigningCredentials..ctor(X509Certificate2 certificate)
at Microsoft.IdentityModel.Tokens.X509SigningCredentials..ctor(X509Certificate2 certificate)
--- End of inner exception stack trace ---
at System.Management.Automation.DotNetAdapter.AuxiliaryConstructorInvoke(MethodInformation methodInformation, Object[] arguments, Object[] originalArguments)
at System.Management.Automation.DotNetAdapter.ConstructorInvokeDotNet(Type type, ConstructorInfo[] constructors, Object[] arguments)
at Microsoft.PowerShell.Commands.NewObjectCommand.CallConstructor(Type type, ConstructorInfo[] constructors, Object[] args)
Can someone explain to me what the difference is between 5.1 and 7 other than .NET version? And why this piece of code won't run on 5.1?
$CertPassWord = "password" # Password used for creating the certificate
$CertificatePath_Pfx = "C:\Temp\Certs\test.pfx" # Path where the certificate is saved
[System.Reflection.Assembly]::LoadFrom("C:\Temp\Certs\Microsoft.IdentityModel.Tokens.dll")
$x509cert = new-object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath_Pfx, $CertPassWord)
new-object Microsoft.IdentityModel.Tokens.X509SigningCredentials($x509cert)
I found the problem why it wasn't running in PS 5.1. I updated my question with the detailed exception. The dll "System.Runtime.CompilerServices.Unsafe.dll" wasn't loaded in PowerShell session causing the script to fail. In PS 7 this dll is loaded by default. I only had a newer version then was expected so I needed a binding redirect in PowerShell 5.1. I got the way to do that from this question: Powershell config assembly redirect
This is my example script that is working in PS 5.1
$CertPassWord = "password" # Password used for creating the certificate
$CertificatePath_Pfx = "C:\Temp\Certs\test.pfx" # Path where the certificate is saved
[System.Reflection.Assembly]::LoadFrom("C:\Temp\Certs\Microsoft.IdentityModel.Tokens.dll")
[System.Reflection.Assembly]::LoadFrom("C:\Temp\Certs\System.Runtime.CompilerServices.Unsafe.dll")
$OnAssemblyResolve = [System.ResolveEventHandler] {
param($sender, $e)
$searchFor = $null
if ($e.Name -match "(.*?), .*") {
$searchFor = $matches[1]
}
foreach ($a in [System.AppDomain]::CurrentDomain.GetAssemblies()) {
Write-Host $a
$foundItem = $null
if ($a.FullName -match "(.*?), .*") {
$foundItem = $matches[1]
}
if ($foundItem -eq $searchFor) {
return $a
}
}
return $null
}
[System.AppDomain]::CurrentDomain.add_AssemblyResolve($OnAssemblyResolve)
try {
$x509cert = new-object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath_Pfx, $CertPassWord)
new-object Microsoft.IdentityModel.Tokens.X509SigningCredentials($x509cert)
}
catch {
Write-Host "An error occurred:"
Write-Host $_.Exception
}