This repository has been archived by the owner on Mar 2, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathInvoke-ElevatedCommand.ps1
87 lines (69 loc) · 2.44 KB
/
Invoke-ElevatedCommand.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
##############################################################################
##
## Invoke-ElevatedCommand
##
## From Windows PowerShell Cookbook (O'Reilly)
## by Lee Holmes (http://www.leeholmes.com/guide)
##
##############################################################################
<#
.SYNOPSIS
Runs the provided script block under an elevated instance of PowerShell as
through it were a member of a regular pipeline.
.EXAMPLE
PS > Get-Process | Invoke-ElevatedCommand.ps1 {
$input | Where-Object { $_.Handles -gt 500 } } | Sort Handles
#>
param(
## The script block to invoke elevated
[Parameter(Mandatory = $true)]
[ScriptBlock] $Scriptblock,
## Any input to give the elevated process
[Parameter(ValueFromPipeline = $true)]
$InputObject,
## Switch to enable the user profile
[switch] $EnableProfile
)
begin
{
Set-StrictMode -Version 3
$inputItems = New-Object System.Collections.ArrayList
}
process
{
$null = $inputItems.Add($inputObject)
}
end
{
## Create some temporary files for streaming input and output
$outputFile = [IO.Path]::GetTempFileName()
$inputFile = [IO.Path]::GetTempFileName()
## Stream the input into the input file
$inputItems.ToArray() | Export-CliXml -Depth 1 $inputFile
## Start creating the command line for the elevated PowerShell session
$commandLine = ""
if(-not $EnableProfile) { $commandLine += "-NoProfile " }
## Convert the command into an encoded command for PowerShell
$commandString = "Set-Location '$($pwd.Path)'; " +
"`$output = Import-CliXml '$inputFile' | " +
"& {" + $scriptblock.ToString() + "} 2>&1; " +
"`$output | Export-CliXml -Depth 1 '$outputFile'"
$commandBytes = [System.Text.Encoding]::Unicode.GetBytes($commandString)
$encodedCommand = [Convert]::ToBase64String($commandBytes)
$commandLine += "-EncodedCommand $encodedCommand"
## Start the new PowerShell process
$process = Start-Process -FilePath (Get-Command powershell).Definition `
-ArgumentList $commandLine -Verb RunAs `
-WindowStyle Hidden `
-Passthru
$process.WaitForExit()
## Return the output to the user
if((Get-Item $outputFile).Length -gt 0)
{
Import-CliXml $outputFile
}
## Clean up
[Console]::WriteLine($outputFile)
# Remove-Item $outputFile
Remove-Item $inputFile
}