PoshCode Logo PowerShell Code Repository

Invoke-ElevatedCommand by Tao Klerks 5 years ago (modification of post by obsidience view diff)
diff | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/3158"></script>download | new post

Corrected the enhanced error handling, added window display option, corrected interactivity of hidden windows, added header area, wrapped in a function.

  1. Function Invoke-ElevatedCommand {
  2.         <#
  3.                 .DESCRIPTION
  4.                         Invokes the provided script block in a new elevated (Administrator) powershell process,
  5.                         while retaining access to the pipeline (pipe in and out). Please note, "Write-Host" output
  6.                         will be LOST - only the object pipeline and errors are handled. In general, prefer
  7.                         "Write-Output" over "Write-Host" unless UI output is the only possible use of the information.
  8.                         Also see Community Extensions "Invoke-Elevated"/"su"
  9.  
  10.                 .EXAMPLE
  11.                         Invoke-ElevatedCommand {"Hello World"}
  12.  
  13.                 .EXAMPLE
  14.                         "test" | Invoke-ElevatedCommand {$input | Out-File -filepath c:\test.txt}
  15.  
  16.                 .EXAMPLE
  17.                         Invoke-ElevatedCommand {$one = 1; $zero = 0; $throwanerror = $one / $zero}
  18.  
  19.                 .PARAMETER Scriptblock
  20.                         A script block to be executed with elevated priviledges.
  21.  
  22.                 .PARAMETER InputObject
  23.                         An optional object (of any type) to be passed in to the scriptblock (available as $input)
  24.  
  25.                 .PARAMETER EnableProfile
  26.                         A switch that enables powershell profile loading for the elevated command/block
  27.  
  28.                 .PARAMETER DisplayWindow
  29.                         A switch that enables the display of the spawned process (for potential interaction)
  30.  
  31.                 .SYNOPSIS
  32.                         Invoke a powershell script block as Administrator
  33.  
  34.                 .NOTES
  35.                         Originally from "Windows PowerShell Cookbook" (O'Reilly), by Lee Holmes, September 2010
  36.                                 at http://poshcode.org/2179
  37.                         Modified by obsidience for enhanced error-reporting, October 2010
  38.                                 at http://poshcode.org/2297
  39.                         Modified by Tao Klerks for code formatting, enhanced/fixed error-reporting, and interaction/hanging options, January 2012
  40.                                 at https://gist.github.com/gists/1582185
  41.                                 and at http://poshcode.org/, followup to http://poshcode.org/2297
  42.                         SEE ALSO: "Invoke-Elevated" (alias "su") in PSCX 2.0 - simpler "just fire" elevated process runner.
  43.         #>
  44.  
  45.         param
  46.         (
  47.                 ## The script block to invoke elevated. NOTE: to access the InputObject/pipeline data from the script block, use "$input"!
  48.                 [Parameter(Mandatory = $true)]
  49.                 [ScriptBlock] $Scriptblock,
  50.          
  51.                 ## Any input to give the elevated process
  52.                 [Parameter(ValueFromPipeline = $true)]
  53.                 $InputObject,
  54.          
  55.                 ## Switch to enable the user profile
  56.                 [switch] $EnableProfile,
  57.          
  58.                 ## Switch to display the spawned window (as interactive)
  59.                 [switch] $DisplayWindow
  60.         )
  61.          
  62.         begin
  63.         {
  64.                 Set-StrictMode -Version Latest
  65.                 $inputItems = New-Object System.Collections.ArrayList
  66.         }
  67.          
  68.         process
  69.         {
  70.                 $null = $inputItems.Add($inputObject)
  71.         }
  72.          
  73.         end
  74.         {
  75.  
  76.                 ## Create some temporary files for streaming input and output
  77.                 $outputFile = [IO.Path]::GetTempFileName()     
  78.                 $inputFile = [IO.Path]::GetTempFileName()
  79.                 $errorFile = [IO.Path]::GetTempFileName()
  80.  
  81.                 ## Stream the input into the input file
  82.                 $inputItems.ToArray() | Export-CliXml -Depth 1 $inputFile
  83.          
  84.                 ## Start creating the command line for the elevated PowerShell session
  85.                 $commandLine = ""
  86.                 if(-not $EnableProfile) { $commandLine += "-NoProfile " }
  87.  
  88.                 if(-not $DisplayWindow) {
  89.                         $commandLine += "-Noninteractive "
  90.                         $processWindowStyle = "Hidden"
  91.                 }
  92.                 else {
  93.                         $processWindowStyle = "Normal"
  94.                 }
  95.          
  96.                 ## Convert the command into an encoded command for PowerShell
  97.                 $commandString = "Set-Location '$($pwd.Path)'; " +
  98.                         "`$output = Import-CliXml '$inputFile' | " +
  99.                         "& {" + $scriptblock.ToString() + "} 2>&1 ; " +
  100.                         "Out-File -filepath '$errorFile' -inputobject `$error;" +
  101.                         "Export-CliXml -Depth 1 -In `$output '$outputFile';"
  102.          
  103.                 $commandBytes = [System.Text.Encoding]::Unicode.GetBytes($commandString)
  104.                 $encodedCommand = [Convert]::ToBase64String($commandBytes)
  105.                 $commandLine += "-EncodedCommand $encodedCommand"
  106.  
  107.                 ## Start the new PowerShell process
  108.                 $process = Start-Process -FilePath (Get-Command powershell).Definition `
  109.                         -ArgumentList $commandLine `
  110.                         -Passthru `
  111.                         -Verb RunAs `
  112.                         -WindowStyle $processWindowStyle
  113.  
  114.                 $process.WaitForExit()
  115.  
  116.                 $errorMessage = $(gc $errorFile | Out-String)
  117.                 if($errorMessage) {
  118.                         Write-Error -Message $errorMessage
  119.                 }
  120.                 else {
  121.                         ## Return the output to the user
  122.                         if((Get-Item $outputFile).Length -gt 0)
  123.                         {
  124.                                 Import-CliXml $outputFile
  125.                         }
  126.                 }
  127.  
  128.                 ## Clean up
  129.                 Remove-Item $outputFile
  130.                 Remove-Item $inputFile
  131.                 Remove-Item $errorFile
  132.         }
  133. }

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me