Public/Get-emsIsInteractiveHost.ps1

<#PSScriptInfo
 
.VERSION 1.0.0
 
.GUID 15d830b0-9874-4d43-a17a-099579251e12
 
.AUTHOR enthus Managed Services GmbH
 
.COMPANYNAME enthus Managed Services GmbH
 
#>


#Requires -Version 5.1

<#
    .SYNOPSIS
    Checks if the current PowerShell host supports interactive user input.
 
    .DESCRIPTION
    This cmdlet checks if the current PowerShell host environment supports interactive user input by testing the availability of virtual terminal support and RawUI capabilities. This is essential for functions that require user interaction such as prompts or menu selections.
 
    The function returns $true if the host supports interactive operations, and $false if it's running in a non-interactive environment (such as Azure Automation, scheduled tasks, or headless execution).
 
    .NOTES
    PSVersion: 5.1.x or 7.2.x
 
    ENVIRONMENT:
    [x] Azure Automation
    [x] Azure Function
    [x] Local
    [x] Nerdio
    [x] PowerShell Universal
    [x] Server
    [ ] ...
 
    REQUIRED CONTEXT:
    [x] Application && Delegated
    [x] Application
    [x] Delegated
    [x] User
 
    REQUIRED PERMISSIONS:
    - None
 
    .INPUTS
    None. This cmdlet does not accept pipeline input.
 
    .OUTPUTS
    System.Boolean. Returns $true if the host supports interactive operations, $false otherwise.
 
    .EXAMPLE
    $isInteractive = Get-emsIsInteractiveHost
    if ($isInteractive) {
        # Proceed with interactive operations
        $userInput = Read-Host "Please enter a value"
    } else {
        # Use default values or throw an error
        throw "This script requires an interactive PowerShell host."
    }
 
    Checks if the host is interactive and handles both cases appropriately.
 
    .EXAMPLE
    if (Get-emsIsInteractiveHost) {
        Write-Host "Running in interactive mode"
    } else {
        Write-Warning "Running in non-interactive mode"
    }
 
    Simple check with conditional logic for interactive vs non-interactive execution.
#>

function Get-emsIsInteractiveHost {
    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param()

    $verbosePrefix = "Get-emsIsInteractiveHost | "

    try {
        $supportsVirtualTerminal = $Host.UI.SupportsVirtualTerminal
        $hasRawUI = $null -ne $Host.UI.RawUI

        # Try to access RawUI properties that indicate real interactivity capabilities
        $hasInteractiveRawUI = $false
        if ($hasRawUI) {
            try {
                # Check if we can actually read console properties (fails in non-interactive environments)
                $bufferSize = $Host.UI.RawUI.BufferSize
                $hasInteractiveRawUI = $bufferSize.Width -gt 0 -or $bufferSize.Height -gt 0
            } catch {
                # If accessing BufferSize fails, it's likely a dummy RawUI implementation
                $hasInteractiveRawUI = $false
            }
        }

        $isInteractive = $supportsVirtualTerminal -or $hasInteractiveRawUI

        Write-Verbose "$($verbosePrefix)SupportsVirtualTerminal: $supportsVirtualTerminal"
        Write-Verbose "$($verbosePrefix)HasRawUI: $hasRawUI"
        Write-Verbose "$($verbosePrefix)HasInteractiveRawUI: $hasInteractiveRawUI"
        Write-Verbose "$($verbosePrefix)IsInteractive: $isInteractive"

        Write-Output $isInteractive
    }
    catch {
        Write-Verbose "$($verbosePrefix)Exception occurred during host capability check: $($_.Exception.Message)"

        # If we can't determine the capabilities, assume non-interactive for safety
        Write-Output $false
    }
}