簡體   English   中英

VB.NET 流程標准 Output 重定向在 OpenSSH SCP 上不起作用

[英]VB.NET Process Standart Output redirect does not work on OpenSSH SCP

當我將 OpenSSH SCP 可執行文件與 System.Diagnostics.Process 一起使用時,Standart Output 不會被重定向

我在托管 Windows PC 上工作,必須將文件發送到僅受密碼保護的 SFTP 服務器。 由於我無法安裝任何其他程序或庫,我只能使用沒有密碼參數的 Windows 默認 OpenSSH 客戶端。 這些 PC 在無法訪問 inte.net 的公司防火牆后面。 但這就是我堅持的。

我的方法是使用System.Diagnostics.Process啟動 SCP 命令,收聽密碼提示,然后使用System.IO.StreamWriter發送它。

雖然這似乎確實適用於我收聽ipconfig並隨后發送輸入的測試用例,但我正在努力處理scpsftp和其他程序,因為 DefaultOutput 似乎沒有被重定向。

簡化代碼:

Private Dim Output = ""
Public Function CreateAndStartProcess(FileName As String, Optional Arguments As String = "")
  Dim targetProcess As New Process()
  targetProcess.StartInfo.FileName = FileName
  targetProcess.StartInfo.Arguments = Arguments
  targetProcess.StartInfo.UseShellExecute = False
  targetProcess.StartInfo.RedirectStandardInput = True
  targetProcess.StartInfo.RedirectStandardOutput = True
  targetProcess.StartInfo.CreateNoWindow = False
  
  targetProcess.Start()
  AddHandler targetProcess.OutputDataReceived, OutputHandler

  return targetProcess 
End Function

Sub OutputHandler(sender, e, process) //never gets called
  If String.IsNullOrEmpty(e.Data) Then
    Exit Sub
  End If

  Output = Output & Environment.NewLine & e.Data
End Sub

Dim targetProcess = CreateAndStartProcess("C:\\Windows\\Sysnative\\OpenSSH\\scp.exe", "C:\test.txt user@host:/test")
System.Threading.Thread.Sleep(2000) //just for simplification
Dim SW As System.IO.StreamWriter = targetProcess.StandardInput
SW.WriteLine("password")

 

當我將斷點放入OutputHandler時,它永遠不會被調用。 執行后Output字符串為空

有什么我想念的嗎? 使用 ipconfig 時它工作得很好。

SCP執行截圖

不確定你是如何編譯的。 您 output 處理程序的方法簽名是錯誤的...

根據您的 VB 代碼,您可能正在嘗試從https://learn.microsoft.com/en-us/do.net/api/system.diagnostics.process.outputdatareceived?view.net-重新創建 C# 示例6.0

我沒有您要連接的任何主機,因此當它為我觸發時 OutputHandler 是一個空字符串。 但是,我在下面的代碼中添加的 ErrorHandler 從進程中獲得了 output。

我建議閱讀上面鏈接的文檔。 我用來修改您的代碼的示例代碼中的幾個要點:

  1. 您必須調用 process.BeginOutputReadLine() 才能觸發 OutputHandler 方法。

  2. 您需要調用 process.WaitForExit() 或設置 process.EnableRaiseEvents = True 並添加一個 Exit 事件處理程序,否則您將永遠不知道進程何時結束。

  3. 僅當將換行符(CR、LF 或 CR+LF)發送到 StandardOutput stream 時,才會調用 output 事件處理程序。可能是該行顯示“密碼:”正在等待該行的輸入,因此已發送換行符yet,所以 Password: 還沒有被發送到我們的 OutputHandler。 因此,您可能需要直接使用 StandardOutput stream 來讀取而不是使用 OutputHandler 方法,而無需等待換行符。

  4. 您可能想要添加 ErrorHandler 方法(或類似方法),以防您收到 StandardError stream 而不是 output stream 的錯誤消息。

     Sub Main() Dim targetProcess = CreateAndStartProcess("C:\\Windows\\Sysnative\\OpenSSH\\scp.exe", "C:\test.txt user@host:/test") targetProcess.BeginOutputReadLine() targetProcess.BeginErrorReadLine() Dim SW As System.IO.StreamWriter = targetProcess.StandardInput System.Threading.Thread.Sleep(2000) '//just For simplification SW.WriteLine("password") targetProcess.WaitForExit() If Not String.IsNullOrEmpty(Output) Then Console.WriteLine(Output) If Not String.IsNullOrEmpty(ErrorOutput) Then Console.WriteLine(ErrorOutput) targetProcess.WaitForExit() targetProcess.Close() Console.WriteLine(Environment.NewLine & Environment.NewLine & "Press any key to exit.") Console.ReadLine() End Sub Private Output As String = "" Private ErrorOutput As String = "" Public Function CreateAndStartProcess(FileName As String, Optional Arguments As String = "") As Process Dim targetProcess As New Process() targetProcess.StartInfo.FileName = FileName targetProcess.StartInfo.Arguments = Arguments targetProcess.StartInfo.UseShellExecute = False targetProcess.StartInfo.RedirectStandardInput = True targetProcess.StartInfo.RedirectStandardOutput = True targetProcess.StartInfo.RedirectStandardError = True targetProcess.StartInfo.CreateNoWindow = False AddHandler targetProcess.ErrorDataReceived, AddressOf ErrorHandler AddHandler targetProcess.OutputDataReceived, AddressOf OutputHandler targetProcess.Start() Return targetProcess End Function Sub OutputHandler(sender As Object, e As DataReceivedEventArgs) '//never gets called If String.IsNullOrEmpty(e.Data) Then Exit Sub End If Output = Output & Environment.NewLine & e.Data End Sub Sub ErrorHandler(sender As Object, e As DataReceivedEventArgs) '//never gets called If String.IsNullOrEmpty(e.Data) Then Exit Sub End If ErrorOutput = ErrorOutput & Environment.NewLine & e.Data End Sub

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM