How can prevent a PowerShell window from closing so I can see the error?

Powershell

Powershell Problem Overview


I'm creating a local PowerShell module downloader script. The module and the script are held on a network share. The script is invoke using:

& '\\net\DSFShare\Shared Data\Powershell Modules\Install-MyModuleManager.ps1'

It copies the script to the standard profile modules folder and then runs Install.ps1 from the module folder. Install.ps1 elevates itself, if needed. Just before the elevated window closes, a red error pops up, but the window closes too quickly for me to see the error. How can I find out what the error is?

The downloader script invokes the installer using:

$installerPath = [IO.Path]::Combine($LocalModulePath, 'Install.ps1')
Write-Host "Installer path: $installerPath"
if (Test-Path $installerPath) {
    Write-Host 'Install.ps1 exists.  Running Install.ps1'
    & $installerPath
}

Note, if from PowerShell, I populate $installerPath and call it using & $installerPath, I don't see the error.

I've checked the Application, System, Windows PowerShell, and Security event logs. There aren't any errors relating to this.

All the script does is create an event source. If you want to run it, you can use:

Remove-EventLog -Source 'My.Module.Manager'

afterwards, to remove it. Here's the script:

Write-Host "Installing module..."
$eventSource = 'My.Module.Manager'

try {
    $sourceExists = [System.Diagnostics.EventLog]::SourceExists($eventSource)
} catch [Security.SecurityException] {
    Write-Verbose "Caught 'SecurityException': $_.Exception.Message"
}

if ($sourceExists) {
    Write-Host "...installation complete..."
} else {

    #region ----- Ensure-ProcessIsElevated -----

    if ($Verbose) {
        $VerbosePreference = "Continue"
    }
    if ($Debug) {
        $DebugPreference = "Continue"
    }

    Write-Debug "Command line is ___$($MyInvocation.Line)___"
    Write-Verbose "Entering script body"

    if ($ScriptPath) {
        Set-Location $ScriptPath
        Write-Verbose "Working directory: $pwd"
    }

    If (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
        Write-Warning "This script must be run with elevated privileges."
        Write-Warning "Restarting as an elevated process."
        Write-Warning "You will be prompted for authorization."
        Write-Warning "You may click 'No' and re-run manually, if you prefer."

        If ((Get-WmiObject Win32_OperatingSystem | select BuildNumber).BuildNumber -ge 6000) {
            Write-Verbose "This is a UAC-enabled system. Elevating ..."
            $CommandLine = "$($MyInvocation.Line.Replace($MyInvocation.InvocationName, $MyInvocation.MyCommand.Definition)) -ScriptPath $pwd"
            Write-Verbose "CommandLine: $CommandLine"

            Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList "$CommandLine"

        } else {
            Write-Verbose "The system does not support UAC: an elevated process cannot be started."
            Write-Warning "This script requires administrative privileges. Please re-run with administrative account."
        }

        Break
    }

    Write-Verbose "The script is now running with elevated privileges."

    #endregion ----- Ensure-ProcessIsElevated -----

    New-EventLog -LogName Application -Source $eventSource

    Write-Host "...installation complete..."
}

I'm using PowerShell 4.0.

Powershell Solutions


Solution 1 - Powershell

You basically have three options to prevent the PowerShell Console window from closing, that I describe in more detail in my blog post.

  1. One-time Fix: Run your script from the PowerShell Console, or launch the PowerShell process using the -NoExit switch. E.g., PowerShell -NoExit "C:\SomeFolder\SomeScript.ps1"

  2. Per-script Fix: Add a prompt for input to the end of your script file. E.g., Read-Host -Prompt "Press Enter to exit"

  3. Global Fix: Change your registry key to always leave the PowerShell Console window open after the script finishes running. Here's the two registry keys that would need to be changed:

    ● Open With → Windows PowerShell
    When you right-click a .ps1 file and choose Open With

    Registry Key: HKEY_CLASSES_ROOT\Applications\powershell.exe\shell\open\command

    Default Value:

    "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "%1"
    

    Desired Value:

    "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "& \"%1\""
    

    ● Run with PowerShell
    When you right-click a .ps1 file and choose Run with PowerShell (shows up depending on which Windows OS and Updates you have installed).

    Registry Key: HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\0\Command

    Default Value:

    "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-Command" "if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & '%1'"
    

    Desired Value:

    "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -NoExit "-Command" "if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & \"%1\""
    

You can download a .reg file from my blog to modify the registry keys for you if you don't want to do it manually.

It sounds like you likely want to use option #2. You could even wrap your whole script in a try block, and only prompt for input if an error occurred, like so:

try
{
    # Do your script's stuff
}
catch
{
    Write-Error $_.Exception.ToString()
    Read-Host -Prompt "The above error occurred. Press Enter to exit."
}

Solution 2 - Powershell

This will make the PowerShell window wait until you press the Enter key (not any key):

pause

Solution 3 - Powershell

Also simple and easy:

Start-Sleep 10

Solution 4 - Powershell

The simplest and easiest way is to execute your particular script with -NoExit param.

1.Open run box by pressing:

> Win + R

2.Then type into input prompt:

PowerShell -NoExit "C:\folder\script.ps1"

and execute.

Solution 5 - Powershell

I'm adding the Registry script to leave the PowerShell window open after it completes.

I took it from blog.danskingdom.com

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Applications\powershell.exe\shell\open\command]
@="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoExit \"& \\\"%1\\\"\""

[HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\0\Command]
@="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoExit \"-Command\" \"if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & \\\"%1\\\"\""

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2871239View Question on Stackoverflow
Solution 1 - PowershelldeadlydogView Answer on Stackoverflow
Solution 2 - PowershellAmr BahaaView Answer on Stackoverflow
Solution 3 - PowershellPaul FijmaView Answer on Stackoverflow
Solution 4 - PowershellRostyslav ZhalivtsivView Answer on Stackoverflow
Solution 5 - PowershellAlper EbicogluView Answer on Stackoverflow