Functions/GenXdev.Windows/Invoke-CommandElevated.ps1
|
<############################################################################## Part of PowerShell module : GenXdev.Windows Original cmdlet filename : Invoke-CommandElevated.ps1 Original author : René Vaessen / GenXdev Version : 3.29.2026 ################################################################################ Copyright (c) 2026 René Vaessen / GenXdev Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ################################################################################> <# .SYNOPSIS Runs code in an elevated PowerShell session, streaming output back to the original terminal. .DESCRIPTION Ensures a scriptblock is executed in an elevated (admin) session using a proper user-experience. After the scriptblock has completed, the environment variables are updated to reflect any changes made in the elevated session. In contrast to other Environment variables, the directories in $ENV:PATH is merged. .PARAMETER ScriptBlock Scriptblock to execute in elevated session .PARAMETER JobDescription Description of the job to be displayed in the window title .PARAMETER PauseAfterCompletion Optionally pauses after the scriptblock has completed .PARAMETER DontUpdateEnvironment Optionally skips updating the environment after the elevated session has completed. .EXAMPLE Invoke-CommandElevated { sfc /scannow } -PauseAfterCompletion #> function Invoke-CommandElevated { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 0, HelpMessage = "Scriptblock to execute in elevated session")] [ScriptBlock] $ScriptBlock, [Parameter(Mandatory = $false, Position = 1, HelpMessage = "Description of the job to be displayed in the window title")] [String] $JobDescription = "Launching elevated session", [Parameter(Mandatory = $false, HelpMessage = "Optionally pauses after the scriptblock has completed")] [Switch] $PauseAfterCompletion, [Parameter(Mandatory = $false, HelpMessage = "Optionally skips updating the environment after the elevated session has completed.")] [Switch] $DontUpdateEnvironment ) if (GenXdev\CurrentUserHasElevatedRights) { Microsoft.PowerShell.Core\Invoke-Command -ScriptBlock $ScriptBlock return } 1..25 | Microsoft.PowerShell.Core\ForEach-Object { Microsoft.PowerShell.Utility\Write-Progress -Id 11232 -Activity "$JobDescription" -Status "Prepare for upcoming UAC prompt.." -PercentComplete $_ Microsoft.PowerShell.Utility\Start-Sleep -Milliseconds 80 } [System.Diagnostics.Process] $process; try { $CurrentWindow = GenXdev\Get-PowershellMainWindow $command = @" `$ErrorOccurred = `$false; `$Host.UI.RawUI.WindowTitle = "$JobDescription" Import-Module -Name GenXdev -Version '3.29.2026'; GenXdev\Set-WindowPosition -X $($CurrentWindow.Left) -Y $($CurrentWindow.Top) -Width $($CurrentWindow.Width) -Height $($CurrentWindow.Height) -SetRestored -SetForeground; GenXdev\Set-WindowPosition -Process (Get-Process -Pid `$PID) -X $($CurrentWindow.Left) -Y $($CurrentWindow.Top) -Width $($CurrentWindow.Width) -Height $($CurrentWindow.Height) -SetRestored -SetForeground; try { 1..10 | % { Write-Progress -Id 11233 -Activity "$JobDescription" -Status "Executing elevated command.." -PercentComplete (`$_ * 10) Start-Sleep -Milliseconds 200 } Write-Progress -Id 11233 -PercentComplete 100 -Completed Write-Host "--------------------" -foregroundcolor Cyan; Write-Host "$JobDescription" -foregroundcolor Yellow; Write-Host "--------------------" -foregroundcolor Cyan; $ScriptBlock Write-Host "--------------------" -foregroundcolor Cyan; $($PauseAfterCompletion ? 'Pause' : '') } catch { `$ErrorOccurred = `$true; Write-Progress -Id 11233 -Activity "$JobDescription" -Status "Error occured!" -PercentComplete 100 -Completed Write-Host "--------------------" -foregroundcolor Cyan; GenXdev\Show-ExceptionPanel `$PSItem.Exception Write-Host "--------------------" -foregroundcolor Cyan; Pause } finally { 1..10 | % { Write-Progress -Id 11233 -Activity "$JobDescription" -Status "Returning to previous session" -PercentComplete (`$_ * 10) Start-Sleep -Milliseconds 200 } Write-Progress -Id 11233 -Activity "$JobDescription" -Status "Returning to previous session" -PercentComplete 100 -Completed Exit (`$ErrorOccurred ? 1 : 0) } "@; Microsoft.PowerShell.Utility\Write-Verbose "Elevating command: $command" $encodedCommand = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($command)); $arguments = @( "-NoProfile", "-NoLogo", "-MTA", "-EncodedCommand", $encodedCommand ); $process = Microsoft.PowerShell.Management\Start-Process ` -FilePath (Microsoft.PowerShell.Management\Get-Process -Pid $PID).Path ` -ArgumentList $arguments ` -WorkingDirectory $PWD.Path ` -WindowStyle Minimized ` -Verb "RunAs" ` -PassThru; if (-not $process) { throw "User cancelled" } Microsoft.PowerShell.Utility\Write-Progress -Id 11232 -Activity "$JobDescription" -Status "Loading PowerShell modules.." -PercentComplete 25 } catch { Microsoft.PowerShell.Utility\Write-Progress -Id 11232 -PercentComplete 100 -Completed throw "User cancelled" } $i = 25; while (-not $process.HasExited) { Microsoft.PowerShell.Utility\Write-Progress -Id 11232 -Activity "$JobDescription" -Status "Loading PowerShell modules.." -PercentComplete ([Math]::Min(75, $i++)) Microsoft.PowerShell.Utility\Start-Sleep -Milliseconds 250 } $errorOccurred = $process.ExitCode -ne 0 if ($errorOccurred) { 75..100 | Microsoft.PowerShell.Core\ForEach-Object { Microsoft.PowerShell.Utility\Write-Progress -Id 11232 -Activity "$JobDescription" -Status ($errorOccurred ? "Completed with error!" : "Completed") -PercentComplete $_ Microsoft.PowerShell.Utility\Start-Sleep -Milliseconds 80 } } Microsoft.PowerShell.Utility\Write-Progress -Id 11232 -PercentComplete 100 -Completed if (-not $DontUpdateEnvironment) { GenXdev\Update-Environment } GenXdev\Set-WindowPosition -SetForeground -RestoreFocus } |