1

I have a PowerShell scripts, the basic function is to run curl.exe to copy a file from remote ftp server to local. At first, I used the following code to run curl.exe:

$curlPath = "curl.exe"
$curlArgs = "sftp://download.url.com/filename_20220618.zip --user username:psw -o D:\filename_20220618.zip -k"
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = $curlPath
$pinfo.Arguments = $curlArgs
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.CreateNoWindow = $true
$curlProcess = New-Object System.Diagnostics.Process
$curlProcess.StartInfo = $pinfo
$curlProcess.Start() | Out-Null
$curlProcess.WaitForExit()

The code sometimes works. But most of the time will pending forever. I don't known the cause. When the code works, I can get error message from $curlProcess.StandError if $curlProcess.ExitCode is not 0.

To work around, I decided to use

$curlPath = "curl.exe"
$curlArgs = "sftp://download.url.com/filename_20220618.zip --user username:psw -o D:\filename_20220618.zip -k"
$curlProcess = Start-Process $curlPath -ArgumentList $curlArgs -Wait -PassThru -WindowStyle Hidden

The above codes worked. The only problem is when $curlProcess.ExistCode is not 0, I cannot get the error message. $curlProcess.StandError is always empty.

Does anyone know how to fix this issue?

DBZHOU
  • 169
  • 2
  • 12

1 Answers1

0

To synchronously execute console applications and capture their output, call them directly, do not use Start-Process (or the System.Diagnostics.Process API it is based on) - see this answer for background information, and GitHub docs issue #6239 for guidance on when use of Start-Process is and isn't appropriate.

Direct invocation:

  • implicitly executes console applications synchronously (in a blocking fashion)

  • connects a console application's stdout and stderr streams to PowerShell streams, which passes them through to the host (display) by default, but also allows:

    • capturing stdout output, simply by piping it to another command or capturing it in a variable (e.g., $var = curl.exe ...); note that the output is captured as lines of text, with a single line getting captured as-is, and two or more getting captured as an array of lines.

    • redirecting stderr output, either to a file (e.g., 2>errs.txt) or by merging it into the success output stream (2>&1) - see this answer for more information.

  • makes the process exit code available via the automatic $LASTEXITCODE variable.

# Prints both stdout and stderr to the display.
# $LASTEXITCODE reflects the process exit code.
curl.exe sftp://download.url.com/filename_20220618.zip --user username:psw -o D:\filename_20220618.zip -k
mklement0
  • 382,024
  • 64
  • 607
  • 775