Converting from Start-process to System.Diagnostics.Process - powershell
We have working powershell script ran through start-process
$EncodedCommand = 'JABFAHIAcgBvAHIALgBjAGwAZQBhAHIAKAApAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIABbAHMAdAByAGkAbgBnAF0AIAAkAEUAbgBjAG8AZABlAGQAQQByAGcAdQBtAGUAbgB0AHMAIAA9ACAAJwBQAEEAQgBQAEEARwBJAEEAYQBnAEIAegBBAEMAQQBBAFYAZwBCAGwAQQBIAEkAQQBjAHcAQgBwAEEARwA4AEEAYgBnAEEAOQBBAEMASQBBAE0AUQBBAHUAQQBEAEUAQQBMAGcAQQB3AEEAQwA0AEEATQBRAEEAaQBBAEMAQQBBAGUAQQBCAHQAQQBHAHcAQQBiAGcAQgB6AEEARAAwAEEASQBnAEIAbwBBAEgAUQBBAGQAQQBCAHcAQQBEAG8AQQBMAHcAQQB2AEEASABNAEEAWQB3AEIAbwBBAEcAVQBBAGIAUQBCAGgAQQBIAE0AQQBMAGcAQgB0AEEARwBrAEEAWQB3AEIAeQBBAEcAOABBAGMAdwBCAHYAQQBHAFkAQQBkAEEAQQB1AEEARwBNAEEAYgB3AEIAdABBAEMAOABBAGMAQQBCAHYAQQBIAGMAQQBaAFEAQgB5AEEASABNAEEAYQBBAEIAbABBAEcAdwBBAGIAQQBBAHYAQQBEAEkAQQBNAEEAQQB3AEEARABRAEEATAB3AEEAdwBBAEQAUQBBAEkAZwBBACsAQQBBADAAQQBDAGcAQQBnAEEAQwBBAEEAUABBAEIAUABBAEcASQBBAGEAZwBBAGcAQQBGAEkAQQBaAFEAQgBtAEEARQBrAEEAWgBBAEEAOQBBAEMASQBBAE0AQQBBAGkAQQBEADQAQQBEAFEAQQBLAEEAQwBBAEEASQBBAEEAZwBBAEMAQQBBAFAAQQBCAFUAQQBFADQAQQBJAEEAQgBTAEEARwBVAEEAWgBnAEIASgBBAEcAUQBBAFAAUQBBAGkAQQBEAEEAQQBJAGcAQQArAEEAQQAwAEEAQwBnAEEAZwBBAEMAQQBBAEkAQQBBAGcAQQBDAEEAQQBJAEEAQQA4AEEARgBRAEEAUABnAEIAVABBAEgAawBBAGMAdwBCADAAQQBHAFUAQQBiAFEAQQB1AEEARQA4AEEAWQBnAEIAcQBBAEcAVQBBAFkAdwBCADAAQQBGAHMAQQBYAFEAQQA4AEEAQwA4AEEAVgBBAEEAKwBBAEEAMABBAEMAZwBBAGcAQQBDAEEAQQBJAEEAQQBnAEEAQwBBAEEASQBBAEEAOABBAEYAUQBBAFAAZwBCAFQAQQBIAGsAQQBjAHcAQgAwAEEARwBVAEEAYgBRAEEAdQBBAEUARQBBAGMAZwBCAHkAQQBHAEUAQQBlAFEAQQA4AEEAQwA4AEEAVgBBAEEAKwBBAEEAMABBAEMAZwBBAGcAQQBDAEEAQQBJAEEAQQBnAEEAQwBBAEEASQBBAEEAOABBAEYAUQBBAFAAZwBCAFQAQQBIAGsAQQBjAHcAQgAwAEEARwBVAEEAYgBRAEEAdQBBAEUAOABBAFkAZwBCAHEAQQBHAFUAQQBZAHcAQgAwAEEARAB3AEEATAB3AEIAVQBBAEQANABBAEQAUQBBAEsAQQBDAEEAQQBJAEEAQQBnAEEAQwBBAEEAUABBAEEAdgBBAEYAUQBBAFQAZwBBACsAQQBBADAAQQBDAGcAQQBnAEEAQwBBAEEASQBBAEEAZwBBAEQAdwBBAFQAQQBCAFQAQQBGAFEAQQBQAGcAQQBOAEEAQQBvAEEASQBBAEEAZwBBAEMAQQBBAEkAQQBBAGcAQQBDAEEAQQBQAEEAQgBUAEEARAA0AEEAZABBAEIAbABBAEgATQBBAGQAQQBBAHQAQQBIAFEAQQBaAFEAQgB6AEEASABRAEEATABRAEIAMABBAEcAVQBBAGMAdwBCADAAQQBEAHcAQQBMAHcAQgBUAEEARAA0AEEARABRAEEASwBBAEMAQQBBAEkAQQBBAGcAQQBDAEEAQQBJAEEAQQBnAEEARAB3AEEAVAB3AEIAaQBBAEcAbwBBAEkAQQBCAFMAQQBHAFUAQQBaAGcAQgBKAEEARwBRAEEAUABRAEEAaQBBAEQARQBBAEkAZwBBACsAQQBBADAAQQBDAGcAQQBnAEEAQwBBAEEASQBBAEEAZwBBAEMAQQBBAEkAQQBBAGcAQQBDAEEAQQBQAEEAQgBFAEEARgBRAEEAUABnAEEAeQBBAEQAQQBBAE0AZwBBAHkAQQBDADAAQQBNAEEAQQAzAEEAQwAwAEEATQBBAEEAMwBBAEYAUQBBAE0AQQBBAHgAQQBEAG8AQQBNAEEAQQA0AEEARABvAEEATgBRAEEAMgBBAEMANABBAE4AUQBBADMAQQBEAFEAQQBPAFEAQQB5AEEARABrAEEATgBRAEEAcgBBAEQAQQBBAE0AdwBBADYAQQBEAEEAQQBNAEEAQQA4AEEAQwA4AEEAUgBBAEIAVQBBAEQANABBAEQAUQBBAEsAQQBDAEEAQQBJAEEAQQBnAEEAQwBBAEEASQBBAEEAZwBBAEMAQQBBAEkAQQBBADgAQQBFADAAQQBVAHcAQQArAEEAQQAwAEEAQwBnAEEAZwBBAEMAQQBBAEkAQQBBAGcAQQBDAEEAQQBJAEEAQQBnAEEAQwBBAEEASQBBAEEAZwBBAEQAdwBBAFQAdwBCAGkAQQBHAG8AQQBJAEEAQgBPAEEARAAwAEEASQBnAEIARQBBAEcAawBBAGMAdwBCAHcAQQBHAHcAQQBZAFEAQgA1AEEARQBnAEEAYQBRAEIAdQBBAEgAUQBBAEkAZwBBAGcAQQBGAEkAQQBaAFEAQgBtAEEARQBrAEEAWgBBAEEAOQBBAEMASQBBAE0AZwBBAGkAQQBEADQAQQBEAFEAQQBLAEEAQwBBAEEASQBBAEEAZwBBAEMAQQBBAEkAQQBBAGcAQQBDAEEAQQBJAEEAQQBnAEEAQwBBAEEASQBBAEEAZwBBAEQAdwBBAFYAQQBCAE8AQQBDAEEAQQBVAGcAQgBsAEEARwBZAEEAUwBRAEIAawBBAEQAMABBAEkAZwBBAHgAQQBDAEkAQQBQAGcAQQBOAEEAQQBvAEEASQBBAEEAZwBBAEMAQQBBAEkAQQBBAGcAQQBDAEEAQQBJAEEAQQBnAEEAQwBBAEEASQBBAEEAZwBBAEMAQQBBAEkAQQBBAGcAQQBEAHcAQQBWAEEAQQArAEEARQAwAEEAYQBRAEIAagBBAEgASQBBAGIAdwBCAHoAQQBHADgAQQBaAGcAQgAwAEEAQwA0AEEAVQBBAEIAdgBBAEgAYwBBAFoAUQBCAHkAQQBGAE0AQQBhAEEAQgBsAEEARwB3AEEAYgBBAEEAdQBBAEUATQBBAGIAdwBCAHQAQQBHADAAQQBZAFEAQgB1AEEARwBRAEEAYwB3AEEAdQBBAEUAUQBBAGEAUQBCAHoAQQBIAEEAQQBiAEEAQgBoAEEASABrAEEAUwBBAEIAcABBAEcANABBAGQAQQBCAFUAQQBIAGsAQQBjAEEAQgBsAEEARAB3AEEATAB3AEIAVQBBAEQANABBAEQAUQBBAEsAQQBDAEEAQQBJAEEAQQBnAEEAQwBBAEEASQBBAEEAZwBBAEMAQQBBAEkAQQBBAGcAQQBDAEEAQQBJAEEAQQBnAEEAQwBBAEEASQBBAEEAOABBAEYAUQBBAFAAZwBCAFQAQQBIAGsAQQBjAHcAQgAwAEEARwBVAEEAYgBRAEEAdQBBAEUAVQBBAGIAZwBCADEAQQBHADAAQQBQAEEAQQB2AEEARgBRAEEAUABnAEEATgBBAEEAbwBBAEkAQQBBAGcAQQBDAEEAQQBJAEEAQQBnAEEAQwBBAEEASQBBAEEAZwBBAEMAQQBBAEkAQQBBAGcAQQBDAEEAQQBJAEEAQQBnAEEARAB3AEEAVgBBAEEAKwBBAEYATQBBAGUAUQBCAHoAQQBIAFEAQQBaAFEAQgB0AEEAQwA0AEEAVgBnAEIAaABBAEcAdwBBAGQAUQBCAGwAQQBGAFEAQQBlAFEAQgB3AEEARwBVAEEAUABBAEEAdgBBAEYAUQBBAFAAZwBBAE4AQQBBAG8AQQBJAEEAQQBnAEEAQwBBAEEASQBBAEEAZwBBAEMAQQBBAEkAQQBBAGcAQQBDAEEAQQBJAEEAQQBnAEEAQwBBAEEASQBBAEEAZwBBAEQAdwBBAFYAQQBBACsAQQBGAE0AQQBlAFEAQgB6AEEASABRAEEAWgBRAEIAdABBAEMANABBAFQAdwBCAGkAQQBHAG8AQQBaAFEAQgBqAEEASABRAEEAUABBAEEAdgBBAEYAUQBBAFAAZwBBAE4AQQBBAG8AQQBJAEEAQQBnAEEAQwBBAEEASQBBAEEAZwBBAEMAQQBBAEkAQQBBAGcAQQBDAEEAQQBJAEEAQQBnAEEAQwBBAEEAUABBAEEAdgBBAEYAUQBBAFQAZwBBACsAQQBBADAAQQBDAGcAQQBnAEEAQwBBAEEASQBBAEEAZwBBAEMAQQBBAEkAQQBBAGcAQQBDAEEAQQBJAEEAQQBnAEEAQwBBAEEASQBBAEEAOABBAEYAUQBBAGIAdwBCAFQAQQBIAFEAQQBjAGcAQgBwAEEARwA0AEEAWgB3AEEAKwBBAEUAUQBBAFkAUQBCADAAQQBHAFUAQQBWAEEAQgBwAEEARwAwAEEAWgBRAEEAOABBAEMAOABBAFYAQQBCAHYAQQBGAE0AQQBkAEEAQgB5AEEARwBrAEEAYgBnAEIAbgBBAEQANABBAEQAUQBBAEsAQQBDAEEAQQBJAEEAQQBnAEEAQwBBAEEASQBBAEEAZwBBAEMAQQBBAEkAQQBBAGcAQQBDAEEAQQBJAEEAQQBnAEEARAB3AEEAUwBRAEEAegBBAEQASQBBAFAAZwBBAHkAQQBEAHcAQQBMAHcAQgBKAEEARABNAEEATQBnAEEAKwBBAEEAMABBAEMAZwBBAGcAQQBDAEEAQQBJAEEAQQBnAEEAQwBBAEEASQBBAEEAZwBBAEMAQQBBAEkAQQBBAGcAQQBEAHcAQQBMAHcAQgBQAEEARwBJAEEAYQBnAEEAKwBBAEEAMABBAEMAZwBBAGcAQQBDAEEAQQBJAEEAQQBnAEEAQwBBAEEASQBBAEEAZwBBAEMAQQBBAFAAQQBBAHYAQQBFADAAQQBVAHcAQQArAEEAQQAwAEEAQwBnAEEAZwBBAEMAQQBBAEkAQQBBAGcAQQBDAEEAQQBJAEEAQQA4AEEAQwA4AEEAVAB3AEIAaQBBAEcAbwBBAFAAZwBBAE4AQQBBAG8AQQBJAEEAQQBnAEEAQwBBAEEASQBBAEEAZwBBAEMAQQBBAFAAQQBCAEMAQQBEADQAQQBkAEEAQgB5AEEASABVAEEAWgBRAEEAOABBAEMAOABBAFEAZwBBACsAQQBBADAAQQBDAGcAQQBnAEEAQwBBAEEASQBBAEEAZwBBAEQAdwBBAEwAdwBCAE0AQQBGAE0AQQBWAEEAQQArAEEAQQAwAEEAQwBnAEEAZwBBAEMAQQBBAFAAQQBBAHYAQQBFADgAQQBZAGcAQgBxAEEARAA0AEEARABRAEEASwBBAEQAdwBBAEwAdwBCAFAAQQBHAEkAQQBhAGcAQgB6AEEARAA0AEEAJwANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAJABBAHIAZwB1AG0AZQBuAHQAcwAgACAAPQAgAFsAUwB5AHMAdABlAG0ALgBNAGEAbgBhAGcAZQBtAGUAbgB0AC4AQQB1AHQAbwBtAGEAdABpAG8AbgAuAFAAUwBTAGUAcgBpAGEAbABpAHoAZQByAF0AOgA6AEQAZQBzAGUAcgBpAGEAbABpAHoAZQAoACAAWwBTAHkAcwB0AGUAbQAuAFQAZQB4AHQALgBFAG4AYwBvAGQAaQBuAGcAXQA6ADoAVQBuAGkAYwBvAGQAZQAuAEcAZQB0AFMAdAByAGkAbgBnACgAWwBTAHkAcwB0AGUAbQAuAEMAbwBuAHYAZQByAHQAXQA6ADoARgByAG8AbQBCAGEAcwBlADYANABTAHQAcgBpAG4AZwAoACAAJABFAG4AYwBvAGQAZQBkAEEAcgBnAHUAbQBlAG4AdABzACAAKQApACAAKQANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACQAUwBjAHIAaQBwAHQAQgBsAG8AYwBrACAAPQAgAHsADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIwBzAGIAMQAgAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAcABhAHIAYQBtACgAIAAkAFAAYQByAGEAbQAxACwAIAAkAFAAYQByAGEAbQAyACwAIAAkAFAAYQByAGEAbQAzACAAKQANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIwByAGUAZwBpAG8AbgAgAE8AdQB0AGUAcgAgAHMAYwByAGkAcAB0ACAAYQBkAGQAaQB0AGkAbwBuAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIABTAHQAYQByAHQALQBUAHIAYQBuAHMAYwByAGkAcAB0ACAALQBwAGEAdABoACAAIgBDADoAXABVAHMAZQByAHMAXABQAHUAYgBsAGkAYwBcAFQATQBQAFwAVAByAGEAbgBzAGMAcgBpAHAAdAAuAHQAeAB0ACIAIAAtAGYAbwByAGMAZQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACQARwBsAG8AYgBhAGwAOgBQAFMAUwBjAHIAaQBwAHQATgBhAG0AZQAgAD0AIAAgACIAUwBjAHIAaQBwAHQAYgBsAG8AYwBrACIACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAkAFAAUwBDAG8AbQBtAGEAbgBkAFAAYQB0AGgAIAA9ACAAIgBDADoAXABVAHMAZQByAHMAXABBAGwAZQB4AFwAQQBwAHAARABhAHQAYQBcAEwAbwBjAGEAbABcAFQAZQBtAHAAXABTAGMAcgBpAHAAdABiAGwAbwBjAGsAIgAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAjAGUAbgBkAHIAZQBnAGkAbwBuAA0ACgANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgAGcAZQB0AC0AZABhAHQAZQANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACQAVQBzAGUAcgAgAD0AIAB3AGgAbwBhAG0AaQANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACQAUgB1AG4AYQBzACAAPQAgAFQAZQBzAHQALQBFAGwAZQB2AGEAdABlAGQAUgBpAGcAaAB0AHMADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAB3AHIAaQB0AGUALQBoAG8AcwB0ACAAIgBVAHMAZQByACAAPQAgACQAVQBzAGUAcgAiAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAdwByAGkAdABlAC0AaABvAHMAdAAgACIAUgB1AG4AYQBzACAAPQAgACQAUgB1AG4AYQBzACIADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAB3AHIAaQB0AGUALQBoAG8AcwB0ACAAIgBQAGEAcgBhAG0AMQAgAD0AIAAkAFAAYQByAGEAbQAxACIADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAB3AHIAaQB0AGUALQBoAG8AcwB0ACAAIgBQAGEAcgBhAG0AMgAgAD0AIAAkAFAAYQByAGEAbQAyACIADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAB3AHIAaQB0AGUALQBoAG8AcwB0ACAAIgBQAGEAcgBhAG0AMwAgAD0AIAAkAFAAYQByAGEAbQAzACIADQAKAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIwByAGUAZwBpAG8AbgAgAE8AdQB0AGUAcgAgAHMAYwByAGkAcAB0ACAAYQBkAGQAaQB0AGkAbwBuACAAKAByAGUAdAB1AHIAbgAgAHIAZQBwAGwAYQBjAGUAKQANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAJABVAHMAZQByACAAfAAgAEUAeABwAG8AcgB0AC0AQwBsAGkAWABNAEwAIAAtAFAAYQB0AGgAIAAiAEMAOgBcAFUAcwBlAHIAcwBcAFAAdQBiAGwAaQBjAFwAVABNAFAAXABSAGUAcwB1AGwAdAAuAHgAbQBsACIAIAAtAEYAbwByAGMAZQANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAdAByAHkAewAgAHMAdABvAHAALQB0AHIAYQBuAHMAYwByAGkAcAB0ACAAfQBjAGEAdABjAGgAewB9AA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAjAGUAeABpAHQADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAjAGUAbgBkAHIAZQBnAGkAbwBuAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAB9AA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAASQBuAHYAbwBrAGUALQBDAG8AbQBtAGEAbgBkACAALQBTAGMAcgBpAHAAdABCAGwAbwBjAGsAIAAkAFMAYwByAGkAcAB0AEIAbABvAGMAawAgAC0AQQByAGcAdQBtAGUAbgB0AEwAaQBzAHQAIAAgACQAQQByAGcAdQBtAGUAbgB0AHMA'
$Arguments = '-Noexit', '-NoLogo', '–NoProfile', '-ExecutionPolicy RemoteSigned', "-EncodedCommand $EncodedCommand"
# line below executed successfully
start-process -filepath powershell -ArgumentList $Arguments
Now we should transform our code to use System.Diagnostics.Process
$Process = New-Object System.Diagnostics.Process
$ProcessStartInfoParam = [ordered]#{
Arguments = ( "'" + ( $Arguments -join "', '" ) + "'" )
CreateNoWindow = $False
FileName = 'powershell'
WindowStyle = 'Normal'
LoadUserProfile = $False
UseShellExecute = $False
}
$ProcessStartInfo = New-Object -TypeName 'System.Diagnostics.ProcessStartInfo' -Property $ProcessStartInfoParam
$Process.StartInfo = $ProcessStartInfo
$StartResult = $Process.Start()
We have no script output and $StartResult is true. Also trying to remove '-Noexit' argument.
I want to have new window with output like in first example.
You are joining the arguments incorrectly. Command-line arguments must be separated by space and quoted using double-quotation marks. In your case you don't need quoting as the arguments don't contain whitespace.
Try this:
$ProcessStartInfoParam = [ordered]#{
Arguments = $Arguments -join ' '
CreateNoWindow = $False
FileName = 'powershell'
WindowStyle = 'Normal'
LoadUserProfile = $False
UseShellExecute = $False
}
Related
Pass complex arguments to powershell script through encoded command
I want to run nested powershell script block, with complex type arguments. I want to pass parameters to powershell scriptblock trough encoded command and encoded arguments. I`m trying this script. $text = "This is a test message." $Cred = get-credential 'alex' $Arguments = #{ Msg = $Text Proc = $PID Cred = $Cred } $Serialized = [System.Management.Automation.PSSerializer]::Serialize($Arguments) $Bytes = [System.Text.Encoding]::Unicode.GetBytes($Serialized) $EncodedArguments = [Convert]::ToBase64String($Bytes) $ScriptBlock = { param([String]$Base64) $Serialized = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($Base64)) $Arguments = [System.Management.Automation.PSSerializer]::Deserialize($Serialized) Write-Host " $($Arguments.msg) FROM PID: $($Arguments.proc), cred: $( $Arguments.Cred.Username)" } $Bytes = [System.Text.Encoding]::Unicode.GetBytes( $ScriptBlock.ToString() ) $EncodedCommand = [Convert]::ToBase64String( $Bytes ) Start-Process -FilePath powershell -ArgumentList '-noprofile', '-noexit', ` '-EncodedCommand', $EncodedCommand, '-EncodedArguments', $EncodedArguments Powershell process flashing, then closing. Help me to correct this script. PS. Why stack overflow editor replace the header of my message 'Hello team!' ? Its all right on preview.
A -EncodedArguments parameter (or something alike) doesn't exist, therefore I would simply embed your arguments as a default param value in your (encoded) scriptblock: $Arguments = #{ Msg = "This is a test message." Proc = $PID Cred = (Get-Credential 'Alex') } $Serialized = [System.Management.Automation.PSSerializer]::Serialize($Arguments) $Bytes = [System.Text.Encoding]::Unicode.GetBytes($Serialized) $EncodedArguments = [Convert]::ToBase64String($Bytes) $ScriptBlock = "param([String]`$EncodedArguments = '$EncodedArguments')" + { $Serialized = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($EncodedArguments)) $Arguments = [System.Management.Automation.PSSerializer]::Deserialize($Serialized) Write-Host " $($Arguments.msg) FROM PID: $($Arguments.proc), cred: $( $Arguments.Cred.Username)" } $Bytes = [System.Text.Encoding]::Unicode.GetBytes( $ScriptBlock.ToString() ) $EncodedCommand = [Convert]::ToBase64String( $Bytes ) Start-Process -FilePath powershell -ArgumentList '-noprofile', '-noexit', '-EncodedCommand', $EncodedCommand
How to get output from Start-Process [duplicate]
Is there a bug in PowerShell's Start-Process command when accessing the StandardError and StandardOutput properties? If I run the following I get no output: $process = Start-Process -FilePath ping -ArgumentList localhost -NoNewWindow -PassThru -Wait $process.StandardOutput $process.StandardError But if I redirect the output to a file I get the expected result: $process = Start-Process -FilePath ping -ArgumentList localhost -NoNewWindow -PassThru -Wait -RedirectStandardOutput stdout.txt -RedirectStandardError stderr.txt
That's how Start-Process was designed for some reason. Here's a way to get it without sending to file: $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = "ping.exe" $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.Arguments = "localhost" $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null $p.WaitForExit() $stdout = $p.StandardOutput.ReadToEnd() $stderr = $p.StandardError.ReadToEnd() Write-Host "stdout: $stdout" Write-Host "stderr: $stderr" Write-Host "exit code: " + $p.ExitCode
In the code given in the question, I think that reading the ExitCode property of the initiation variable should work. $process = Start-Process -FilePath ping -ArgumentList localhost -NoNewWindow -PassThru -Wait $process.ExitCode Note that (as in your example) you need to add the -PassThru and -Wait parameters (this caught me out for a while).
IMPORTANT: We have been using the function as provided above by LPG. However, this contains a bug you might encounter when you start a process that generates a lot of output. Due to this you might end up with a deadlock when using this function. Instead use the adapted version below: Function Execute-Command ($commandTitle, $commandPath, $commandArguments) { Try { $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = $commandPath $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.Arguments = $commandArguments $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null [pscustomobject]#{ commandTitle = $commandTitle stdout = $p.StandardOutput.ReadToEnd() stderr = $p.StandardError.ReadToEnd() ExitCode = $p.ExitCode } $p.WaitForExit() } Catch { exit } } Further information on this issue can be found at MSDN: A deadlock condition can result if the parent process calls p.WaitForExit before p.StandardError.ReadToEnd and the child process writes enough text to fill the redirected stream. The parent process would wait indefinitely for the child process to exit. The child process would wait indefinitely for the parent to read from the full StandardError stream.
I also had this issue and ended up using Andy's code to create a function to clean things up when multiple commands need to be run. It'll return stderr, stdout, and exit codes as objects. One thing to note: the function won't accept .\ in the path; full paths must be used. Function Execute-Command ($commandTitle, $commandPath, $commandArguments) { $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = $commandPath $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.Arguments = $commandArguments $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null $p.WaitForExit() [pscustomobject]#{ commandTitle = $commandTitle stdout = $p.StandardOutput.ReadToEnd() stderr = $p.StandardError.ReadToEnd() ExitCode = $p.ExitCode } } Here's how to use it: $DisableACMonitorTimeOut = Execute-Command -commandTitle "Disable Monitor Timeout" -commandPath "C:\Windows\System32\powercfg.exe" -commandArguments " -x monitor-timeout-ac 0"
I really had troubles with those examples from Andy Arismendi and from LPG. You should always use: $stdout = $p.StandardOutput.ReadToEnd() before calling $p.WaitForExit() A full example is: $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = "ping.exe" $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.Arguments = "localhost" $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null $stdout = $p.StandardOutput.ReadToEnd() $stderr = $p.StandardError.ReadToEnd() $p.WaitForExit() Write-Host "stdout: $stdout" Write-Host "stderr: $stderr" Write-Host "exit code: " + $p.ExitCode
Here's a kludgy way to get the output from another powershell process (serialized): start-process -wait -nonewwindow powershell 'ps | Export-Clixml out.xml' import-clixml out.xml Let me emphasize -nonewwindow to get the standardoutput and standarderror, at least on the local screen: start-process -wait cmd '/c dir' -nonewwindow Volume in drive C is Windows Volume Serial Number is 2AC6-626F Directory of C:\users\me\foo 11/24/2022 11:40 AM <DIR> . 11/24/2022 11:40 AM <DIR> .. 11/24/2022 11:40 AM 330 file.json 1 File(s) 330 bytes 2 Dir(s) 25,042,915,328 bytes free start-process -wait cmd '/c dir foo' -nonewwindow Volume in drive C is Windows Volume Serial Number is 2AC6-626F Directory of C:\users\me\foo File Not Found
Here's what I cooked up based on the examples posted by others on this thread. This version will hide the console window and provided options for output display. function Invoke-Process { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$FilePath, [Parameter()] [ValidateNotNullOrEmpty()] [string]$ArgumentList, [ValidateSet("Full","StdOut","StdErr","ExitCode","None")] [string]$DisplayLevel ) $ErrorActionPreference = 'Stop' try { $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = $FilePath $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.WindowStyle = 'Hidden' $pinfo.CreateNoWindow = $true $pinfo.Arguments = $ArgumentList $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null $result = [pscustomobject]#{ Title = ($MyInvocation.MyCommand).Name Command = $FilePath Arguments = $ArgumentList StdOut = $p.StandardOutput.ReadToEnd() StdErr = $p.StandardError.ReadToEnd() ExitCode = $p.ExitCode } $p.WaitForExit() if (-not([string]::IsNullOrEmpty($DisplayLevel))) { switch($DisplayLevel) { "Full" { return $result; break } "StdOut" { return $result.StdOut; break } "StdErr" { return $result.StdErr; break } "ExitCode" { return $result.ExitCode; break } } } } catch { exit } } Example: Invoke-Process -FilePath "FQPN" -ArgumentList "ARGS" -DisplayLevel Full
To get both stdout and stderr, I use: Function GetProgramOutput([string]$exe, [string]$arguments) { $process = New-Object -TypeName System.Diagnostics.Process $process.StartInfo.FileName = $exe $process.StartInfo.Arguments = $arguments $process.StartInfo.UseShellExecute = $false $process.StartInfo.RedirectStandardOutput = $true $process.StartInfo.RedirectStandardError = $true $process.Start() $output = $process.StandardOutput.ReadToEnd() $err = $process.StandardError.ReadToEnd() $process.WaitForExit() $output $err } $exe = "cmd" $arguments = '/c echo hello 1>&2' #this writes 'hello' to stderr $runResult = (GetProgramOutput $exe $arguments) $stdout = $runResult[-2] $stderr = $runResult[-1] [System.Console]::WriteLine("Standard out: " + $stdout) [System.Console]::WriteLine("Standard error: " + $stderr)
Improved Answer - as long as you're OK with Start-Job instead of Start-Process It turns out that the STDOUT and STDERR are accumulated in string arrays $job.ChildJobs[0].Output and $job.ChildJobs[0].Erroras the script runs. So you can poll these values and write them out periodically. Somewhat of a hack maybe, but it works. It's not a stream though, so you have to manually keep track of the starting index into the array. This code is simpler than my original answer, and at the end you have the entire STDOUT in $job.ChildJobs[0].Output. And as a little bonus for this demo, the calling script is PS7 and the background job is PS5. $scriptBlock = { Param ([int]$param1, [int]$param2) $PSVersionTable Start-Sleep -Seconds 1 $param1 + $param2 } $parameters = #{ ScriptBlock = $scriptBlock ArgumentList = 1, 2 PSVersion = 5.1 # <-- remove this line for PS7 } $timeoutSec = 5 $job = Start-Job #parameters $job.ChildJobs[0].Output $index = $job.ChildJobs[0].Output.Count while ($job.JobStateInfo.State -eq [System.Management.Automation.JobState]::Running) { Start-Sleep -Milliseconds 200 $job.ChildJobs[0].Output[$index] $index = $job.ChildJobs[0].Output.Count if (([DateTime]::Now - $job.PSBeginTime).TotalSeconds -gt $timeoutSec) { throw "Job timed out." } } As pointed out, my original answer can interleave the output. This is a limitation of event handling in PowerShell. It's not a fixable problem. Original Answer, don't use - just leaving it here for interest If there's a timeout, ReadToEnd() is not an option. You could do some fancy looping, but IMO the 'cleanest' way to do this is to ignore the streams. Hook the OutputDataReceived/ErrorDataReceived events instead, collecting the output. This approach also avoids the threading issues mentioned by others. This is straightforward in C#, but it's tricky and verbose in Powershell. In particular, add_OutputDataReceived is not available for some reason. (Not sure if this is a bug or a feature, at least this seems to be the case in PowerShell 5.1.) To work around it you can use Register-ObjectEvent. $stdout = New-Object System.Text.StringBuilder $stderr = New-Object System.Text.StringBuilder $proc = [System.Diagnostics.Process]#{ StartInfo = #{ FileName = 'ping.exe' Arguments = 'google.com' RedirectStandardOutput = $true RedirectStandardError = $true UseShellExecute = $false WorkingDirectory = $PSScriptRoot } } $stdoutEvent = Register-ObjectEvent $proc -EventName OutputDataReceived -MessageData $stdout -Action { $Event.MessageData.AppendLine($Event.SourceEventArgs.Data) } $stderrEvent = Register-ObjectEvent $proc -EventName ErrorDataReceived -MessageData $stderr -Action { $Event.MessageData.AppendLine($Event.SourceEventArgs.Data) } $proc.Start() | Out-Null $proc.BeginOutputReadLine() $proc.BeginErrorReadLine() Wait-Process -Id $proc.Id -TimeoutSec 5 if ($proc.HasExited) { $exitCode = $proc.ExitCode } else { Stop-Process -Force -Id $proc.Id $exitCode = -1 } # Be sure to unregister. You have been warned. Unregister-Event $stdoutEvent.Id Unregister-Event $stderrEvent.Id Write-Output $stdout.ToString() Write-Output $stderr.ToString() Write-Output "Exit code: $exitCode" The code shown is the happy path (stderr is empty) To test the timeout path, set -TimeoutSec to .5 To test the sad path (stderr has content), set FileName to 'cmd' and Arguments to /C asdf
Here is my version of function that is returning standard System.Diagnostics.Process with 3 new properties Function Execute-Command ($commandTitle, $commandPath, $commandArguments) { Try { $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = $commandPath $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.WindowStyle = 'Hidden' $pinfo.CreateNoWindow = $True $pinfo.Arguments = $commandArguments $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null $stdout = $p.StandardOutput.ReadToEnd() $stderr = $p.StandardError.ReadToEnd() $p.WaitForExit() $p | Add-Member "commandTitle" $commandTitle $p | Add-Member "stdout" $stdout $p | Add-Member "stderr" $stderr } Catch { } $p }
You may want to also consider using the & operator combined with --% instead of start-process - that lets you easily pipe and process the command and/or error output. put the escape parameter into a variable put the arguments into a variable $deploy= "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" $esc = '--%' $arguments ="-source:package='c:\temp\pkg.zip' -verb:sync" $output = & $deploy $esc $arguments That passes the parameters to the executable without interference and let me get around the issues with start-process. Combine Stderr and Stdout into one variable: $output = & $deploy $esc $arguments 2>&1 Get separate variables for Stderr and Stdout $err = $( $output = & $deploy $esc $arguments) 2>&1
installing msi file using powershell bringing up command line options
I am trying to run the below command and it opens windows installers parameters, what am I doing wrong? $current_pc = "$env:computername" $filePath = "c:\users\ArA\Desktop\parameters.csv" $machineParams = Import-CSV $filePath $info = if($machineParams){$machineParams | where {$_.branch -eq $($current_pc.Substring($current_pc.length - 3,3))}} else{write-output "CSV not loaded"} $info start-process msiexec.exe -Wait -ArgumentList /L* "c:\users\Ara\Desktop\t.log" /qn /I "c:\users\Ar\Desktop\setup.msi" DATABASE_ID=$($info.DATABASE_ID),ODBC_DATABASE_NAME=$($info.ODBC_DATABASE_NAME),ODBC_ENGINE_NAME=$($info.ODBC_ENGINE_NAME) ODBC_HOST_NAME=$($info.ODBC_HOST_NAME) NOLAN=1
It's likely how you are passing your arguments. As a best-practice, I utilize an array when passing exe arguments so they're interpreted properly: $machineParams = Import-Csv -Path $Env:UserProfile\Desktop\parameters.csv $info = if ($machineParams) { $machineParams | Where-Object { $_.branch -eq $Env:ComputerName.Substring($Env:ComputerName.Length - 3, 3) } } else { 'CSV not loaded.' } $info $StartArgs = #{ 'Wait' = $true 'FilePath' = "$Env:SystemRoot\System32\msiexec.exe" 'ArgumentList' = #( '/i',"$Env:UserProfile\Desktop\setup.msi" '/qn' '/log',"$Env:UserProfile\Desktop\t.log" ) } if ($info -ne 'CSV not loaded.') { $StartArgs['ArgumentList'] += #( "DATABASE_ID=$($info.DATABASE_ID)" "ODBC_DATABASE_NAME=$($info.ODBC_DATABASE_NAME)" "ODBC_ENGINE_NAME=$($info.ODBC_ENGINE_NAME)" "ODBC_HOST_NAME=$($info.ODBC_HOST_NAME)" 'NOLAN=1' ) } Start-Process #StartArgs
How to run a program as another user and add arguments in powershell?
We have a program that only updates when being run with the switch /t from an administrator account. I came up with the CMD prompt version, but I'm new to powershell and having a hard time translating it to Powershell. The CMD version is: C:\Windows\System32\runas.exe /savecred /user:ourdomain\ouruseracct "C:\Program Files (x86)\ProjectMatrix\ProjectNotify\ProjectNotify.exe /t" So far I got: C:\Windows\System32\runas.exe /user:ourdomain\ouruseracct /savecred "powershell -c start-process -FilePath \"'C:\Program Files (x86)\ProjectMatrix\ProjectNotify\ProjectNotify.exe'\" -verb runAs" Which runs powershell as admin and starts the program as admin but we need to pass the argument -t or /t to projectnotify.exe when running it. I believe we need to make use of the -argumentlist but not sure how to word it. I tried $t = "-t" Start-Process -FilePath "C:\Program Files (x86)\ProjectMatrix\ProjectNotify\projectnotify.exe" -ArgumentList $t -Verb runas Which runs the program but not sure if that's how you pass the argument.
Extra work (troubleshooting): $Cred = Get-Credential $ProcInfo = New-Object -TypeName 'System.Diagnostics.ProcessStartInfo' $ProcInfo.Domain = $Cred.GetNetworkCredential().Domain $ProcInfo.UserName = $Cred.UserName $ProcInfo.Password = $Cred.Password $ProcInfo.FileName = "${Env:ProgramFiles(x86)}\ProjectMatrix\ProjectNotify\ProjectNotify.exe" $ProcInfo.Arguments = '/t' $ProcInfo.WorkingDirectory = "${Env:ProgramFiles(x86)}\ProjectMatrix\ProjectNotify" $ProcInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Normal $ProcInfo.Verb = 'RunAs' $ProcInfo.UseShellExecute = $true [System.Diagnostics.Process]::Start($ProcInfo) After some more thought, here's a simpler way (in a single command even): Start-Job -Credential (Get-Credential) -ScriptBlock { $Dir = "${Env:ProgramFiles(x86)}\ProjectMatrix\ProjectNotify" $StartArgs = #{ 'FilePath' = "$Dir\ProjectNotify.exe" 'ArgumentList' = '/t' 'Verb' = 'RunAs' 'WindowStyle' = 'Normal' 'WorkingDirectory' = $Dir 'PassThru' = $true } Start-Process #StartArgs } | Wait-Job | Receive-Job My previous answer is at the bottom of this post now. References: about_Splatting Get-Credential Start-Process Start-Job Extra reading: Import-CliXml Export-CliXml Assuming an on-demand script, you should create a pscredential object if you want to natively run this from powershell: Launch.cmd SET "PS=%WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe" SET "SCRIPT=%SYSTEMDRIVE%\Path\to\wrapper.ps1" %PS% -NoProfile -NoLogo -ExecutionPolicy Bypass -File "%SCRIPT%" wrapper.ps1 $Cred = Get-Credential # To avoid prompting every time: # # if (-not (Test-Path -Path '.\mycred.xml')) { # Get-Credential | Export-CliXml -Path '.\mycred.xml' # } # $Cred = Import-CliXml -Path '.\mycred.xml' $StartArgs = #{ 'FilePath' = "$PSHOME\powershell.exe" 'ArgumentList' = '-NoProfile', '-NoLogo', '-File', '.\runas.ps1' 'Credential' = $Cred } Start-Process #StartArgs runas.ps1 $StartArgs = #{ 'FilePath' = "${Env:ProgramFiles(x86)}\ProjectMatrix\ProjectNotify\ProjectNotify.exe" 'ArgumentList' = '/t' 'Verb' = 'RunAs' } Start-Process #StartArgs
I know the question asks for arguements, but if you don't them, this works: Start cmd.exe -Verb RunAs You can also run this using the 'Run' window or search box: powershell -command start cmd.exe -verb runas
How to get output from powershell process
Here's the code function RunPowershellAsAdmin($CommandToBeExecuted) { If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { #$arguments = "& '" + $myinvocation.mycommand.definition + "'" Start-Process powershell -Verb runAs -ArgumentList "$CommandToBeExecuted" -Verbose } } RunPowershellAsAdmin("& { Import-Module WebAdministration; if(Test-Path 'IIS:\Sites\$Website_Name') { Remove-WebSite -Name '$Website_Name'; } }") -Verb and -RedirectStandardOutput are not in the same parameter, so i can not use -RedirectStandardOutput to get process output as per answer from this link. I want to run the process in a hidden window, wait for it to return and get the error, output and exit code. Is there any other solution? Thanks in advance.
If you need access to both RunAs in addition to redirecting any of the standard streams, you'll need to use the System.Diagnostics.Process and System.Diagnostics.ProcessStartInfo classes directly. More information on how to handle the redirected stream can be found on MSDN. $startInfo = new-object System.Diagnostics.ProcessStartInfo $startInfo.FileName = "powershell" $startInfo.Arguments = "& { Import-Module WebAdministration; ... }" $startInfo.Verb = "runas" $startInfo.RedirectStandardOutput = $true $process = [System.Diagnostics.Process]::Start($startInfo) $output = $process.StandardOutput.ReadToEnd() $process.WaitForExit()