Differences
This shows you the differences between the selected revisions of the page.
| 2015-08-25 | 2015-08-25 | ||
| no summary (martin) (hidden) | Restored revision 1435092494. Undoing revision 1440530835. (martin) (hidden) | ||
| Line 6: | Line 6: | ||
| <code powershell> | <code powershell> | ||
| param ( | param ( | ||
| - | $session = "sftp://user:mypassword;fingerprint=ssh-rsa-xx-xx-xx@example.com/", | + | $localPath = "c:\downloaded\", |
| - | $remotePath = "/path", | + | $remotePath = "/home/user/" |
| - | $outFile = "listing.csv" | + | |
| ) | ) | ||
| Line 18: | Line 17: | ||
| # Setup session options | # Setup session options | ||
| $sessionOptions = New-Object WinSCP.SessionOptions | $sessionOptions = New-Object WinSCP.SessionOptions | ||
| - | $sessionOptions.ParseUrl($session) | + | $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 | try | ||
| { | { | ||
| # Connect | # Connect | ||
| - | Write-Host "Connecting..." | ||
| - | $session = New-Object WinSCP.Session | ||
| $session.Open($sessionOptions) | $session.Open($sessionOptions) | ||
| + | |||
| + | # Get list of files in the directory | ||
| + | $directoryInfo = $session.ListDirectory($remotePath) | ||
| - | # Retrieve listing | + | # Select the most recent file |
| - | Write-Host "Listing..." | + | $latest = |
| - | ·······$directory = $session.ListDirectory($remotePath) | + | ···········$directoryInfo.Files | |
| + | ············Where-Object { -Not $_.IsDirectory } | | ||
| + | ············Sort-Object LastWriteTime -Descending | | ||
| + | ············Select-Object -First 1 | ||
| - | # Remove output file if it exists | + | # Any file at all? |
| - | if (Test-Path $outFile) | + | if ($latest -eq $Null) |
| { | { | ||
| - | Remove-Item $outFile | + | Write-Host "No file found" |
| - | ········} | + | ···········exit 1 |
| - | + | ||
| - | # Generate a custom listing for ach file in the output file | + | |
| - | # Using UTF-16 (Unicode) encoding that Microsoft Excel likes. | + | |
| - | foreach ($fileInfo in $directory.Files) | + | |
| - | { | + | |
| - | ("`"{0}`"`t{1}`t`"{2}`"" -f $fileInfo.Name, $fileInfo.Length, $fileInfo.LastWriteTime) | Out-File -Append $outFile -Encoding Unicode | + | |
| } | } | ||
| - | Write-Host "Done" | + | # Download the selected file |
| + | $session.GetFiles($session.EscapeFileMask($remotePath + $latest.Name), $localPath).Check() | ||
| } | } | ||
| finally | finally | ||
| Line 62: | Line 66: | ||
| ===== [[scripting]] Using WinSCP Scripting ===== | ===== [[scripting]] Using WinSCP Scripting ===== | ||
| - | You may have WinSCP produce [[logging_xml|XML log]] with the listing and convert it to your custom format [[logging_xml#xslt|using XSLT]]: | + | You may use following [[guide_automation_advanced#wsh|Windows script host JScript code]] (''example.js''): |
| - | Use the following Windows batch file (''listing.bat''): | + | <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 batch> | <code batch> | ||
| - | @echo off | + | cscript /nologo example.js |
| - | set XMLLOG=script.xml | + | |
| - | winscp.com /log=script.log /xmllog=%XMLLOG% /command ^ | + | |
| - | "open mysession" ^ | + | |
| - | "ls /path" ^ | + | |
| - | "exit" | + | |
| - | if %ERRORLEVEL% == 0 msxsl.exe %XMLLOG% listing.xsl > listing_script.csv | + | |
| </code> | </code> | ||
| - | Where the ''listing.xsl'' may look like: | + | ===== Alternatives ===== |
| - | <code xml> | + | Some of following alternatives can be easier to implement or actually even more appropriate for your specific task: |
| - | <?xml version="1.0" encoding="UTF-8"?> | + | |
| - | <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:winscp="http://winscp.net/schema/session/1.0"> | + | ··* Synchronizing a remote directory to a local directory (using ''[[scriptcommand_synchronize|synchronize local]]'' in scripting or ''[[library_session_synchronizedirectories|Session.SynchronizeDirectories(SynchronizationMode.Local, ...)]]'' in .NET assembly); |
| - | ···<!-- Using UTF-16 encoding that Microsoft Excel likes --> | + | * Downloading all files created in the last 24 hours (using [[file_mask|file mask]] ''*>=1D''; e.g. ''%%get -filemask="*>=1D" /home/user/*%%'', or an equivalent in .NET assembly). |
| - | ···<xsl:output method="text" encoding="UTF-16"/> | + | ·* Downloading all files created today (using ''[[scripting#timestamp|%TIMESTAMP%]]039;' syntax to format [[file_mask|file mask]] with today's time constraint, e.g. '039;%%get -filemask="*>=%TIMESTAMP#yyyy-mm-dd%" /home/user/*%%'', or an equivalent in .NET assembly). |
| - | ····<xsl:strip-space elements="*"/> | + | |
| - | ···<xsl:template match='winscp:ls[winscp:result[@success="true"]]/winscp:files/winscp:file'> | + | |
| - | ········<xsl:text>"</xsl:text> | + | |
| - | ········<xsl:value-of select="winscp:filename/@value"/> | + | |
| - | <xsl:text>&quot;&#9;</xsl:text> | + | |
| - | ········<xsl:value-of select="winscp:size/@value"/> | + | |
| - | ········<xsl:text>&#9;&quot;</xsl:text> | + | |
| - | <xsl:value-of select="winscp:modification/@value"/> | + | |
| - | ·········<xsl:text>&quot;
</xsl:text> | + | |
| - | </xsl:template> | + | |
| - | </xsl:stylesheet> | + | |
| - | </code> | + | |
| ===== Further Reading ===== | ===== Further Reading ===== | ||
| Line 100: | Line 194: | ||
| * Guide to [[guide_automation|scripting/automation]]; | * Guide to [[guide_automation|scripting/automation]]; | ||
| * [[library|WinSCP .NET assembly]]; | * [[library|WinSCP .NET assembly]]; | ||
| - | * [[library_powershell|Using WinSCP .NET Assembly from PowerShell]]; | + | * [[library_powershell|Using WinSCP .NET Assembly from PowerShell]]. |
| - | * [[logging_xml|XML logging]]. | + | |