param([Parameter(Mandatory=$true)][string]$OutFile, [Parameter(Mandatory=$true)][string]$Work) $lines = New-Object System.Collections.Generic.List[string] function L($s) { $lines.Add($s) } L ("PSVersion: " + $PSVersionTable.PSVersion + " CLR " + [System.Environment]::Version) L ("Work: " + $Work) $tgNet472 = Join-Path $Work 'tg115\lib\net472\Terminal.Gui.dll' $tgNs21 = Join-Path $Work 'tg115\lib\netstandard2.1\Terminal.Gui.dll' $tgNs20 = Join-Path $Work 'tg115\lib\netstandard2.0\Terminal.Gui.dll' $nstack = Join-Path $Work 'nstack\lib\netstandard2.0\NStack.dll' $scNs20 = Join-Path $Work 'sc049\lib\netstandard2.0\Spectre.Console.dll' L "" L "### STEP 1: try [Reflection.Assembly]::LoadFrom on Terminal.Gui net472 (5.1's native TFM) WITHOUT dependencies ###" try { $a = [System.Reflection.Assembly]::LoadFrom($tgNet472); L (" LoadFrom tg/net472 -> OK: " + $a.FullName) } catch { L (" LoadFrom tg/net472 FAILED: " + $_.Exception.GetType().Name + ': ' + $_.Exception.Message) } L "" L "### STEP 2: try GetTypes() -- this forces dependency resolution ###" if ($a) { try { $ts = $a.GetTypes(); L (" GetTypes() -> OK, " + $ts.Count + " types. Sample: " + (($ts | Select-Object -First 5 | ForEach-Object { $_.FullName }) -join ', ')) } catch { L (" GetTypes() FAILED: " + $_.Exception.GetType().Name + ': ' + $_.Exception.Message) $ie = $_.Exception.InnerException while ($ie) { L (" inner: " + $ie.GetType().Name + ': ' + $ie.Message); $ie = $ie.InnerException } $le = $_.Exception.LoaderExceptions if ($le) { foreach ($x in $le) { L (" loaderEx: " + $x.Message) } } } try { $appType = $a.GetType('Terminal.Gui.Application'); L (" GetType('Terminal.Gui.Application') -> " + $(if ($appType) { 'FOUND: ' + $appType.FullName } else { 'null' })) } catch { L (" GetType(Application) THREW: " + $_.Exception.Message) } } L "" L "### STEP 3: load NStack.Core first (the declared dependency), then Terminal.Gui ###" try { $ns = [System.Reflection.Assembly]::LoadFrom($nstack); L (" LoadFrom NStack.Core/netstandard2.0 -> " + $ns.FullName) } catch { L (" NStack load FAILED: " + $_.Exception.Message) } try { $a2 = [System.Reflection.Assembly]::LoadFrom($tgNet472) $ts2 = $a2.GetTypes() L (" after NStack preload: GetTypes() -> OK, " + $ts2.Count + " types") $appType = $a2.GetType('Terminal.Gui.Application') L (" Terminal.Gui.Application -> " + $(if ($appType) { 'FOUND' } else { 'null' })) } catch { L (" after NStack preload: FAILED " + $_.Exception.GetType().Name + ': ' + $_.Exception.Message) $le = $_.Exception.LoaderExceptions; if ($le) { foreach ($x in $le) { L (" loaderEx: " + $x.Message) } } $ie = $_.Exception.InnerException; while ($ie) { L (" inner: " + $ie.GetType().Name + ': ' + $ie.Message); $ie = $ie.InnerException } } L "" L "### STEP 4: ACTUAL INSTANTIATION + a real TUI win. Does Application.Init() work in 5.1? ###" $didInit = $false try { $a3 = [System.Reflection.Assembly]::LoadFrom($tgNet472) $t = $a3.GetType('Terminal.Gui.Application') L (" Application type: " + $(if ($t) { $t.FullName } else { 'null' })) if ($t) { $init = $t.GetMethod('Init', [Type[]]@()) L (" Application.Init() method found: " + [bool]$init) if ($init) { if ([Console]::IsOutputRedirected) { L " SKIPPING Init() because stdout is redirected (it would hang / corrupt output)" } else { $init.Invoke($null, @()) | Out-Null $didInit = $true L " Application.Init() -> SUCCEEDED on this host" } } } } catch { L (" Application.Init probe FAILED: " + $_.Exception.GetType().Name + ': ' + $_.Exception.Message) $ie = $_.Exception.InnerException; while ($ie) { L (" inner: " + $ie.GetType().Name + ': ' + $ie.Message); $ie = $ie.InnerException } } if ($didInit) { try { $t = ([System.Reflection.Assembly]::LoadFrom($tgNet472)).GetType('Terminal.Gui.Application') $shutdown = $t.GetMethod('Shutdown', [Type[]]@()) if ($shutdown) { $shutdown.Invoke($null, @()) | Out-Null; L " Application.Shutdown() -> called" } } catch { L (" Shutdown failed: " + $_.Exception.Message) } } L "" L "### STEP 5: Spectre.Console netstandard2.0 in this host ###" try { $sc = [System.Reflection.Assembly]::LoadFrom($scNs20) L (" LoadFrom Spectre.Console/netstandard2.0 -> " + $sc.FullName) try { $t2 = $sc.GetTypes(); L (" GetTypes() -> OK, " + $t2.Count + " types") } catch { L (" GetTypes() FAILED: " + $_.Exception.Message); $ie = $_.Exception.InnerException; while ($ie) { L (" inner: " + $ie.GetType().Name + ': ' + $ie.Message); $ie = $ie.InnerException } } try { $ansiType = $sc.GetType('Spectre.Console.AnsiConsole') L (" Spectre.Console.AnsiConsole -> " + $(if ($ansiType) { 'FOUND' } else { 'null' })) if ($ansiType) { $w = $ansiType.GetMethod('Write', [Type[]]@([string])) L (" AnsiConsole.Write(string) overload: " + [bool]$w) } } catch { L (" AnsiConsole probe FAILED: " + $_.Exception.Message) } } catch { L (" LoadFrom Spectre.Console FAILED: " + $_.Exception.GetType().Name + ': ' + $_.Exception.Message) } L "" L "### STEP 6: Add-Type -Path variant (what a user would literally type) ###" try { Add-Type -Path $tgNet472 -ErrorAction Stop; L " Add-Type -Path Terminal.Gui(net472) -> OK" } catch { L (" Add-Type -Path Terminal.Gui(net472) FAILED: " + $_.Exception.Message) } try { Add-Type -Path $scNs20 -ErrorAction Stop; L " Add-Type -Path Spectre.Console(netstandard2.0) -> OK" } catch { L (" Add-Type -Path Spectre.Console(ns2.0) FAILED: " + $_.Exception.Message) } try { Add-Type -Path $tgNs21 -ErrorAction Stop; L " Add-Type -Path Terminal.Gui(netstandard2.1) -> OK" } catch { L (" Add-Type -Path Terminal.Gui(ns2.1) FAILED: " + $_.Exception.Message) } L (" (tg netstandard2.0 path exists? " + (Test-Path $tgNs20) + ")") [System.IO.File]::WriteAllLines($OutFile, $lines, (New-Object System.Text.UTF8Encoding($false)))