Private/Get-HDTPowerShellPath.ps1
|
function Get-HDTPowerShellPath { <# .SYNOPSIS Returns the PowerShell console host that a relaunch may start. .DESCRIPTION A HOST IS NOT ALWAYS A CONSOLE, and Start-HDTConsole assumed it was. It relaunched GetCurrentProcess().MainModule.FileName, which is right in powershell.exe and wrong everywhere else. In the ISE that resolves to powershell_ise.exe, and the ISE takes exactly three parameters - -File, -Mta and -NoProfile. It has never had -STA. So Start-HDTConsole -Detach C:\HDTLab\Share from the ISE started a second ISE with a switch the ISE does not have, and reported an error about STA from the command whose whole job is getting the apartment right. The same hole is open in any WPF or WinForms application hosting PowerShell, and in anything embedding System.Management.Automation: none of them can be handed -File and told to run a script. $PSHOME IS THE ANSWER because it is where the console host that matches THIS engine lives - the 5.1 directory under the ISE, the pwsh directory under pwsh. Picking powershell.exe off PATH would silently move a pwsh 7 session onto 5.1. .PARAMETER ProcessPath The executable of the process asking - normally [Diagnostics.Process]::GetCurrentProcess().MainModule.FileName. .PARAMETER InstallPath Where to look when ProcessPath is not a console host. Normally $PSHOME. .OUTPUTS System.String - the full path of a console host. .EXAMPLE Get-HDTPowerShellPath -ProcessPath 'C:\...\powershell_ise.exe' -InstallPath $PSHOME C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe .LINK Start-HDTConsole #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $ProcessPath, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $InstallPath ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' $leaf = [System.IO.Path]::GetFileName($ProcessPath) if (@('powershell.exe', 'pwsh.exe') -contains $leaf) { return $ProcessPath } foreach ($candidate in @('pwsh.exe', 'powershell.exe')) { $path = Join-Path -Path $InstallPath -ChildPath $candidate if (Test-Path -LiteralPath $path -PathType Leaf) { return $path } } # IT NAMES THE HOST AND THE DIRECTORY. "STA" as an error sends somebody to # read about apartment states; the cause is that the thing they are typing # into cannot run a script file, and only this message can say so. throw ("'{0}' is not a PowerShell console host, and neither pwsh.exe nor powershell.exe is in '{1}'. Open the console from powershell.exe or pwsh.exe, or run Show-HDTConsole here instead - this host is already STA." -f $leaf, $InstallPath) } |