// // Class: sftp // Current CLR: 4.0.30319.34209 // System: Microsoft Visual Studio 10.0 // Author: dani // Created: 4/28/2015 8:53:41 AM // // Copyright (c) 2015 Informatikbüro Daniel Schick. All rights reserved. using System; using System.Diagnostics; using System.IO; using System.Xml; using System.Xml.XPath; using System.Collections.Generic; using log4net; namespace bsmd.dakosy { /// /// Hilfsklasse zur Kommunikation via SFTP. Wir machen es uns hier leicht und verwenden das beliebte WINSCP im /// Process-Modus. (http://winscp.net/eng/docs/guide_dotnet) /// public static class SFtp { private static readonly ILog _log = LogManager.GetLogger(typeof(SFtp)); public enum Direction { INCOMING, OUTGOING } public static void Put(string filename, string targetDir) { Process winscp = new Process(); winscp.StartInfo.FileName = Properties.Settings.Default.WINSCPFullPath; winscp.StartInfo.Arguments = "/xmllog=\"" + Properties.Settings.Default.SFTPLog + "\""; winscp.StartInfo.UseShellExecute = false; winscp.StartInfo.RedirectStandardInput = true; winscp.StartInfo.RedirectStandardOutput = true; winscp.StartInfo.CreateNoWindow = true; winscp.Start(); string dotlessFilename = filename.Substring(1); // Feed in the scripting commands winscp.StandardInput.WriteLine("option batch abort"); winscp.StandardInput.WriteLine("option confirm off"); winscp.StandardInput.WriteLine("open " + Properties.Settings.Default.SFTPSessionName); winscp.StandardInput.WriteLine("lcd " + Properties.Settings.Default.SFTPOutDir); // winscp.StandardInput.WriteLine("ls"); if (targetDir != null) winscp.StandardInput.WriteLine("cd " + targetDir); winscp.StandardInput.WriteLine("put " + filename); winscp.StandardInput.WriteLine(string.Format("mv {0} {1}", filename, dotlessFilename)); winscp.StandardInput.Close(); // Collect all output string output = winscp.StandardOutput.ReadToEnd(); _log.Info(output); output = winscp.StandardError.ReadToEnd(); _log.Warn(output); // 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) XPathDocument log = new XPathDocument(Properties.Settings.Default.SFTPLog); XmlNamespaceManager ns = new XmlNamespaceManager(new NameTable()); ns.AddNamespace("w", @"http://winscp.net/schema/session/1.0"); XPathNavigator nav = log.CreateNavigator(); // Success (0) or error? if (winscp.ExitCode != 0) { Console.WriteLine("Error occured"); // See if there are any messages associated with the error foreach (XPathNavigator message in nav.Select("//w:message", ns)) { Console.WriteLine(message.Value); } } else { // It can be worth looking for directory listing even in case of // error as possibly only upload may fail XPathNodeIterator files = nav.Select("//w:file", ns); Console.WriteLine(string.Format("There are {0} files and subdirectories:", files.Count)); foreach (XPathNavigator file in files) { Console.WriteLine(file.SelectSingleNode("w:filename/@value", ns).Value); } } */ } public static void TransmitAll(string remoteDir, string localDir, Direction direction, string sessionName) { Process winscp = new Process(); winscp.StartInfo.FileName = Properties.Settings.Default.WINSCPFullPath; winscp.StartInfo.Arguments = "/xmllog=\"" + Properties.Settings.Default.SFTPLog + "\""; winscp.StartInfo.UseShellExecute = false; winscp.StartInfo.RedirectStandardInput = true; winscp.StartInfo.RedirectStandardOutput = true; winscp.StartInfo.RedirectStandardError = true; winscp.StartInfo.CreateNoWindow = true; winscp.Start(); // Feed in the scripting commands winscp.StandardInput.WriteLine("option batch abort"); winscp.StandardInput.WriteLine("option confirm off"); winscp.StandardInput.WriteLine("open " + sessionName); winscp.StandardInput.WriteLine("lcd " + localDir); // winscp.StandardInput.WriteLine("ls"); if (remoteDir != null) winscp.StandardInput.WriteLine("cd " + remoteDir); if(direction == Direction.INCOMING) winscp.StandardInput.WriteLine("get *.xml"); if(direction == Direction.OUTGOING) winscp.StandardInput.WriteLine("put *.xml"); // move back up since winscp session remembers the last folder winscp.StandardInput.WriteLine("cd .."); winscp.StandardInput.WriteLine("cd .."); winscp.StandardInput.Close(); // Collect all output string output = winscp.StandardOutput.ReadToEnd(); _log.Info(output); output = winscp.StandardError.ReadToEnd(); _log.Warn(output); // Wait until WinSCP finishes winscp.WaitForExit(); } public static void RemoveProcessedFile(string remoteDir, string filename, string sessionName) { Process winscp = new Process(); winscp.StartInfo.FileName = Properties.Settings.Default.WINSCPFullPath; winscp.StartInfo.Arguments = "/xmllog=\"" + Properties.Settings.Default.SFTPLog + "\""; winscp.StartInfo.UseShellExecute = false; winscp.StartInfo.RedirectStandardInput = true; winscp.StartInfo.RedirectStandardOutput = true; winscp.StartInfo.RedirectStandardError = true; winscp.StartInfo.CreateNoWindow = true; winscp.Start(); // Feed in the scripting commands winscp.StandardInput.WriteLine("option batch abort"); winscp.StandardInput.WriteLine("option confirm off"); winscp.StandardInput.WriteLine("open " + sessionName); // winscp.StandardInput.WriteLine("ls"); if (remoteDir != null) winscp.StandardInput.WriteLine("cd " + remoteDir); winscp.StandardInput.WriteLine("rm " + filename); if (remoteDir != null) { // move back up since winscp session remembers the last folder winscp.StandardInput.WriteLine("cd .."); winscp.StandardInput.WriteLine("cd .."); } winscp.StandardInput.Close(); // Collect all output string output = winscp.StandardOutput.ReadToEnd(); _log.Info(output); output = winscp.StandardError.ReadToEnd(); _log.Warn(output); // Wait until WinSCP finishes winscp.WaitForExit(); } } }