2014-10-06 68 views
1

我需要通過C#代碼執行SFTP進程。我正在使用Windows服務。以下是我正在使用的代碼。Windows服務中的SFTP

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

我假設你正在運行的程序(「外部批次」)永遠不會結束。

當您重定向流程輸出時,您必須正在讀取它。重定向輸出有一個有限的緩衝區。填充時,子進程在下一次嘗試產生輸出時停止,並等待父進程從緩衝區讀取一些數據。如果你從不這樣做,並且你等待進程退出,就會發生死鎖。

請參閱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:廣告:5C:是:3B:C5:72:78
如果信任此主機,輸入「y」將密鑰添加到
PuTTY的緩存並進行連接。
如果您只想繼續連接一次,而沒有
將密鑰添加到緩存中,請輸入「n」。
如果您不信任此主機,請按回車鍵以放棄
連接。
將密鑰存儲在緩存中? (y/n)

您應該使用-hostkey switch明確指定可信主機密鑰的指紋。

或者使用一些本地SFTP .NET庫。

附註:命名psftp腳本.bat令人困惑。它不是(Windows)批處理文件。

+0

我已經更新我的答案。 – 2014-10-07 07:38:45

+0

將p.WaitForExit()更改爲p.StandardOutput.ReadToEnd()不起作用。同樣的結果:( – user3859666 2014-10-07 14:07:51

+0

好的,比它很可能是由於某些提示,請參閱我的編輯 – 2014-10-07 15:33:44

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); 
    //} 
} 
+0

sessionOptions具有參數Password,SshHostKeyFingerprint。如何得到這個。我只有私鑰才能訪問服務器(即)我有Servername,用戶名和私鑰來訪問服務器。請幫助.. – user3859666 2014-10-08 04:55:01

+0

獲取您的服務器SshHostKeyFingerprint:只需運行winScp客戶端「windows應用程序」,添加用戶名/密碼,應用程序就會顯示該密鑰,或者您可以從命令菜單 - >服務器/協議信息打開WinScp應用程序 - >彈出窗口包含該鍵。 – 2014-10-15 06:36:55