Reputation: 1572
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.
Upvotes: 77
Views: 222082
Reputation: 485
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.
Upvotes: 7
Reputation: 9634
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\\\"\""
Upvotes: 1
Reputation: 1157
This will make the PowerShell window wait until you press the Enter key (not any key):
pause
Upvotes: 60
Reputation: 24424
You basically have three options to prevent the PowerShell Console window from closing, that I describe in more detail in my blog post.
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"
Per-script Fix: Add a prompt for input to the end of your script file. E.g., Read-Host -Prompt "Press Enter to exit"
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."
}
Upvotes: 158