Differences
This shows you the differences between the selected revisions of the page.
scripts 2014-03-06 | scripts 2021-03-31 (current) | ||
Line 1: | Line 1: | ||
====== Useful Scripts ====== | ====== Useful Scripts ====== | ||
- | ~~SPLIT~~ | ||
- | ===== [[upload_single_file]] Uploading a single file ===== | + | ··* [[script_upload_single_file|*]] |
- | A single file upload involves so few commands that it is enough to provide them on the command line, saving writing a script file: | + | ··* [[script_upload_multiple_servers|*]] |
+ | * [[script_download_timestamped_filename|*]] | ||
+ | * [[script_download_most_recent_file|*]] | ||
+ | ··* [[script_upload_most_recent_file|*]] | ||
+ | * [[script_checking_file_existence|*]] | ||
+ | * [[script_local_move_after_successful_upload|*]] | ||
+ | * [[script_locking_files_while_uploading|*]] | ||
+ | * [[script_downloading_when_done_file_exists|*]] | ||
+ | * [[script_download_files_to_same_folder|*]] | ||
+ | * [[script_upload_file_list|*]] | ||
+ | * [[script_synchronize_any_local_file|*]] | ||
+ | * [[script_auto_compress_download|*]] | ||
+ | * [[script_custom_listing_format_csv|*]] | ||
+ | * [[script_retry|*]] | ||
+ | * [[script_formatting_timestamp_batch_file|*]] | ||
+ | * [[script_email|*]] | ||
+ | * [[script_vbnet_robust_example|*]] | ||
- | <code> | ||
- | winscp.com /command "option batch abort" "option confirm off" "open sftp://user@example.com/" "put examplefile.txt /home/user/" "exit" | ||
- | </code> | ||
- | |||
- | However you may want to use a script file anyway, so you can later expand it: | ||
- | |||
- | <code winscp> | ||
- | option batch abort | ||
- | option confirm off | ||
- | open sftp://user@example.com/ | ||
- | put examplefile.txt /home/user/ | ||
- | exit | ||
- | </code> | ||
- | |||
- | To run the script use following command (providing you have saved the script to file ''example.txt''): | ||
- | |||
- | <code> | ||
- | winscp.com /script=example.txt | ||
- | </code> | ||
- | |||
- | |||
- | ===== [[download_timestamped_filename]] Downloading file to timestamped-filename ===== | ||
- | |||
- | ==== Using WinSCP .NET Assembly ==== | ||
- | Use [[library|WinSCP .NET assembly]] from your favourite language. Use relevant construct of your language or API of your runtime environment for the file name formatting. | ||
- | |||
- | If you do not have your favourite language, use [[library_powershell|PowerShell]]: | ||
- | |||
- | <code powershell> | ||
- | try | ||
- | { | ||
- | # Load WinSCP .NET assembly | ||
- | [Reflection.Assembly]::LoadFrom("WinSCPnet.dll") | Out-Null | ||
- | |||
- | # Setup session options | ||
- | $sessionOptions = New-Object WinSCP.SessionOptions | ||
- | $sessionOptions.Protocol = [WinSCP.Protocol]::Sftp | ||
- | $sessionOptions.HostName = "example.com" | ||
- | $sessionOptions.UserName = "user" | ||
- | $sessionOptions.Password = "mypassword" | ||
- | $sessionOptions.SshHostKeyFingerprint = "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx" | ||
- | |||
- | $session = New-Object WinSCP.Session | ||
- | |||
- | try | ||
- | { | ||
- | # Connect | ||
- | $session.Open($sessionOptions) | ||
- | |||
- | $localPath = "c:\downloaded\" | ||
- | $remotePath = "/home/user/" | ||
- | $file = "download.txt" | ||
- | |||
- | # Format timestamp | ||
- | $stamp = $(Get-Date -f "yyyyMMddHHmmss") | ||
- | |||
- | # Download the file and throw on any error | ||
- | $session.GetFiles( | ||
- | ($remotePath + $file), | ||
- | ($localPath + $file + "." + $stamp)).Check() | ||
- | } | ||
- | finally | ||
- | { | ||
- | # Disconnect, clean up | ||
- | $session.Dispose() | ||
- | } | ||
- | |||
- | exit 0 | ||
- | } | ||
- | catch [Exception] | ||
- | { | ||
- | Write-Host $_.Exception.Message | ||
- | exit 1 | ||
- | } | ||
- | </code> | ||
- | |||
- | ==== Using WinSCP Scripting ==== | ||
- | You may use following [[guide_automation_advanced#wsh|Windows script host JavaScript code]] (''example.js''): | ||
- | |||
- | <code javascript> | ||
- | // Local path to download to (keep trailing slash) | ||
- | var LOCALPATH = "c:\\downloaded\\"; | ||
- | // Remote path to download from (keep trailing slash) | ||
- | var REMOTEPATH = "/home/user/"; | ||
- | // File to download | ||
- | var FILE = "download.txt"; | ||
- | // Session to connect to | ||
- | var SESSION = "session"; | ||
- | // Path to winscp.com | ||
- | var WINSCP = "c:\\program files\\winscp\\winscp.com"; | ||
- | |||
- | // helper function to pad zeroes to the left of number | ||
- | function pad(n, len) | ||
- | { | ||
- | var s = n.toString(); | ||
- | while (s.length < len) | ||
- | { | ||
- | s = '0' + s; | ||
- | } | ||
- | return s; | ||
- | } | ||
- | |||
- | var date = new Date(); | ||
- | |||
- | // format timestamp | ||
- | var stamp = | ||
- | pad(date.getFullYear(), 4) + | ||
- | pad(date.getMonth(), 2) + | ||
- | pad(date.getDate(), 2) + | ||
- | pad(date.getHours(), 2) + | ||
- | pad(date.getMinutes(), 2) + | ||
- | pad(date.getSeconds(), 2); | ||
- | |||
- | var shell = WScript.CreateObject("WScript.Shell"); | ||
- | |||
- | // run winscp to download the file into timestamped-filename | ||
- | exec = shell.Exec("\"" + WINSCP + "\""); | ||
- | exec.StdIn.Write( | ||
- | "option batch abort\n" + | ||
- | "open \"" + SESSION + "\"\n" + | ||
- | "get \"" + REMOTEPATH + FILE + "\" \"" + LOCALPATH + FILE + "." + stamp + "\"\n" + | ||
- | "exit\n"); | ||
- | |||
- | // wait until it finishes and collect its output | ||
- | var output = exec.StdOut.ReadAll(); | ||
- | // optionally print the output | ||
- | WScript.Echo(output); | ||
- | </code> | ||
- | |||
- | Run the script with command: | ||
- | <code> | ||
- | cscript /nologo example.js | ||
- | </code> | ||
- | |||
- | ===== [[download_most_recent_file]] Downloading the most recent file ===== | ||
- | |||
- | ==== Using WinSCP .NET Assembly ==== | ||
- | Use [[library|WinSCP .NET assembly]] from your favourite language. | ||
- | |||
- | If you do not have your favourite language, use [[library_powershell|PowerShell]]: | ||
- | |||
- | <code powershell> | ||
- | try | ||
- | { | ||
- | # Load WinSCP .NET assembly | ||
- | [Reflection.Assembly]::LoadFrom("WinSCPnet.dll") | Out-Null | ||
- | |||
- | # Setup session options | ||
- | $sessionOptions = New-Object WinSCP.SessionOptions | ||
- | $sessionOptions.Protocol = [WinSCP.Protocol]::Sftp | ||
- | $sessionOptions.HostName = "example.com" | ||
- | $sessionOptions.UserName = "user" | ||
- | $sessionOptions.Password = "mypassword" | ||
- | $sessionOptions.SshHostKeyFingerprint = "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx" | ||
- | |||
- | $session = New-Object WinSCP.Session | ||
- | |||
- | try | ||
- | { | ||
- | # Connect | ||
- | $session.Open($sessionOptions) | ||
- | |||
- | $localPath = "c:\downloaded\" | ||
- | $remotePath = "/home/user/" | ||
- | |||
- | # Gel list of files in the directory | ||
- | $files = $session.ListDirectory($remotePath) | ||
- | |||
- | # Select the most recent file | ||
- | $latest = | ||
- | $files.Files | | ||
- | Where-Object { -not $_.IsDirectory } | | ||
- | Sort-Object LastWriteTime | | ||
- | Select-Object -Last 1 | ||
- | |||
- | # Any file at all? | ||
- | if ($latest -eq $Null) | ||
- | { | ||
- | Write-Host "No file found" | ||
- | exit 1 | ||
- | } | ||
- | |||
- | # Download the selected file | ||
- | $session.GetFiles($session.EscapeFileMask($remotePath + $latest.Name), $localPath).Check() | ||
- | } | ||
- | finally | ||
- | { | ||
- | # Disconnect, clean up | ||
- | $session.Dispose() | ||
- | } | ||
- | |||
- | exit 0 | ||
- | } | ||
- | catch [Exception] | ||
- | { | ||
- | Write-Host $_.Exception.Message | ||
- | exit 1 | ||
- | } | ||
- | </code> | ||
- | |||
- | ==== Using WinSCP Scripting ==== | ||
- | You may use following [[guide_automation_advanced#wsh|Windows script host JavaScript code]] (''example.js''): | ||
- | |||
- | <code javascript> | ||
- | // Configuration | ||
- | |||
- | // Local path to download to (keep trailing slash) | ||
- | var LOCALPATH = "c:\\downloaded\\"; | ||
- | // Remote path to search in (keep trailing slash) | ||
- | var REMOTEPATH = "/home/user/"; | ||
- | // Mask of files to search for | ||
- | var FILEMASK = "*.*"; | ||
- | // Session to connect to | ||
- | var SESSION = "session"; | ||
- | // Path to winscp.com | ||
- | var WINSCP = "c:\\program files\\winscp\\winscp.com"; | ||
- | |||
- | var filesys = WScript.CreateObject("Scripting.FileSystemObject"); | ||
- | var shell = WScript.CreateObject("WScript.Shell"); | ||
- | |||
- | var logfilepath = filesys.GetSpecialFolder(2) + "\\" + filesys.GetTempName() + ".xml"; | ||
- | |||
- | var exec; | ||
- | |||
- | // run winscp to get list of file in the remote directory into XML log | ||
- | exec = shell.Exec("\"" + WINSCP + "\" /xmllog=\"" + logfilepath + "\""); | ||
- | exec.StdIn.Write( | ||
- | "option batch abort\n" + | ||
- | "open \"" + SESSION + "\"\n" + | ||
- | "ls \"" + REMOTEPATH + FILEMASK + "\"\n" + | ||
- | "exit\n"); | ||
- | |||
- | // wait until it finishes and collect its output | ||
- | var output = exec.StdOut.ReadAll(); | ||
- | // optionally print the output | ||
- | WScript.Echo(output); | ||
- | |||
- | if (exec.ExitCode != 0) | ||
- | { | ||
- | WScript.Echo("Error retrieving list of files"); | ||
- | WScript.Quit(1); | ||
- | } | ||
- | |||
- | // look for log file | ||
- | var logfile = filesys.GetFile(logfilepath); | ||
- | |||
- | if (logfile == null) | ||
- | { | ||
- | WScript.Echo("Cannot find log file"); | ||
- | WScript.Quit(1); | ||
- | } | ||
- | |||
- | // parse XML log file | ||
- | var doc = new ActiveXObject("MSXML2.DOMDocument"); | ||
- | doc.async = false; | ||
- | doc.load(logfilepath); | ||
- | |||
- | doc.setProperty("SelectionNamespaces", | ||
- | "xmlns:w='http://winscp.net/schema/session/1.0'"); | ||
- | |||
- | var nodes = doc.selectNodes("//w:file"); | ||
- | |||
- | // find the latest file | ||
- | var filenameLatest = null; | ||
- | var modificationLatest = null; | ||
- | for (var i = 0; i < nodes.length; ++i) | ||
- | { | ||
- | var filename = nodes[i].selectSingleNode("w:filename/@value"); | ||
- | var modification = nodes[i].selectSingleNode("w:modification/@value"); | ||
- | if ((filename != null) && | ||
- | (filename.value != ".") && | ||
- | (filename.value != "..") && | ||
- | (modification != null)) | ||
- | { | ||
- | // can compare timestamps stringwise | ||
- | if ((modificationLatest == null) || | ||
- | (modificationLatest < modification.value)) | ||
- | { | ||
- | modificationLatest = modification.value; | ||
- | filenameLatest = filename.value; | ||
- | } | ||
- | } | ||
- | } | ||
- | |||
- | // no file in the log | ||
- | if (filenameLatest == null) | ||
- | { | ||
- | WScript.Echo("No file found"); | ||
- | WScript.Quit(0); | ||
- | } | ||
- | |||
- | // run winscp to download the latest file | ||
- | exec = shell.Exec("\"" + WINSCP + "\""); | ||
- | exec.StdIn.Write( | ||
- | "option batch abort\n" + | ||
- | "option confirm off\n" + | ||
- | "open \"" + SESSION + "\"\n" + | ||
- | "get \"" + REMOTEPATH + filenameLatest + "\" \"" + LOCALPATH + "\"\n" + | ||
- | "exit\n"); | ||
- | |||
- | // wait until it finishes and collect its output | ||
- | var output = exec.StdOut.ReadAll(); | ||
- | // optionally print the output | ||
- | WScript.Echo(output); | ||
- | |||
- | if (exec.ExitCode != 0) | ||
- | { | ||
- | WScript.Echo("Error downloading " + filenameLatest); | ||
- | WScript.Quit(1); | ||
- | } | ||
- | </code> | ||
- | |||
- | Run the script with command: | ||
- | <code> | ||
- | cscript /nologo example.js | ||
- | </code> | ||
- | |||
- | ===== [[checking_file_existence]] Checking file existence ===== | ||
- | |||
- | ==== Using WinSCP .NET Assembly ==== | ||
- | Use method ''[[library_session_fileexists|Session.FileExists]]'' from [[library|WinSCP .NET assembly]]. | ||
- | |||
- | If you do not have your favourite language, use [[library_powershell|PowerShell]]: | ||
- | |||
- | <code powershell> | ||
- | $remotePath = "/home/user/test.txt" | ||
- | |||
- | if ($session.FileExists($remotePath)) | ||
- | { | ||
- | Write-Host ("File {0} exists" -f $remotePath) | ||
- | } | ||
- | </code> | ||
- | |||
- | See complete [[library_session_fileexists#powershell|PowerShell example for Session.FileExists]]. | ||
- | |||
- | ~~AD~~ | ||
- | |||
- | ==== Using WinSCP Scripting and XML Logging from JScript ==== | ||
- | You may use following [[guide_automation_advanced#wsh|Windows script host JavaScript code]] (''example.js''): | ||
- | |||
- | <code javascript> | ||
- | // Configuration | ||
- | |||
- | // Remote file search for | ||
- | var FILEPATH = "/home/user/myfile.dat"; | ||
- | // Session to connect to | ||
- | var SESSION = "session"; | ||
- | // Path to winscp.com | ||
- | var WINSCP = "c:\\program files\\winscp\\winscp.com"; | ||
- | |||
- | var filesys = WScript.CreateObject("Scripting.FileSystemObject"); | ||
- | var shell = WScript.CreateObject("WScript.Shell"); | ||
- | |||
- | var logfilepath = filesys.GetSpecialFolder(2) + "\\" + filesys.GetTempName() + ".xml"; | ||
- | |||
- | var p = FILEPATH.lastIndexOf('/'); | ||
- | var path = FILEPATH.substring(0, p); | ||
- | var filename = FILEPATH.substring(p + 1); | ||
- | |||
- | var exec; | ||
- | |||
- | // run winscp to check for file existence | ||
- | exec = shell.Exec("\"" + WINSCP + "\" /xmllog=\"" + logfilepath + "\""); | ||
- | exec.StdIn.Write( | ||
- | "option batch abort\n" + | ||
- | "open \"" + SESSION + "\"\n" + | ||
- | "ls \"" + path + "\"\n" + | ||
- | "exit\n"); | ||
- | |||
- | // wait until it finishes and collect its output | ||
- | var output = exec.StdOut.ReadAll(); | ||
- | // optionally print the output | ||
- | WScript.Echo(output); | ||
- | |||
- | if (exec.ExitCode != 0) | ||
- | { | ||
- | WScript.Echo("Error checking for file existence"); | ||
- | WScript.Quit(1); | ||
- | } | ||
- | |||
- | // look for log file | ||
- | var logfile = filesys.GetFile(logfilepath); | ||
- | |||
- | if (logfile == null) | ||
- | { | ||
- | WScript.Echo("Cannot find log file"); | ||
- | WScript.Quit(1); | ||
- | } | ||
- | |||
- | // parse XML log file | ||
- | var doc = new ActiveXObject("MSXML2.DOMDocument"); | ||
- | doc.async = false; | ||
- | doc.load(logfilepath); | ||
- | |||
- | doc.setProperty("SelectionNamespaces", | ||
- | "xmlns:w='http://winscp.net/schema/session/1.0'"); | ||
- | |||
- | var nodes = doc.selectNodes("//w:file/w:filename[@value='" + filename + "']"); | ||
- | |||
- | if (nodes.length > 0) | ||
- | { | ||
- | WScript.Echo("File found"); | ||
- | // signalize file existence to calling process; | ||
- | // you can also continue with processing (e.g. downloading the file) | ||
- | // directly from the script here | ||
- | WScript.Quit(0); | ||
- | } | ||
- | else | ||
- | { | ||
- | WScript.Echo("File not found"); | ||
- | WScript.Quit(1); | ||
- | } | ||
- | </code> | ||
- | |||
- | Run the script with command: | ||
- | <code> | ||
- | cscript /nologo example.js | ||
- | </code> | ||
- | |||
- | Following batch file shown how to continue with processing based on file exitence: | ||
- | <code> | ||
- | cscript /nologo example.js | ||
- | if errorlevel 1 goto error | ||
- | |||
- | echo File exists, do something | ||
- | rem Do something | ||
- | exit | ||
- | |||
- | :error | ||
- | echo Error or file not exists | ||
- | </code> | ||
- | |||
- | Alternatively you can continue with the processing directly in JavaScript code as suggested by respective comments. | ||
- | |||
- | ===== [[local_move_after_successful_upload]] Moving local files to different location after successful upload ===== | ||
- | |||
- | ==== [[library]] Using WinSCP .NET Assembly ==== | ||
- | Use [[library|WinSCP .NET assembly]] from your favourite language. | ||
- | |||
- | If you do not have your favourite language, use [[library_powershell|PowerShell]]: | ||
- | |||
- | <code powershell> | ||
- | try | ||
- | { | ||
- | # Load WinSCP .NET assembly | ||
- | [Reflection.Assembly]::LoadFrom("WinSCPnet.dll") | Out-Null | ||
- | |||
- | # Setup session options | ||
- | $sessionOptions = New-Object WinSCP.SessionOptions | ||
- | $sessionOptions.Protocol = [WinSCP.Protocol]::Sftp | ||
- | $sessionOptions.HostName = "example.com" | ||
- | $sessionOptions.UserName = "user" | ||
- | $sessionOptions.Password = "mypassword" | ||
- | $sessionOptions.SshHostKeyFingerprint = "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx" | ||
- | |||
- | $session = New-Object WinSCP.Session | ||
- | |||
- | try | ||
- | { | ||
- | # Connect | ||
- | $session.Open($sessionOptions) | ||
- | |||
- | $localPath = "C:\upload\*" | ||
- | $remotePath = "/home/user/" | ||
- | $backupPath = "C:\backup\" | ||
- | |||
- | # Upload files, collect results | ||
- | $transferResult = $session.PutFiles($localPath, $remotePath) | ||
- | |||
- | # Iterate over every transfer | ||
- | foreach ($transfer in $transferResult.Transfers) | ||
- | { | ||
- | # Success or error? | ||
- | if ($transfer.Error -eq $Null) | ||
- | { | ||
- | Write-Host ("Upload of {0} succeeded, moving to backup" -f | ||
- | $transfer.FileName) | ||
- | # Upload succeeded, move source file to backup | ||
- | Move-Item $transfer.FileName $backupPath | ||
- | } | ||
- | else | ||
- | { | ||
- | Write-Host ("Upload of {0} failed: {1}" -f | ||
- | $transfer.FileName, $transfer.Error.Message) | ||
- | } | ||
- | } | ||
- | } | ||
- | finally | ||
- | { | ||
- | # Disconnect, clean up | ||
- | $session.Dispose() | ||
- | } | ||
- | |||
- | exit 0 | ||
- | } | ||
- | catch [Exception] | ||
- | { | ||
- | Write-Host $_.Exception.Message | ||
- | exit 1 | ||
- | } | ||
- | </code> | ||
- | |||
- | ==== Using WinSCP Scripting ==== | ||
- | WinSCP scripting does not support move command for local files. Instead you can combine WinSCP script with batch file: | ||
- | |||
- | <code winscp> | ||
- | option batch abort | ||
- | option confirm off | ||
- | # Connect | ||
- | open mysession | ||
- | # Upload the files | ||
- | put *.* | ||
- | </code> | ||
- | |||
- | Launch the above script from batch file like the one below: | ||
- | |||
- | <code> | ||
- | winscp.com /script=example.txt | ||
- | if errorlevel 1 goto error | ||
- | |||
- | echo Upload succeeded, moving local files | ||
- | move *.* c:\backup\ | ||
- | exit | ||
- | |||
- | :error | ||
- | echo Upload failed, keeping local files | ||
- | </code> | ||
- | |||
- | ===== [[synchronize_any_local_file]] Shortcut to synchronize any local directory with remote directory ===== | ||
- | |||
- | You may want to have a script that synchronizes any local directory with a same-named subdirectory of fixed remote path, e.g.: | ||
- | * ''c:\www\gallery'' with ''/home/user/www/gallery''; | ||
- | * ''c:\users\username\www\forum'' with ''/home/user/www/forum''. &winpath | ||
- | |||
- | Such a script is particularly useful for integrating with Windows Explorer's 'Send To' menu. | ||
- | |||
- | First create wrapper batch file to store the paths you want to synchronize into environment variables (change ''/home/user/www/'' to remote path root you want to synchronize against): | ||
- | <code> | ||
- | winscp.com /script=example.txt /parameter %1 "/home/user/www/%~n1%~x1" | ||
- | </code> | ||
- | |||
- | The script ''example.txt'' may look like: | ||
- | |||
- | <code winscp> | ||
- | # Being intended for interactive session, we are not enabling batch mode | ||
- | # Connect | ||
- | open mysession | ||
- | # Synchronize paths provided via environment variables | ||
- | synchronize remote "%1%" "%2%" | ||
- | </code> | ||
- | |||
- | Then you can make a shortcut to the batch file: | ||
- | * When placed on desktop, you can drop any local directory to it to start synchronization; | ||
- | * When placed to ''C:\Users\username\AppData\Roaming\Microsoft\Windows\SendTo'', you can use //Send To > Your Shortcut// from context menu of any local directory. &winpath | ||
- | |||
- | ===== [[auto_compress_download]] Automatically compress files before download ===== | ||
- | Following script compresses selected files into tar/gzip archive and downloads it: | ||
- | |||
- | <code winscp> | ||
- | option batch abort | ||
- | option confirm off | ||
- | open mysession | ||
- | cd %1% | ||
- | call tar -czf /tmp/archive.tar.gz %2% | ||
- | lpwd | ||
- | get -delete /tmp/archive.tar.gz | ||
- | exit | ||
- | </code> | ||
- | |||
- | Launch the above script from batch file like the one below, which automatically decompresses the archive: | ||
- | |||
- | <code> | ||
- | winscp.com /script=example.txt /parameter %* | ||
- | if errorlevel 1 goto error | ||
- | |||
- | echo Retrieving files succeeded | ||
- | gzip -d archive.tar.gz | ||
- | tar -xf archive.tar | ||
- | del archive.tar | ||
- | exit | ||
- | |||
- | :error | ||
- | echo Retrieving files failed | ||
- | </code> | ||
- | |||
- | Example of running the batch file to download all files under ''/home/user/www'': | ||
- | |||
- | <code> | ||
- | example.bat /home/user/www *.* | ||
- | </code> | ||
- | |||
- | The batch file needs Windows ports of ''gzip'' and ''tar'' tools. You can get them from [[http://sourceforge.net/projects/unxutils/|UnxUtils]] project. | ||
- | |||
- | ===== [[vbnet_robust_example]] Running WinSCP from VB.NET ===== | ||
- | &deprecated_use_net | ||
- | |||
- | __**Please note the existence of a second code. This code is functional for uploading and donwload with vb .net 2005. This same code that worked in VB . Net 2005 was also tested in VB .Net 2012 (Version 11.0.50.727.42 & Netframework Version 4.5.50938) and worked without changes**__ | ||
- | |||
- | Following is more robust alternative to simple example contained in guide to [[guide_dotnet|SFTP file transfers in .NET]]. | ||
- | |||
- | <code vbnet> | ||
- | Imports System | ||
- | Imports System.IO | ||
- | Imports System.Diagnostics | ||
- | Imports System.Xml | ||
- | Imports System.Xml.XPath | ||
- | Imports System.Configuration.ConfigurationManager | ||
- | |||
- | Public Class SFTP | ||
- | ' SFTP support, built on WinSCP | ||
- | Public Shared Function PutSFTP(ByRef filename As String, ByRef remotehost As String, ByRef username As String, ByRef password As String, _ | ||
- | Optional ByVal outfilename As String = Nothing, Optional ByVal output As String = Nothing, | ||
- | Optional ByRef errmsg As String = Nothing) As Boolean | ||
- | |||
- | ' Run hidden WinSCP process | ||
- | Dim winscp As Process = New Process() | ||
- | Dim logname As String = Path.ChangeExtension(Path.GetTempFileName, "xml") | ||
- | With winscp.StartInfo | ||
- | ' SFTPExecutable needs to be defined in app.config to point to winscp.com | ||
- | Try | ||
- | .FileName = AppSettings("SFTPExecutable") | ||
- | If .FileName Is Nothing OrElse .FileName.Length = 0 Then Throw (New Exception("from PutSFTP: SFTPExecutable not set in config file.")) | ||
- | Catch ex As Exception | ||
- | errmsg = ex.Message | ||
- | Return False | ||
- | End Try | ||
- | .Arguments = "/xmllog=" + logname | ||
- | .UseShellExecute = False | ||
- | .RedirectStandardInput = True | ||
- | .RedirectStandardOutput = True | ||
- | .CreateNoWindow = True | ||
- | End With | ||
- | Try | ||
- | winscp.Start() | ||
- | Catch ex As Exception | ||
- | errmsg = "from PutSFTP: Could not run the WinSCP executable " & winscp.StartInfo.FileName & Environment.NewLine & ex.Message | ||
- | Return False | ||
- | End Try | ||
- | |||
- | ' Feed in the scripting commands | ||
- | With winscp.StandardInput | ||
- | .WriteLine("option batch abort") | ||
- | .WriteLine("option confirm off") | ||
- | .WriteLine("open sftp://" & username & ":" & password & "@" & remotehost & "/") | ||
- | If outfilename Is Nothing Then .WriteLine("put " & filename) Else .WriteLine("put " & filename & " """ & outfilename & """") | ||
- | .Close() | ||
- | End With | ||
- | If output IsNot Nothing Then output = winscp.StandardOutput.ReadToEnd() | ||
- | |||
- | ' Wait until WinSCP finishes | ||
- | winscp.WaitForExit() | ||
- | |||
- | ' Parse and interpret the XML log | ||
- | ' (Note that in case of fatal failure the log file may not exist at all) | ||
- | If Not File.Exists(logname) Then | ||
- | errmsg = "from PutSFTP: The WinSCP executable appears to have crashed." | ||
- | Return False | ||
- | End If | ||
- | |||
- | Dim log As XPathDocument = New XPathDocument(logname) | ||
- | Dim ns As XmlNamespaceManager = New XmlNamespaceManager(New NameTable()) | ||
- | ns.AddNamespace("w", "http://winscp.net/schema/session/1.0") | ||
- | Dim nav As XPathNavigator = log.CreateNavigator() | ||
- | |||
- | ' Success (0) or error? | ||
- | Dim status As Boolean = (winscp.ExitCode = 0) | ||
- | If Not status Then | ||
- | errmsg = "from PutSFTP: There was an error transferring " & filename & "." | ||
- | ' See if there are any messages associated with the error | ||
- | For Each message As XPathNavigator In nav.Select("//w:message", ns) | ||
- | errmsg &= Environment.NewLine & message.Value | ||
- | Next message | ||
- | End If | ||
- | |||
- | Try | ||
- | My.Computer.FileSystem.DeleteFile(logname) | ||
- | Catch ex As Exception | ||
- | ' at least we tried to clean up | ||
- | End Try | ||
- | |||
- | Return status | ||
- | End Function | ||
- | End Class | ||
- | </code> | ||
- | |||
- | In this code below, have to add the files in there resources tab in the project properties, add also the OpenFileDialog1 and SaveFileDialog1 object. Add WinSCP.com and WinSCP.exe files as resources. The reference: Public Class WINSCP is for the form class | ||
- | The Full Project can be download at link forum: | ||
- | winscp.net/forum/viewtopic.php?p=49701#49701 | ||
- | |||
- | This code that work in VB .Net 2005 and also tested in VB .Net 2012 and worked without changes. (W7 x64 RAM: 2GB) | ||
- | |||
- | <code vbnet> | ||
- | Imports System.IO | ||
- | Imports System.Diagnostics | ||
- | Imports System | ||
- | Imports System.Xml | ||
- | Imports System.Xml.XPath | ||
- | |||
- | Public Class WINSCP | ||
- | |||
- | 'field for storing the command for opening connections. | ||
- | Private _connect As String = "" | ||
- | |||
- | Public Sub New_connection(ByVal host As String, ByVal username As String, _ | ||
- | ByVal password As String, Optional ByVal port As Integer = 22) | ||
- | |||
- | 'get the full path to the systems temp folder for storing | ||
- | 'the WinSCP.com and WinSCP.exe files in. | ||
- | Dim tempPath As String = Path.GetTempPath | ||
- | |||
- | 'check to see if the WinSCP files are in the temp path. | ||
- | 'if they are not then copy them from the resources. | ||
- | If File.Exists(tempPath & "WinSCP.com") = False Then | ||
- | File.WriteAllBytes(tempPath & "WinSCP.com", My.Resources.WinSCP) | ||
- | End If | ||
- | If File.Exists(tempPath & "WinSCP.exe") = False Then | ||
- | File.WriteAllBytes(tempPath & "WinSCP.exe", My.Resources.WinSCP1) | ||
- | End If | ||
- | |||
- | 'attempt to get the host key from the SSH server. This | ||
- | 'is required to make a connection to the server without storing it | ||
- | 'in the winscp.ini file. | ||
- | Dim hostKey = GetAndStoreFingerprint(host & ":" & port.ToString) | ||
- | |||
- | 'build connection string for opening ssh connections. | ||
- | 'this command needs to be run before any other commands. | ||
- | _connect = "open sftp://" & username & ":" & password _ | ||
- | & "@" & host & ":" & port.ToString _ | ||
- | & " -hostKey=" & """" & hostKey & """" | ||
- | |||
- | End Sub | ||
- | |||
- | Public Function ListFile() As Boolean | ||
- | |||
- | Try | ||
- | |||
- | 'create the required startinfo for WinSCP to run in background. | ||
- | Dim startInfo As New ProcessStartInfo | ||
- | startInfo.FileName = Path.GetTempPath & "WinSCP.com" | ||
- | startInfo.RedirectStandardInput = True | ||
- | startInfo.RedirectStandardOutput = True | ||
- | startInfo.UseShellExecute = False | ||
- | startInfo.CreateNoWindow = True | ||
- | startInfo.WindowStyle = ProcessWindowStyle.Hidden | ||
- | |||
- | 'create the process object. | ||
- | Dim process As New Process | ||
- | process.StartInfo = startInfo | ||
- | process.Start() | ||
- | |||
- | 'run the commands | ||
- | process.StandardInput.WriteLine(_connect) | ||
- | If CheckBox1.Checked = True Then | ||
- | process.StandardInput.WriteLine("option confirm off") | ||
- | End If | ||
- | |||
- | process.StandardInput.WriteLine("ls") | ||
- | |||
- | process.StandardInput.WriteLine("close") | ||
- | process.StandardInput.WriteLine("exit") | ||
- | process.StandardInput.Close() | ||
- | |||
- | 'get the response | ||
- | Dim response As String = process.StandardOutput.ReadToEnd | ||
- | process.WaitForExit() | ||
- | TextBox1.Text = response | ||
- | |||
- | TextBox1.SelectionLength = 0 | ||
- | |||
- | TextBox1.SelectionStart = TextBox1.Text.Length | ||
- | |||
- | TextBox1.ScrollToCaret() | ||
- | |||
- | |||
- | 'check the result. | ||
- | Dim exitCode = process.ExitCode | ||
- | If exitCode = 0 Then | ||
- | Return True | ||
- | Else | ||
- | 'find out why failed. | ||
- | End If | ||
- | |||
- | |||
- | Catch ex As Exception | ||
- | Return False | ||
- | End Try | ||
- | |||
- | 'failed because exitCode should be 0 | ||
- | Return False | ||
- | End Function | ||
- | Public Function UploadFile(ByVal localFilePath As String, _ | ||
- | ByVal remoteFilePath As String) As Boolean | ||
- | |||
- | 'wrap paths in quotes. | ||
- | localFilePath = """" & localFilePath & """" | ||
- | remoteFilePath = """" & remoteFilePath & """" | ||
- | |||
- | Try | ||
- | |||
- | 'create the required startinfo for WinSCP to run in background. | ||
- | Dim startInfo As New ProcessStartInfo | ||
- | startInfo.FileName = Path.GetTempPath & "WinSCP.com" | ||
- | startInfo.RedirectStandardInput = True | ||
- | startInfo.RedirectStandardOutput = True | ||
- | startInfo.UseShellExecute = False | ||
- | startInfo.CreateNoWindow = True | ||
- | startInfo.WindowStyle = ProcessWindowStyle.Hidden | ||
- | |||
- | 'create the process object. | ||
- | Dim process As New Process | ||
- | process.StartInfo = startInfo | ||
- | process.Start() | ||
- | |||
- | 'run the commands | ||
- | process.StandardInput.WriteLine(_connect) | ||
- | If CheckBox1.Checked = True Then | ||
- | process.StandardInput.WriteLine("option confirm off") | ||
- | End If | ||
- | process.StandardInput.WriteLine("put " & remoteFilePath & " " & localFilePath) | ||
- | process.StandardInput.WriteLine("close") | ||
- | process.StandardInput.WriteLine("exit") | ||
- | process.StandardInput.Close() | ||
- | |||
- | 'get the response | ||
- | Dim response As String = process.StandardOutput.ReadToEnd | ||
- | process.WaitForExit() | ||
- | TextBox1.Text = response | ||
- | |||
- | TextBox1.SelectionLength = 0 | ||
- | |||
- | TextBox1.SelectionStart = TextBox1.Text.Length | ||
- | |||
- | TextBox1.ScrollToCaret() | ||
- | |||
- | |||
- | 'check the result. | ||
- | Dim exitCode = process.ExitCode | ||
- | If exitCode = 0 Then | ||
- | Return True | ||
- | Else | ||
- | 'find out why failed. | ||
- | End If | ||
- | |||
- | |||
- | Catch ex As Exception | ||
- | Return False | ||
- | End Try | ||
- | |||
- | 'failed because exitCode should be 0 | ||
- | Return False | ||
- | End Function | ||
- | |||
- | Public Function DownloadFile(ByVal remoteFilePath As String, _ | ||
- | ByVal localFilePath As String) As Boolean | ||
- | |||
- | 'wrap paths in quotes. | ||
- | localFilePath = """" & localFilePath & """" | ||
- | remoteFilePath = """" & remoteFilePath & """" | ||
- | |||
- | Try | ||
- | |||
- | 'create the required startinfo for program to run in background. | ||
- | Dim startInfo As New ProcessStartInfo | ||
- | startInfo.FileName = Path.GetTempPath & "WinSCP.com" | ||
- | startInfo.RedirectStandardInput = True | ||
- | startInfo.RedirectStandardOutput = True | ||
- | startInfo.UseShellExecute = False | ||
- | startInfo.CreateNoWindow = True | ||
- | startInfo.WindowStyle = ProcessWindowStyle.Hidden | ||
- | |||
- | 'create the process object. | ||
- | Dim process As New Process | ||
- | process.StartInfo = startInfo | ||
- | process.Start() | ||
- | |||
- | 'run the commands | ||
- | process.StandardInput.WriteLine(_connect) | ||
- | process.StandardInput.WriteLine("get " & remoteFilePath & " " & localFilePath) | ||
- | process.StandardInput.WriteLine("close") | ||
- | process.StandardInput.WriteLine("exit") | ||
- | process.StandardInput.Close() | ||
- | |||
- | 'get the response | ||
- | Dim response As String = process.StandardOutput.ReadToEnd | ||
- | process.WaitForExit() | ||
- | TextBox1.Text = response | ||
- | |||
- | 'check the result. | ||
- | Dim exitCode = process.ExitCode | ||
- | If exitCode = 0 Then | ||
- | Return True | ||
- | Else | ||
- | 'find out why failed. | ||
- | End If | ||
- | |||
- | Catch ex As Exception | ||
- | Return False | ||
- | End Try | ||
- | |||
- | 'failed because exitCode should be 0 | ||
- | Return False | ||
- | |||
- | End Function | ||
- | |||
- | Private Function GetAndStoreFingerprint(ByRef host As String) As String | ||
- | Try | ||
- | |||
- | 'attempt a connect and load the fingerprint from initial connect. | ||
- | Dim startInfo As New ProcessStartInfo | ||
- | startInfo.FileName = Path.GetTempPath & "WinSCP.com" | ||
- | startInfo.RedirectStandardInput = True | ||
- | startInfo.RedirectStandardOutput = True | ||
- | startInfo.UseShellExecute = False | ||
- | startInfo.CreateNoWindow = True | ||
- | startInfo.WindowStyle = ProcessWindowStyle.Hidden | ||
- | |||
- | Dim process As New Process | ||
- | process.StartInfo = startInfo | ||
- | process.Start() | ||
- | process.StandardInput.WriteLine("open " & host) | ||
- | process.StandardInput.Close() | ||
- | process.WaitForExit() | ||
- | |||
- | 'read the first line from the output of the command. | ||
- | Dim response As String = process.StandardOutput.ReadLine | ||
- | Dim rsa As String = "" | ||
- | |||
- | 'loop through all lines of the output for the line containing | ||
- | 'the servers fingerprint (hostkey) | ||
- | While response <> Nothing | ||
- | If response.Contains("ssh-rsa") Then | ||
- | rsa = response | ||
- | Exit While | ||
- | End If | ||
- | response = process.StandardOutput.ReadLine | ||
- | End While | ||
- | |||
- | 'return the key | ||
- | Return rsa | ||
- | |||
- | Catch ex As Exception | ||
- | End Try | ||
- | |||
- | 'return not found | ||
- | Return "" | ||
- | |||
- | End Function | ||
- | |||
- | Private Sub brnUPLOAD_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles brnUPLOAD.Click | ||
- | New_connection(tbx_HOST.Text, tbx_USER.Text, tbx_PW.Text, tbx_PORT.Text) | ||
- | If UploadFile(tbx_UPLOAD_remoteFilePath.Text, tbx_UPLOAD_localFilePath.Text) Then | ||
- | MsgBox("UPLOAD OK!", ) | ||
- | Else | ||
- | MsgBox("UPLOAD FAIL!", ) | ||
- | End If | ||
- | End Sub | ||
- | |||
- | Private Sub btnDOWNLOAD_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDOWNLOAD.Click | ||
- | If System.IO.File.Exists(tbx_DOWNLOAD_localFilePath.Text) Then | ||
- | MsgBox("Waring: deleting file: " & tbx_DOWNLOAD_localFilePath.Text) | ||
- | File.Delete(tbx_DOWNLOAD_localFilePath.Text) | ||
- | End If | ||
- | If System.IO.File.Exists(tbx_DOWNLOAD_localFilePath.Text) Then | ||
- | MsgBox("Error: file not replaced!") | ||
- | Else | ||
- | New_connection(tbx_HOST.Text, tbx_USER.Text, tbx_PW.Text, tbx_PORT.Text) | ||
- | If DownloadFile(tbx_DOWNLOAD_remoteFilePath.Text, tbx_DOWNLOAD_localFilePath.Text) Then | ||
- | MsgBox("DOWNLOAD OK!", ) | ||
- | Else | ||
- | MsgBox("DOWNLOAD FAIL!", ) | ||
- | End If | ||
- | End If | ||
- | |||
- | End Sub | ||
- | |||
- | Private Sub WINSCP_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load | ||
- | |||
- | End Sub | ||
- | |||
- | Private Sub btnBROWSER1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBROWSER1.Click | ||
- | Dim Clicked As Integer = OpenFileDialog1.ShowDialog() | ||
- | If Clicked = Windows.Forms.DialogResult.Cancel Then | ||
- | MsgBox("Cancel Button Clicked") | ||
- | Else | ||
- | tbx_UPLOAD_localFilePath.Text = OpenFileDialog1.FileName | ||
- | End If | ||
- | End Sub | ||
- | |||
- | Private Sub btnBROWSER2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBROWSER2.Click | ||
- | Dim Clicked As Integer = SaveFileDialog1.ShowDialog() | ||
- | If Clicked = Windows.Forms.DialogResult.Cancel Then | ||
- | MsgBox("Cancel Button Clicked") | ||
- | Else | ||
- | tbx_DOWNLOAD_localFilePath.Text = SaveFileDialog1.FileName | ||
- | If System.IO.File.Exists(tbx_DOWNLOAD_localFilePath.Text) Then | ||
- | MsgBox("Waring: file exists!") | ||
- | End If | ||
- | End If | ||
- | End Sub | ||
- | |||
- | Private Sub btnEXIT_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEXIT.Click | ||
- | End | ||
- | End Sub | ||
- | |||
- | Private Sub btnLISTDIR_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLISTDIR.Click | ||
- | New_connection(tbx_HOST.Text, tbx_USER.Text, tbx_PW.Text, tbx_PORT.Text) | ||
- | ListFile() | ||
- | End Sub | ||
- | End Class | ||
- | |||
- | </code> | ||
- | |||
- | <trailer> | ||
- | ===== Further Reading ===== | ||
- | |||
- | |||
- | |||
- | |||
- | |||
- | * Guide to [[guide_automation|scripting/automation]]; | ||
- | * [[library|WinSCP .NET assembly]]; | ||
- | * [[library_powershell|Using WinSCP .NET Assembly from PowerShell]]. | ||
- | </trailer> | ||
- | |||
- | <nosplit> | ||
===== Other Examples ===== | ===== Other Examples ===== | ||
* Guide to [[guide_automation|scripting/automation]]; | * Guide to [[guide_automation|scripting/automation]]; | ||
* Guide to [[guide_automation_advanced|advanced scripting]]; | * Guide to [[guide_automation_advanced|advanced scripting]]; | ||
- | * See [[library_examples|WinSCP .NET assembly examples]] for advanced tasks. | + | * See [[library_examples|*]] for advanced tasks. |
- | </nosplit> | + | |