stattdessen wird ein open command gesendet. Gleichzeitig wird die Ausgabe nicht mehr zum Ende gelesen sondern per Events abgefragt. Die Hoffnung ist hier, dass der Prozess nicht mehr auf dem ReadToEnd() blockiert, wobei das nie bestätigt werden konnte.
162 lines
6.6 KiB
C#
162 lines
6.6 KiB
C#
//
|
|
// 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 log4net;
|
|
using System.Diagnostics;
|
|
using bsmd.database;
|
|
|
|
namespace bsmd.dakosy
|
|
{
|
|
/// <summary>
|
|
/// 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)
|
|
/// </summary>
|
|
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.Debug(output);
|
|
output = winscp.StandardError.ReadToEnd();
|
|
if (!output.Trim().IsNullOrEmpty())
|
|
_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);
|
|
}
|
|
}
|
|
*/
|
|
|
|
}
|
|
|
|
private static Process StartWinSCPProcess()
|
|
{
|
|
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.EnableRaisingEvents = true;
|
|
winscp.OutputDataReceived += (s, e) => _log.Debug(e.Data);
|
|
winscp.ErrorDataReceived += (s, e) => _log.Warn(e.Data);
|
|
winscp.Start();
|
|
winscp.BeginErrorReadLine();
|
|
winscp.BeginOutputReadLine();
|
|
|
|
return winscp;
|
|
}
|
|
|
|
public static void TransmitAll(string remoteDir, string localDir, Direction direction, string openCommand)
|
|
{
|
|
Process winscp = StartWinSCPProcess();
|
|
|
|
// Feed in the scripting commands
|
|
winscp.StandardInput.WriteLine("option batch abort");
|
|
winscp.StandardInput.WriteLine("option confirm off");
|
|
winscp.StandardInput.WriteLine(openCommand);
|
|
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");
|
|
winscp.StandardInput.Close();
|
|
|
|
// Wait until WinSCP finishes
|
|
winscp.WaitForExit();
|
|
}
|
|
|
|
public static void RemoveProcessedFile(string remoteDir, string filename, string openCommand)
|
|
{
|
|
Process winscp = StartWinSCPProcess();
|
|
|
|
// Feed in the scripting commands
|
|
winscp.StandardInput.WriteLine("option batch abort");
|
|
winscp.StandardInput.WriteLine("option confirm off");
|
|
winscp.StandardInput.WriteLine(openCommand);
|
|
|
|
// winscp.StandardInput.WriteLine("ls");
|
|
if (remoteDir != null)
|
|
winscp.StandardInput.WriteLine("cd " + remoteDir);
|
|
winscp.StandardInput.WriteLine("rm " + filename);
|
|
winscp.StandardInput.Close();
|
|
|
|
// Wait until WinSCP finishes
|
|
winscp.WaitForExit();
|
|
}
|
|
}
|
|
}
|