我需要通过C#代码执行SFTP过程。我正在使用Windows服务。以下是我正在使用的代码。
WebCash.writeToFile(WebCash.outerbatchpath, command);
WebCash.writeToFile(WebCash.outerbatchpath, "exit");
ProcessStartInfo psi = new ProcessStartInfo("cmd.exe", "/c "+WebCash.outerbatchpath);
psi.RedirectStandardOutput = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardError = true;
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.WindowStyle = ProcessWindowStyle.Hidden;
Process p = new Process();
p.StartInfo = psi;
p.Start();
p.WaitForExit();
psi = null;
WebCash.writeToFile(WebCash.GetErrorLog(), DateTime.Now.ToString() + "- Running SFTP end - " + p.ExitCode);
return p.ExitCode;
在尝试调试上述代码时,调试器无法传递p.WaitforExit()
函数(即)服务未在p.WaitforExit()
之后执行。
我在我的外部补丁中运行以下命令(SFTP)。
psftp -b D:\Source_Data\SFTP\innerbatch.bat -l username -i D:\privatekey.ppk @servername
内部批处理包含以下命令
put D:\Source_Data\SFTP\FileToTransfer.xml
我还需要退出代码来获取错误。请帮助。
答案 0 :(得分:0)
我认为你正在运行的程序("外部批处理")永远不会完成。
重定向过程输出时,必须阅读它。重定向输出的缓冲区有限。当它填充时,子进程在下一次产生输出的尝试时停止,并等待父进程从缓冲区中读取一些数据。正如你从未做过的那样,等待进程退出,就会发生死锁。
请参阅MSDN了解ProcessStartInfo.RedirectStandardOutput
property :
同步读取操作在从StandardOutput流读取调用者和写入该流的子进程之间引入依赖关系。这些依赖项可能会导致死锁条件。当调用者从子进程的重定向流中读取时,它依赖于子进程。调用者等待读操作,直到子进程写入流或关闭流。当子进程写入足够的数据来填充其重定向流时,它依赖于父进程。子进程等待下一个写操作,直到父进程从完整流中读取或关闭流。当调用者和子进程等待彼此完成操作时,将导致死锁条件,并且两者都不能继续。您可以通过评估调用者和子进程之间的依赖关系来避免死锁。
在这种情况下,始终建议使用p.StandardOutput.ReadToEnd()
代替p.WaitForExit()
。两个命令都等待进程退出,但第一个命令确保不会发生死锁。
另一方面,由于您只传输一个文件,我不确定psftp
输出实际上是否足以填充缓冲区。如果上述建议无效,我建议您直接运行psftp.exe
来简化代码,删除cmd.exe
和外部批处理文件中不必要的图层。
编辑:如果您从未在服务帐户下运行psftp
,则可能会提示您确认主机密钥。
服务器的主机密钥未缓存在注册表中。你
无法保证服务器是您的计算机 认为是。
服务器的dss密钥指纹是:
ssh-dss 1024 0b:77:8b:68:f4:45:b1:3c:87:ad:5c:be:3b:c5:72:78
如果您信任此主机,请输入" y"将密钥添加到
PuTTY的缓存并进行连接。
如果你想只进行一次连接,没有
将密钥添加到缓存中,输入" n"。
如果您不信任此主机,请按Return键放弃 连接。
将密钥存储在缓存中? (Y / N)
您应该使用-hostkey
switch明确指定可信主机密钥的指纹。
或者使用一些本机SFTP .NET库。
附注:命名psftp
脚本.bat
令人困惑。它不是(Windows)批处理文件。
答案 1 :(得分:0)
使用WinSCP。
对于SshHostKeyFingerprint
,请参阅Server and Protocol Information Dialog
// Setup session options
SessionOptions sessionOptions = new SessionOptions
{
Protocol = Protocol.Sftp,
HostName = "000.00.00.000",
UserName = "xxxxxx",
Password = "xxxxxx",
PortNumber= 22,
SshHostKeyFingerprint = "ssh-rsa 2048 xxxxxxxxxxxxxxx"
};
using (Session session = new Session())
{
// Connect
session.Open(sessionOptions);
// Upload files
//TransferOptions transferOptions = new TransferOptions();
//transferOptions.TransferMode = TransferMode.Binary;
//TransferOperationResult transferResult;
var results = session.ListDirectory("/path");
foreach (RemoteFileInfo item in results.Files)
{
Console.WriteLine(item.Name);
}
// Throw on any error
//transferResult.Check();
// Print results
//foreach (TransferEventArgs transfer in transferResult.Transfers)
//{
// Console.WriteLine("Upload of {0} succeeded", transfer.FileName);
//}
}