Chris
Chris

Reputation: 238

Determine which interpreter is executing a powershell script

I have a powershell script that checks if it's admin, and if not relaunches as admin. However, I've had to add a parameter to tell the script what interpreter to use on relaunch (pwsh.exe or powershell.exe in particular). Is there a way to tell which .exe is executing the script?

param (
    [string]$AdminShell = "powershell.exe"
)

# Check if the script is running as administrator
if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
    # Restart the script as administrator
    Start-Process -FilePath $AdminShell -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File $($MyInvocation.MyCommand.Path)" -Verb RunAs
    Exit
}

Upvotes: 2

Views: 71

Answers (2)

mklement0
mklement0

Reputation: 439822

To complement Santiago's helpful answer:

  • An alternative cross-edition solution (i.e. one that works in both Windows PowerShell and PowerShell (Core) 7, as you requested):

    [System.Diagnostics.Process]::GetCurrentProcess().MainModule.FileName
    
  • A simpler, PowerShell 7-only solution that is the equivalent of the above:

    [Environment]::ProcessPath
    

A note re [System.Environment]::GetCommandLineArgs()[0]:

  • It is only .NET executables invoked from PowerShell that are guaranteed to see a full path, because PowerShell itself resolves relative or $env:PATH-based executable paths to full ones before invocation.

  • .NET executables invoked from outside PowerShell, such as via cmd.exe or when using the System.Diagnostics.Process API, see the target executable as specified on the invocation command line, which therefore may be a relative path, or a name only.

    • The latter introduces ambiguity, as an invocation name of foo may either refer to an executable by that name in the current directory or one that can be located via $env:PATH.

    • It is for that reason that the solutions in the top section are generally preferable, as is (Get-Process -Id $PID).Path.

Upvotes: 1

Santiago Squarzon
Santiago Squarzon

Reputation: 60848

You can use GetCommandLineArgs to determine it. The first argument (index 0) will be the shell's absolute path.

[System.IO.Path]::ChangeExtension([System.Environment]::GetCommandLineArgs()[0], 'exe')

Another option is with Get-Process using $PID automatic variable:

(Get-Process -Id $PID).Path

A third option is pointed out by Mathias in comments, using either $PSVersionTable or $IsCoreCLR, both options should be valid:

if ($IsCoreCLR) {
    Join-Path $PSHOME pwsh.exe
}
else {
    Join-Path $PSHOME powershell.exe
}

Upvotes: 2

Related Questions