Make WinSCP commands run synchronously in PowerShell

1

1

I'm trying to use WinSCP to script a directory synchronization against a WebDAV location. I'm running it like this from PowerShell:

.\WinSCP.exe -log=.\winscp.log -command "open davs://username:password@www.example.com/" "synchronize remote .\test-files /path/to/webdav/test-files" "exit"

This works fine. The files are synchronized. I've deleted the WebDAV directory and rerun it to see that the files make it up there.

The problem is that WinSCP is exiting before the synchronization completes. You can see this by checking the current time after it finishes and comparing to the last timestamp in the log file.

Here's a PowerShell command that demos the problem:

& {
.\WinSCP.exe -log=.\winscp.log -command "open davs://username:password@www.example.com/" "synchronize remote .\test-files /path/to/webdav/test-files" "exit"
Get-Date
Write-Host 'Exit code:' $LASTEXITCODE
Start-Sleep -Seconds 30
Get-Content -Tail 6 .\WinSCP.log
}

Output:

Tuesday, April 17, 2018 20:41:52
Exit code: 0
. 2018-04-17 20:42:15.025 Copying finished: Transferred: 177, Elapsed: 0:00:20, CPS: 9/s
> 2018-04-17 20:42:15.025 Script: exit
. 2018-04-17 20:42:15.025 Script: Exit code: 0
. 2018-04-17 20:42:15.025 sess: Destroying session.
. 2018-04-17 20:42:15.025 sess: Closing connection.
. 2018-04-17 20:42:15.025 sess: Connection closed.

As you can see, WinSCP was still writing the log over 20 seconds after the command exited. This doesn't make a lot of sense. How can WinSCP determine if the command worked before it's finished? How can I make WinSCP stop and wait for the command to finish before it exits and before it reports success or failure?

jpmc26

Posted 2018-04-18T00:46:45.543

Reputation: 393

Answers

1

PowerShell does not wait for GUI applications to complete before proceeding to the next command.

You can use piping trick to solve this, as seen in How to tell PowerShell to wait for each command to end before starting the next?

.\WinSCP.exe ... | Out-Null

Though easier is to use WinSCP scripting interface, winscp.com, instead. That's a console equivalent of winscp.exe


Though interestingly your command-line syntax does not produce winscp.log log file for me in any case. PowerShell seems to corrupt the command-line, when - is used for switches. With /, it works:

.\WinSCP.com /log=.\winscp.log /command "open davs://username:password@www.example.com/" "synchronize remote .\test-files /path/to/webdav/test-files" "exit"

Martin Prikryl

Posted 2018-04-18T00:46:45.543

Reputation: 13 764

I believe I could reproduce this in Command Prompt. I just chose PowerShell for the convenience of spitting out the timestamp and reading the file. (It also made pasting the full sequence of commands at once easier, given the sleep.) But I'll have to retest tomorrow, since I'm not at the same machine right now. – jpmc26 – 2018-04-18T06:26:54.293

When you execute GUI application from Windows command-line (cmd.exe), it indeed won't block the prompt either. But it will block when executed from .bat file. Again, use winscp.com to solve this. – Martin Prikryl – 2018-04-18T06:32:42.147

Thanks. Not sure what's up with the - vs. / problem. I know the docs mostly say /, but I usually try - on all my executable calls and prefer it when it works, because of the usage of slashes for other purposes (like directory separators). Supporting both does not seem to be uncommon. Are you using the latest version (5.13.1 (Build 8265))? – jpmc26 – 2018-04-18T20:34:53.257

It's not about WinSCP. WinSCP is happy with -. But if I execute your exact PowerShell script, I can see in Task Manager that PowerShell adds a space between -log= and .\winscp.log. https://i.stack.imgur.com/s1t30.png What does not work. It makes WinSCP consider .\winscp.log to be a hostname to connect to, what causes an error (but the script file is still executed anyway, but no logging happens). If I replace - with /, no space is added.

– Martin Prikryl – 2018-04-19T06:01:55.043

Maybe PowerShell version difference? Something else that might fix it is to quote the entire argument, to minimize PowerShell's processing of the command. If that works for you, I can update the question. – jpmc26 – 2018-04-19T06:27:26.623

That's ok, it's not really a core part of the question. – Martin Prikryl – 2018-04-19T06:37:21.927