This can be solved with a named pipe.
Elevated PowerShell Script (test.ps1)
function IsAdmin{
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
$Is64 = [Environment]::Is64BitOperatingSystem
if ($currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Output "Running with elevated privileges. (64-bit=$Is64)"
} else {
Write-Output "Running without elevated privileges. (64-bit=$Is64)"
}
}
IsAdmin
Write-Output "Running $PSScriptRoot\test.bat"
Start-Process -FilePath "$PSScriptRoot\test.bat" -ArgumentList "C:\" -NoNewWindow
$np = new-object System.IO.Pipes.NamedPipeClientStream('.','SAMPipe', [System.IO.Pipes.PipeDirection]::In,[System.IO.Pipes.PipeOptions]::None,[System.Security.Principal.TokenImpersonationLevel]::Impersonation)
$np.Connect()
$sr = new-object System.IO.StreamReader($np)
while ($l=$sr.ReadLine()) {
Write-Output $l
}
$sr.Close()
$np.Close()
BAT file in the middle to de-elevate (test.bat)
runas /machine:amd64 /trustlevel:0x20000 "powershell -command %~dp0test2.ps1 -drive %1 >dummy.txt"
Non-Elevated PowerShell Script (test2.ps1)
param([string]$drive)
function IsAdmin{
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
$Is64 = [Environment]::Is64BitOperatingSystem
if ($currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Output "Running with elevated privileges. (64-bit=$Is64)"
} else {
Write-Output "Running without elevated privileges. (64-bit=$Is64)"
}
}
function Setup-Test{
Write-Output "Testing Powershell with Parameter Drive=$drive"
git config --global user.name
cd bob
Write-Error "Error Line 1
Error Line 2"
Write-Error "Error Line 3"
$d = 3/0
Write-Output "Done Testing Powershell"
}
$np = New-Object System.IO.Pipes.NamedPipeServerStream('SAMPipe',[System.IO.Pipes.PipeDirection]::Out)
$np.WaitForConnection()
$sw = New-Object System.IO.StreamWriter($np)
$sw.WriteLine('Begin Non-Elevated Process Pipe')
Invoke-Command -ScriptBlock {
try {
IsAdmin
Setup-Test
} catch {
Write-Error $_
}
} -ErrorVariable errVar -OutVariable out
foreach ($line in $out){
$sw.WriteLine($line)
}
foreach ($line in $errVar) {
$sw.WriteLine($line)
}
$sw.WriteLine('End Non-Elevated Process Pipe')
$sw.Close()
$np.Close()
Output
Running with elevated privileges. (64-bit=True)
Running C:\Users\bmarty\source\PowerShellTest\test.bat
C:\Users\bmarty\source\PowerShellTest>runas /machine:amd64 /trustlevel:0x20000 "powershell -command C:\Users\bmarty\source\PowerShellTest\test2.ps1 -drive C:\ >dummy.txt"
Begin Non-Elevated Process Pipe
Running without elevated privileges. (64-bit=True)
Testing Powershell with Parameter Drive=C:\
Ben Marty
Cannot find path 'C:\Users\bmarty\source\PowerShellTest\bob' because it does not exist.
Error Line 1
Error Line 2
Error Line 3
Attempted to divide by zero.
System.Management.Automation.RuntimeException: Attempted to divide by zero. ---> System.DivideByZeroException: Attempted to divide by zero.
--- End of inner exception stack trace ---
at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
Attempted to divide by zero.
Attempted to divide by zero.
End Non-Elevated Process Pipe
Done running
I don't understand why the output of git config only appears in the output if I include >dummy.txt in the BAT file.