Start-Process
produces no output by default.
(The only way to make it produce output directly is to use -PassThru
, which then doesn't return the script's output, but a System.Diagnostics.Process
instance representing the newly created process - see below.)
The only way to capture output from your script via Start-Process
is to use the -RedirectStandardOutput
and
-RedirectStandardError
parameters to capture the script's output as text, in files.[1][2]
You can then read those files in PowerShell after the new process has completed, which you can ensure in one of two ways:
Also pass the -Wait
switch to Start-Process
, to make the invocation synchronous, which means that when Start-Process
returns, the output has already been captured in the specified file(s).
Use -PassThru
to obtain a System.Diagnostics.Process
instance and pass it to Wait-Process
later (or use its .WaitForExit()
method directly; property .HasExited
can be used to check whether the process is still running).
Here's what may work in your situation:
$arguments = "-File C:\...\script1.ps1" + " -ClientName" + $DeviceName
# Launch the script in a new window running as the given user,
# capture its standard output in file ./out.txt,
# and wait for it to finish.
Start-Process -Wait -RedirectStandardOutput ./out.txt powershell -ArgumentList $arguments -Credential $credentials
"Running script1.ps1 produced the following output:"
Get-Content ./out.txt
The PowerShell CLI, regrettably, reports all of PowerShell's 6 output streams, via standard output (see this answer), so the above captures all output from your script, including error output.
However, you can use, e.g., -RedirectStandardError ./err.txt
to capture the error stream separately.
[1] Calling another PowerShell instance via its CLI offers a structured alternative to capturing unstructured text (the for-display output as it would print to the console, which is what happens by default):
-OutputFormat xml
(or -of xml
/ -o xml
) makes PowerShell format its output in CLIXML format, which is the same XML-based serialization format used in PowerShell remoting and background jobs for serializing rich objects, which you can "rehydrate" with a later Import-Clixml
call.
Note: For most complex objects there is a loss of type fidelity: that is, they are serialized as emulations of the original objects; in short as "property bags" without methods, which, however may be sufficient - see this answer.
Here's a quick demonstration, using a [datetime]
instance, which does deserialize with type fidelity:
# Call Get-Date via the PowerShell CLI and save the output
# in CLIXML format in file ./out.xml
Start-Process -Wait -RedirectStandardOutput ./out.xml powershell '-of xml -c Get-Date'
# Import the CLIXML file and convert its content back to a [datetime] instance.
"Type of the CLIXML-serialized and deserialized `Get-Date` output:"
(Import-CliXml ./out.xml).GetType().FullName # -> System.DateTime
[2] The character encoding of the output files is determined by the encoding stored in [Console]::OutputEncoding
, which reflects the current console output code page, which defaults to the system's active legacy OEM code page.