mRemoteNG icon indicating copy to clipboard operation
mRemoteNG copied to clipboard

Using Powershell Reflection.Assembly to interact with mRemoteNG

Open adilias3 opened this issue 3 years ago • 3 comments

Hi All,

I've been using powershell [System.Reflection.Assembly]::LoadFile to create connection files in previous versions.

Similar to : https://github.com/realslacker/PSmRemoteNG

In the latest 1.77 versions of mRemoteNG, this no longer works.

I'm attempting to run this within the latest version of VS Code, on an upto date Windows 10 PC.

Expected Behavior

In Previous versions I've been able to create mRemoteNG objects in powershell by doing:

[void][System.Reflection.Assembly]::LoadFile( "1.76\mRemoteNG.exe" )
[void][System.Reflection.Assembly]::LoadFile( "1.76\BouncyCastle.Crypto.dll" )

$RootNode = [mRemoteNG.Tree.Root.RootNodeInfo]::new($RootNodeType)

Current Behavior

[void][System.Reflection.Assembly]::LoadFile( "1.77.2\mRemoteNG.dll" )
[void][System.Reflection.Assembly]::LoadFile( "1.77.2\BouncyCastle.Crypto.dll" )

$RootNode = [mRemoteNG.Tree.Root.RootNodeInfo]::new('Connection')

In version 1.77.2, I get the following error

Could not load type 'System.Runtime.Versioning.TargetPlatformAttribute' from assembly 
'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
At C:\repos\mremoteng-tree\createfile.ps1:13 char:1
+ $RootNode = [mRemoteNG.Tree.Root.RootNodeInfo]::new('Connection')
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], TypeLoadException
    + FullyQualifiedErrorId : System.TypeLoadException

adilias3 avatar Jul 29 '22 02:07 adilias3

hello, need to check but we move to new .net 6 so just guessing you may not have it installed, try to install .NET Desktop Runtime 6.0.7 perhaps

Kvarkas avatar Jul 29 '22 10:07 Kvarkas

Unfortunately, that didn't help. .NET SDK 6 is already installed.

Strangely I can interact with parts of the assembly, for example, I can do:

[mRemoteNG.Connection.ConnectionInfo].GetProperties()

But not:

$RootNode = [mRemoteNG.Tree.Root.RootNodeInfo]::new('Connection')

I receive the error noted in the original post.

adilias3 avatar Aug 01 '22 03:08 adilias3

Hey all,

the major issue is described here: https://learn.microsoft.com/de-de/powershell/scripting/install/powershell-support-lifecycle?view=powershell-7.3

After updating to the .NET 6 Desktop environment, Powershell 2, 3, and 5 are no longer supported for loading mRemoteNG assemblies. I have verified this with Powershell 5 and the portable versions Stable (v1.76.20) and Preview (v1.77.1) run fine with Powershell 5.1, which is the default and latest version of Microsoft's OS-built Powershell for Windows 10/11.

If you want to use Powershell with the latest Nightly version, you need to use Powershell 7. PS7 supports .NET 6.0/7 or 8 in previous versions. You can check this with the following simple PS cmd:

[System.Runtime.InteropServices.RuntimeInformation]::FrameworkDescription

Additionally, you need to load assemblies like this:

[void][System.Reflection.Assembly]::LoadFile("$mRemoteNGPath\mRemoteNG.dll")
[void][System.Reflection.Assembly]::LoadFile("$mRemoteNGPath\BouncyCastle.Crypto.dll")`

instead of this

[void][System.Reflection.Assembly]::LoadFile("$mRemoteNGPath\mRemoteNG.exe")
[void][System.Reflection.Assembly]::LoadFile("$mRemoteNGPath\BouncyCastle.Crypto.dll")

and be sure, you unblocked all files:

gci $PathTomRemoteNG -Recurse | ForEach-Object {$_ | Unblock-File}

I tested it with your example; therefore, I didn't check each other functionality:

$RootNode = [mRemoteNG.Tree.Root.RootNodeInfo]::new('Connection')
$RootNode

It seems like an issue when using the wrong PowerShell versions. Download and install PowerShell 7 from here: https://learn.microsoft.com/de-de/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.3

Please test it, and if successful, you can happily use the latest Nightly build with PowerShell 7! If, however, downgrading the .NET environment is not a feasible option, please consider keeping an eye on any updates or alternative solutions that may arise.

King reguarts!

P.S.: My full script i have tested with. Its only functinal and a fast check:

$mRemoteNGPath = "Your Path to mRemoteNG"
gci $mRemoteNGPath -Recurse | ForEach-Object {$_ | Unblock-File}

# Get the FrameworkDescription string
$frameworkDescription = [System.Runtime.InteropServices.RuntimeInformation]::FrameworkDescription
# Parse the version from the string
$versionMatch = $frameworkDescription -match '\d+\.\d+\.\d+'
if ($versionMatch)
{
    $versionString = $matches[0]
}
else {
    $versionString = $frameworkDescription -replace '[^\d.]'
}

try {
    $dotNetVersion = [version]$versionString
}
catch {
    throw $_
}

$MRNGVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo( "$mRemoteNGPath\mRemoteNG.exe" ).FileVersionRaw

Write-Host mRemoteNG:
$MRNGVersion
Write-Host

Write-Host PSVersion:
$PSVersionTable.PSVersion
Write-Host

Write-Host .NetVersion
$dotNetVersion

try {
    if ( $MRNGVersion.ToString() -eq "1.76.20.24669" -or $version -eq "1.77.1.27713") {
        [void][System.Reflection.Assembly]::LoadFile( "$mRemoteNGPath\mRemoteNG.exe" )
        [void][System.Reflection.Assembly]::LoadFile( "$mRemoteNGPath\BouncyCastle.Crypto.dll" )
    }
    elseif ($MRNGVersion.ToString() -match "1.77.3.*" ){
            # Check if the version is less than 6
        if ($dotNetVersion -lt [version]'6.0.0.0') {
            throw ".Net build in Version of PS to low"
        }

        [void][System.Reflection.Assembly]::LoadFile( "$mRemoteNGPath\mRemoteNG.dll")
        [void][System.Reflection.Assembly]::LoadFile( "$mRemoteNGPath\BouncyCastle.Crypto.dll" )
    }

    $RootNode = [mRemoteNG.Tree.Root.RootNodeInfo]::new('Connection')
    $RootNode
}
catch {
    # Display detailed error information
    Write-Host "Failed to load the assembly. Error details:"
    Write-Host "Exception Type: $($_.Exception.GetType().FullName)"
    Write-Host "Message: $($_.Exception.Message)"
    Write-Host "StackTrace: $($_.Exception.StackTrace)"
    Write-Host "InnerException: $($_.Exception.InnerException)"
}




xRushG avatar Nov 15 '23 21:11 xRushG