262 lines
11 KiB
C#
262 lines
11 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;
|
|
using WinSCP;
|
|
using System;
|
|
using System.Linq;
|
|
using System.Collections.Generic;
|
|
|
|
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) => { if (!e.Data.IsNullOrEmpty()) _log.Debug(e.Data); };
|
|
//winscp.ErrorDataReceived += (s, e) => { if (!e.Data.IsNullOrEmpty()) _log.Warn(e.Data); };
|
|
winscp.Start();
|
|
//winscp.BeginErrorReadLine();
|
|
//winscp.BeginOutputReadLine();
|
|
|
|
return winscp;
|
|
}
|
|
|
|
public static void TransmitAllFiles(string remoteDir, string localDir, string host, string user, string keyPath, string hostkey)
|
|
{
|
|
try
|
|
{
|
|
SessionOptions sessionOptions = new SessionOptions();
|
|
|
|
sessionOptions.Protocol = Protocol.Sftp;
|
|
sessionOptions.HostName = host;
|
|
sessionOptions.UserName = user;
|
|
sessionOptions.SshPrivateKeyPath = keyPath;
|
|
sessionOptions.SshHostKeyFingerprint = hostkey;
|
|
|
|
using (Session session = new Session())
|
|
{
|
|
session.Open(sessionOptions);
|
|
|
|
// upload
|
|
TransferOptions transferOptions = new TransferOptions();
|
|
transferOptions.TransferMode = TransferMode.Binary;
|
|
|
|
TransferOperationResult transferResult = session.PutFiles(localDir, remoteDir, false, transferOptions);
|
|
|
|
transferResult.Check();
|
|
|
|
foreach(TransferEventArgs tea in transferResult.Transfers.Cast<TransferEventArgs>())
|
|
{
|
|
_log.InfoFormat("Upload of {0} successful", tea.FileName);
|
|
}
|
|
}
|
|
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
_log.Error(e);
|
|
}
|
|
}
|
|
|
|
public static void ReceiveAllFiles(string remoteDir, string localDir, string host, string user, string keyPath, string hostkey)
|
|
{
|
|
try
|
|
{
|
|
SessionOptions sessionOptions = new SessionOptions();
|
|
|
|
sessionOptions.Protocol = Protocol.Sftp;
|
|
sessionOptions.HostName = host;
|
|
sessionOptions.UserName = user;
|
|
sessionOptions.SshPrivateKeyPath = keyPath;
|
|
sessionOptions.SshHostKeyFingerprint = hostkey;
|
|
|
|
using (Session session = new Session())
|
|
{
|
|
session.Open(sessionOptions);
|
|
|
|
// upload
|
|
TransferOptions transferOptions = new TransferOptions();
|
|
transferOptions.TransferMode = TransferMode.Binary;
|
|
|
|
TransferOperationResult transferResult = session.GetFiles(remoteDir, localDir, false, transferOptions);
|
|
transferResult.Check();
|
|
|
|
foreach (TransferEventArgs tea in transferResult.Transfers.Cast<TransferEventArgs>())
|
|
{
|
|
_log.InfoFormat("Download of {0} successful", tea.FileName);
|
|
}
|
|
|
|
if (transferResult.Transfers.Count > 0)
|
|
{
|
|
RemovalOperationResult removalResult = session.RemoveFiles(remoteDir + "/*.*");
|
|
if ((removalResult.IsSuccess) && (removalResult.Removals.Count > 0))
|
|
{
|
|
_log.InfoFormat("Removed {0} downloaded file(s) on remote host", removalResult.Removals.Count);
|
|
}
|
|
if (!removalResult.IsSuccess)
|
|
{
|
|
_log.WarnFormat("RemoveFiles was not successful, {0} failures", removalResult.Failures.Count);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_log.Error(e);
|
|
}
|
|
}
|
|
|
|
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();
|
|
|
|
// 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();
|
|
if(winscp.ExitCode != 0)
|
|
{
|
|
_log.Warn("WinSCP exited with an error");
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|
|
}
|