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 NoExit switch prevents the PowerShell console window from closing after running the script. When you double click on the PowerShell script file, or run with the PowerShell option, the script will execute quickly and then disappear.
Global Fix: Change your registry key by adding the -NoExit switch to always leave the PowerShell Console window open after the script finishes running.
So, let's check out how you can disable the PowerShell Startup status on the Task Manager: Press Ctrl + Shift + Esc to open the Task Manager. Navigate to the Startup tab. Right-click on the Windows PowerShell option and select Disable.
You can use Get-Error to display a specified number of errors that have occurred in the current session using the Newest parameter. The Get-Error cmdlet also receives error objects from a collection, such as $Error , to display multiple errors from the current session.
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." }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With