Detecting Windows Terminal with PowerShell

In the evolving landscape of software development and system administration, understanding your environment is essential for ensuring that scripts and commands run as expected. One useful PowerShell function that helps identify whether a script is running within Windows Terminal is my Test-IsWindowsTerminal function. This function is valuable for developers and system administrators who must tailor their scripts based on the terminal environment.

Overview

Test-IsWindowsTerminal is a PowerShell function designed to determine if the current session is running inside Windows Terminal. Windows Terminal is a modern, feature-rich terminal application for users of command-line tools and shells like PowerShell, WSL, and the Command Prompt. The function employs a hierarchical parent process test to determine if Windows Terminal is part of the process tree.

Details

The code for the Test-IsWindowsTerminal function is shown in the following example.

 1function Test-IsWindowsTerminal {
 2    [CmdletBinding()]
 3    param ()
 4
 5    # Check if PowerShell version is 5.1 or below, or if running on Windows
 6    if ($PSVersionTable.PSVersion.Major -le 5 -or $IsWindows -eq $true) {
 7        $currentPid = $PID
 8
 9        # Loop through parent processes to check if Windows Terminal is in the hierarchy
10        while ($currentPid) {
11            try {
12                $process = Get-CimInstance Win32_Process -Filter "ProcessId = $currentPid" -ErrorAction Stop -Verbose:$false
13            } catch {
14                # Return false if unable to get process information
15                return $false
16            }
17
18            Write-Verbose -Message "ProcessName: $($process.Name), Id: $($process.ProcessId), ParentId: $($process.ParentProcessId)"
19
20            # Check if the current process is Windows Terminal
21            if ($process.Name -eq 'WindowsTerminal.exe') {
22                return $true
23            } else {
24                # Move to the parent process
25                $currentPid = $process.ParentProcessId
26            }
27        }
28
29        # Return false if Windows Terminal is not found in the hierarchy
30        return $false
31    } else {
32        Write-Verbose -Message 'Exiting due to non-Windows environment'
33        return $false
34    }
35}

Components

  • CmdletBinding attribute: This attribute allows the function to use cmdlet features like parameter validation and verbose output.

  • Parameters: The function takes no parameters except the common parameters provided by CmdletBinding. The param() declaration must be present to use the CmdletBinding attribute.

  • Version and environment:

    1if ($PSVersionTable.PSVersion.Major -le 5 -or $IsWindows -eq $true) {
    

    This condition checks if you're running Windows PowerShell or PowerShell on a Windows system. The $IsWindows automatic variable is only available on PowerShell version 6 and higher by default. The function returns $false for non-Windows environments since Windows Terminal is Windows only.

  • Process hierarchy loop:

    1while ($currentPid) {
    

    The function uses the current process ID and iterates through its parent processes to determine if any are WindowsTerminal.exe. The loop checks every process in the hierarchy unless it finds WindowsTerminal.exe because Windows Terminal may not be the immediate parent.

  • Process retrieval:

    1$process = Get-CimInstance Win32_Process -Filter "ProcessId = $currentPid" -ErrorAction Stop -Verbose:$false
    

    This command retrieves the process information based on the process ID. Get-CimInstance is used because Get-Process in Windows PowerShell doesn't include information about the parent process. Using -ErrorAction Stop ensures that any error fetching the process information stops the function. -Verbose:$false suppresses verbose output for this command to prevent extra noise from being added to the output when verbose logging is enabled.

  • Verbose logging:

    1Write-Verbose -Message "ProcessName: $($process.Name), Id: $($process.ProcessId), ParentId: $($process.ParentProcessId)"
    

    Verbose logging provides detailed output for debugging purposes, showing the name, ID, and parent ID of each process.

  • Terminal detection:

    1if ($process.Name -eq 'WindowsTerminal.exe') {
    2    return $true
    3}
    

    If a process named WindowsTerminal.exe is found, the function returns $true, indicating that PowerShell is running within Windows Terminal.

  • Parent process traversal:

    1$currentPid = $process.ParentProcessId
    

    If the current process isn't Windows Terminal, the function moves to the parent process and continues the test.

  • Default return:

    1return $false
    

    If the loop completes without finding Windows Terminal, the function returns $false.

Usage

To use the Test-IsWindowsTerminal function, define it in your PowerShell session and call it when needed.

This function is helpful for scenarios where specific behaviors or configurations are needed when running inside Windows Terminal. It allows for a more tailored and efficient command-line experience.

Summary

The Test-IsWindowsTerminal function is a concise and efficient way to determine if the current PowerShell host is Windows Terminal. By leveraging parent process checks and robust error handling, this function provides a reliable method to tailor scripts based on the terminal environment.

Similar techniques can detect other terminal environments, making it easy to adapt your scripts to different command-line interfaces.

References

Acknowledgments

Thanks to Sean Wheeler for the following tip and for helping resolve a bug in my code.

Other methods of checking the terminal environment, such as testing for the presence of WT_SESSION or WT_PROFILE_ID environment variables, aren't used because they provide false positives due to being inherited if you open another host such as VS Code from Windows Terminal.