Converting Script to Code Based on .NET Assembly
When you have your automation task implemented using WinSCP script, you may sooner or later find yourself limited by its capabilities. The scripting particularly lacks (by design) any support for control structures (like conditional processing, loops/cycles, etc.). A solution is to convert your script to code that uses WinSCP .NET assembly.
Advertisement
Choosing Language
Start by choosing a language. WinSCP .NET assembly can be used from any .NET language or any language that supports COM.
If you do not have your own preferred language, use PowerShell.
Mapping Script Commands to .NET Assembly Calls
Most script commands can be directly mapped to their equivalent .NET assembly method calls. The mapping is described in respective scripting command documentation page.
There are some conceptual differences though. These are discussed in following sections.
Batch Mode
Batch scripts (specified using /script
or /command
command-line switches) run in an option batch abort
mode.
To emulate the option batch abort
call a method OperationResultBase.Check
for all Session
methods that return an operation result (such as GetFiles
, PutFiles
, and SynchronizeDirectories
).
If you are using option batch continue
mode, handle Session.QueryReceived
event and call QueryReceivedEventArgs.Continue
in the handler. For an example, see Recursively download directory tree with custom error handling.
Read more about capturing errors in .NET assembly. Documentation for converting an individual scripting commands (such as get
command mapping) details more mapping specifics for the respective operations.
Default Configuration
Scripting mode by default shares configuration with graphical mode. On the contrary the .NET assembly is isolated from graphical mode configuration (equivalent to using /ini=nul
command-line parameter in scripting mode).
Advertisement
It means that you cannot use stored sites, when opening session with .NET assembly. You need to configure all your site settings directly in your code (using SessionOptions
class).
It also means that with .NET assembly, you always start with default transfer settings, default resume/endurance settings, etc.
Relative/Absolute Paths
Scripting mode (similarly to graphical mode) has concept of current working directory (both on local and remote side). On the contrary, the .NET assembly does not; there are no equivalents to cd
and lcd
commands.
In the scripting you can use paths relative to current working directory in parameters to script commands. In the .NET assembly, you need to always use absolute paths or paths relative to initial working directory (for remote paths the initial directory is typically a home directory).
For example following script snippet:
cd /home/martinp lcd d:\ get test.txt
needs to be converted to following call in PowerShell:
$session.GetFiles("/home/martinp/test.txt", "d:\")
Example
Following script:
# Connect open sftp://user:password@example.com/ -hostkey="ssh-rsa 2048 xxxxxxxxxxx..." # Change remote directory cd /home/user # Force binary mode transfer option transfer binary # Download file to the local directory d:\ get examplefile.txt d:\ # Disconnect close # Exit WinSCP exit
maps to following PowerShell code:
try { # Load WinSCP .NET assembly Add-Type -Path "WinSCPnet.dll" # Setup session options $sessionOptions = New-Object WinSCP.SessionOptions -Property @{ Protocol = [WinSCP.Protocol]::Sftp HostName = "example.com" UserName = "user" Password = "password" SshHostKeyFingerprint = "ssh-rsa 2048 xxxxxxxxxxx..." } $session = New-Object WinSCP.Session try { # Connect $session.Open($sessionOptions) # Force binary mode transfer $transferOptions = New-Object WinSCP.TransferOptions $transferOptions.TransferMode = [WinSCP.TransferMode]::Binary # Download file to the local directory d:\ # Note use of absolute path $transferResult = $session.GetFiles("/home/user/examplefile.txt", "d:\", $False, $transferOptions) # Throw on any error to emulate the default "option batch abort" $transferResult.Check() } finally { # Disconnect, clean up $session.Dispose() } exit 0 } catch { Write-Host "Error: $($_.Exception.Message)" exit 1 }
Advertisement