2012-09-12 15 views
1

你好我已經找到了一個用c#編寫的很棒的類,我想在VB.NET項目中使用它。從c#到vb.net的代碼轉換,包括事件處理程序

我發現它在這個線程: C# : Redirect console application output : How to flush the output?

的C#類 看起來是這樣的:

using System; 
using System.Collections; 
using System.IO; 
using System.Text; 
using System.Threading; 

namespace System.Diagnostics 
{ 
    internal delegate void UserCallBack(string data); 
    public delegate void DataReceivedEventHandler(object sender, DataReceivedEventArgs e); 

    public class FixedProcess : Process 
    { 
     internal AsyncStreamReader output; 
     internal AsyncStreamReader error; 
     public event DataReceivedEventHandler OutputDataReceived; 
     public event DataReceivedEventHandler ErrorDataReceived; 

     public new void BeginOutputReadLine() 
     { 
      Stream baseStream = StandardOutput.BaseStream; 
      this.output = new AsyncStreamReader(this, baseStream, new UserCallBack(this.FixedOutputReadNotifyUser), StandardOutput.CurrentEncoding); 
      this.output.BeginReadLine(); 
     } 

     public void BeginErrorReadLine() 
     { 
      Stream baseStream = StandardError.BaseStream; 
      this.error = new AsyncStreamReader(this, baseStream, new UserCallBack(this.FixedErrorReadNotifyUser), StandardError.CurrentEncoding); 
      this.error.BeginReadLine(); 
     } 

     internal void FixedOutputReadNotifyUser(string data) 
     { 
      DataReceivedEventHandler outputDataReceived = this.OutputDataReceived; 
      if (outputDataReceived != null) 
      { 
       DataReceivedEventArgs dataReceivedEventArgs = new DataReceivedEventArgs(data); 
       if (this.SynchronizingObject != null && this.SynchronizingObject.InvokeRequired) 
       { 
        this.SynchronizingObject.Invoke(outputDataReceived, new object[] 
        { 
         this, 
         dataReceivedEventArgs 
        }); 
        return; 
       } 
       outputDataReceived(this, dataReceivedEventArgs); 
      } 
     } 

     internal void FixedErrorReadNotifyUser(string data) 
     { 
      DataReceivedEventHandler errorDataReceived = this.ErrorDataReceived; 
      if (errorDataReceived != null) 
      { 
       DataReceivedEventArgs dataReceivedEventArgs = new DataReceivedEventArgs(data); 
       if (this.SynchronizingObject != null && this.SynchronizingObject.InvokeRequired) 
       { 
        this.SynchronizingObject.Invoke(errorDataReceived, new object[] 
        { 
         this, 
         dataReceivedEventArgs 
        }); 
        return; 
       } 
       errorDataReceived(this, dataReceivedEventArgs); 
      } 
     } 
    } 

    internal class AsyncStreamReader : IDisposable 
    { 
     internal const int DefaultBufferSize = 1024; 
     private const int MinBufferSize = 128; 
     private Stream stream; 
     private Encoding encoding; 
     private Decoder decoder; 
     private byte[] byteBuffer; 
     private char[] charBuffer; 
     private int _maxCharsPerBuffer; 
     private Process process; 
     private UserCallBack userCallBack; 
     private bool cancelOperation; 
     private ManualResetEvent eofEvent; 
     private Queue messageQueue; 
     private StringBuilder sb; 
     private bool bLastCarriageReturn; 
     public virtual Encoding CurrentEncoding 
     { 
      get 
      { 
       return this.encoding; 
      } 
     } 
     public virtual Stream BaseStream 
     { 
      get 
      { 
       return this.stream; 
      } 
     } 
     internal AsyncStreamReader(Process process, Stream stream, UserCallBack callback, Encoding encoding) 
      : this(process, stream, callback, encoding, 1024) 
     { 
     } 
     internal AsyncStreamReader(Process process, Stream stream, UserCallBack callback, Encoding encoding, int bufferSize) 
     { 
      this.Init(process, stream, callback, encoding, bufferSize); 
      this.messageQueue = new Queue(); 
     } 
     private void Init(Process process, Stream stream, UserCallBack callback, Encoding encoding, int bufferSize) 
     { 
      this.process = process; 
      this.stream = stream; 
      this.encoding = encoding; 
      this.userCallBack = callback; 
      this.decoder = encoding.GetDecoder(); 
      if (bufferSize < 128) 
      { 
       bufferSize = 128; 
      } 
      this.byteBuffer = new byte[bufferSize]; 
      this._maxCharsPerBuffer = encoding.GetMaxCharCount(bufferSize); 
      this.charBuffer = new char[this._maxCharsPerBuffer]; 
      this.cancelOperation = false; 
      this.eofEvent = new ManualResetEvent(false); 
      this.sb = null; 
      this.bLastCarriageReturn = false; 
     } 
     public virtual void Close() 
     { 
      this.Dispose(true); 
     } 
     void IDisposable.Dispose() 
     { 
      this.Dispose(true); 
      GC.SuppressFinalize(this); 
     } 
     protected virtual void Dispose(bool disposing) 
     { 
      if (disposing && this.stream != null) 
      { 
       this.stream.Close(); 
      } 
      if (this.stream != null) 
      { 
       this.stream = null; 
       this.encoding = null; 
       this.decoder = null; 
       this.byteBuffer = null; 
       this.charBuffer = null; 
      } 
      if (this.eofEvent != null) 
      { 
       this.eofEvent.Close(); 
       this.eofEvent = null; 
      } 
     } 
     internal void BeginReadLine() 
     { 
      if (this.cancelOperation) 
      { 
       this.cancelOperation = false; 
      } 
      if (this.sb == null) 
      { 
       this.sb = new StringBuilder(1024); 
       this.stream.BeginRead(this.byteBuffer, 0, this.byteBuffer.Length, new AsyncCallback(this.ReadBuffer), null); 
       return; 
      } 
      this.FlushMessageQueue(); 
     } 
     internal void CancelOperation() 
     { 
      this.cancelOperation = true; 
     } 
     private void ReadBuffer(IAsyncResult ar) 
     { 
      int num; 
      try 
      { 
       num = this.stream.EndRead(ar); 
      } 
      catch (IOException) 
      { 
       num = 0; 
      } 
      catch (OperationCanceledException) 
      { 
       num = 0; 
      } 
      if (num == 0) 
      { 
       lock (this.messageQueue) 
       { 
        if (this.sb.Length != 0) 
        { 
         this.messageQueue.Enqueue(this.sb.ToString()); 
         this.sb.Length = 0; 
        } 
        this.messageQueue.Enqueue(null); 
       } 
       try 
       { 
        this.FlushMessageQueue(); 
        return; 
       } 
       finally 
       { 
        this.eofEvent.Set(); 
       } 
      } 
      int chars = this.decoder.GetChars(this.byteBuffer, 0, num, this.charBuffer, 0); 
      this.sb.Append(this.charBuffer, 0, chars); 
      this.GetLinesFromStringBuilder(); 
      this.stream.BeginRead(this.byteBuffer, 0, this.byteBuffer.Length, new AsyncCallback(this.ReadBuffer), null); 
     } 
     private void GetLinesFromStringBuilder() 
     { 
      int i = 0; 
      int num = 0; 
      int length = this.sb.Length; 
      if (this.bLastCarriageReturn && length > 0 && this.sb[0] == '\n') 
      { 
       i = 1; 
       num = 1; 
       this.bLastCarriageReturn = false; 
      } 
      while (i < length) 
     { 
      char c = this.sb[i]; 
      if (c == '\r' || c == '\n') 
      { 
       if (c == '\r' && i + 1 < length && this.sb[i + 1] == '\n') 
       { 
        i++; 
       } 

       string obj = this.sb.ToString(num, i + 1 - num); 

       num = i + 1; 

       lock (this.messageQueue) 
       { 
        this.messageQueue.Enqueue(obj); 
       } 
      } 
      i++; 
     } 

      // Flush Fix: Send Whatever is left in the buffer 
      string endOfBuffer = this.sb.ToString(num, length - num); 
      lock (this.messageQueue) 
      { 
       this.messageQueue.Enqueue(endOfBuffer); 
       num = length; 
      } 
      // End Flush Fix 

      if (this.sb[length - 1] == '\r') 
      { 
       this.bLastCarriageReturn = true; 
      } 
      if (num < length) 
      { 
       this.sb.Remove(0, num); 
      } 
      else 
      { 
       this.sb.Length = 0; 
      } 
      this.FlushMessageQueue(); 
     } 
     private void FlushMessageQueue() 
     { 
      while (this.messageQueue.Count > 0) 
      { 
       lock (this.messageQueue) 
       { 
        if (this.messageQueue.Count > 0) 
        { 
         string data = (string)this.messageQueue.Dequeue(); 
         if (!this.cancelOperation) 
         { 
          this.userCallBack(data); 
         } 
        } 
        continue; 
       } 
       break; 
      } 
     } 
     internal void WaitUtilEOF() 
     { 
      if (this.eofEvent != null) 
      { 
       this.eofEvent.WaitOne(); 
       this.eofEvent.Close(); 
       this.eofEvent = null; 
      } 
     } 
    } 

    public class DataReceivedEventArgs : EventArgs 
    { 
     internal string _data; 
     /// <summary>Gets the line of characters that was written to a redirected <see cref="T:System.Diagnostics.Process" /> output stream.</summary> 
     /// <returns>The line that was written by an associated <see cref="T:System.Diagnostics.Process" /> to its redirected <see cref="P:System.Diagnostics.Process.StandardOutput" /> or <see cref="P:System.Diagnostics.Process.StandardError" /> stream.</returns> 
     /// <filterpriority>2</filterpriority> 
     public string Data 
     { 
      get 
      { 
       return this._data; 
      } 
     } 
     internal DataReceivedEventArgs(string data) 
     { 
      this._data = data; 
     } 
    } 
} 

我轉換的代碼看起來是這樣的:

Imports System 
Imports System.Collections 
Imports System.IO 
Imports System.Text 
Imports System.Threading 

Namespace System.Diagnostics 
    Friend Delegate Sub UserCallBack(data As String) 
    Public Delegate Sub DataReceivedEventHandler(sender As Object, e As DataReceivedEventArgs) 

    Public Class FixedProcess 
     Inherits Process 
     Friend output As AsyncStreamReader 
     Friend [error] As AsyncStreamReader 
     Public Event OutputDataReceived As DataReceivedEventHandler '<----------Error 1 
     Public Event ErrorDataReceived As DataReceivedEventHandler '<------------Error 2 

     Public Shadows Sub BeginOutputReadLine() 
      Dim baseStream As Stream = StandardOutput.BaseStream 
      Me.output = New AsyncStreamReader(Me, baseStream, New UserCallBack(AddressOf Me.FixedOutputReadNotifyUser), StandardOutput.CurrentEncoding) 
      Me.output.BeginReadLine() 
     End Sub 

     Public Sub BeginErrorReadLine() '<-------------Error 3 
      Dim baseStream As Stream = StandardError.BaseStream 
      Me.[error] = New AsyncStreamReader(Me, baseStream, New UserCallBack(AddressOf Me.FixedErrorReadNotifyUser), StandardError.CurrentEncoding) 
      Me.[error].BeginReadLine() 
     End Sub 

     Friend Sub FixedOutputReadNotifyUser(data As String) 

      Dim outputDataReceived As DataReceivedEventHandler = Me.OutputDataReceived '<------------Error 4 
      If outputDataReceived IsNot Nothing Then 
       Dim dataReceivedEventArgs As New DataReceivedEventArgs(data) 
       If Me.SynchronizingObject IsNot Nothing AndAlso Me.SynchronizingObject.InvokeRequired Then 
        Me.SynchronizingObject.Invoke(outputDataReceived, New Object() {Me, dataReceivedEventArgs}) 
        Return 
       End If 
       outputDataReceived(Me, dataReceivedEventArgs) 
      End If 
     End Sub 

     Friend Sub FixedErrorReadNotifyUser(data As String) 
      Dim errorDataReceived As DataReceivedEventHandler = Me.ErrorDataReceived '<-------------Error 5 
      If errorDataReceived IsNot Nothing Then 
       Dim dataReceivedEventArgs As New DataReceivedEventArgs(data) 
       If Me.SynchronizingObject IsNot Nothing AndAlso Me.SynchronizingObject.InvokeRequired Then 
        Me.SynchronizingObject.Invoke(errorDataReceived, New Object() {Me, dataReceivedEventArgs}) 
        Return 
       End If 
       errorDataReceived(Me, dataReceivedEventArgs) 
      End If 
     End Sub 
    End Class 

    Friend Class AsyncStreamReader 
     Implements IDisposable 
     Friend Const DefaultBufferSize As Integer = 1024 
     Private Const MinBufferSize As Integer = 128 
     Private stream As Stream 
     Private encoding As Encoding 
     Private decoder As Decoder 
     Private byteBuffer As Byte() 
     Private charBuffer As Char() 
     Private _maxCharsPerBuffer As Integer 
     Private process As Process 
     Private userCallBack As UserCallBack 
     Private cancelOperation As Boolean 
     Private eofEvent As ManualResetEvent 
     Private messageQueue As Queue 
     Private sb As StringBuilder 
     Private bLastCarriageReturn As Boolean 
     Public Overridable ReadOnly Property CurrentEncoding() As Encoding 
      Get 
       Return Me.encoding 
      End Get 
     End Property 
     Public Overridable ReadOnly Property BaseStream() As Stream 
      Get 
       Return Me.stream 
      End Get 
     End Property 
     Friend Sub New(process As Process, stream As Stream, callback As UserCallBack, encoding As Encoding) 
      Me.New(process, stream, callback, encoding, 1024) 
     End Sub 
     Friend Sub New(process As Process, stream As Stream, callback As UserCallBack, encoding As Encoding, bufferSize As Integer) 
      Me.Init(process, stream, callback, encoding, bufferSize) 
      Me.messageQueue = New Queue() 
     End Sub 
     Private Sub Init(process As Process, stream As Stream, callback As UserCallBack, encoding As Encoding, bufferSize As Integer) 
      Me.process = process 
      Me.stream = stream 
      Me.encoding = encoding 
      Me.userCallBack = callback 
      Me.decoder = encoding.GetDecoder() 
      If bufferSize < 128 Then 
       bufferSize = 128 
      End If 
      Me.byteBuffer = New Byte(bufferSize - 1) {} 
      Me._maxCharsPerBuffer = encoding.GetMaxCharCount(bufferSize) 
      Me.charBuffer = New Char(Me._maxCharsPerBuffer - 1) {} 
      Me.cancelOperation = False 
      Me.eofEvent = New ManualResetEvent(False) 
      Me.sb = Nothing 
      Me.bLastCarriageReturn = False 
     End Sub 
     Public Overridable Sub Close() 
      Me.Dispose(True) 
     End Sub 
     Private Sub IDisposable_Dispose() Implements IDisposable.Dispose 
      Me.Dispose(True) 
      GC.SuppressFinalize(Me) 
     End Sub 
     Protected Overridable Sub Dispose(disposing As Boolean) 
      If disposing AndAlso Me.stream IsNot Nothing Then 
       Me.stream.Close() 
      End If 
      If Me.stream IsNot Nothing Then 
       Me.stream = Nothing 
       Me.encoding = Nothing 
       Me.decoder = Nothing 
       Me.byteBuffer = Nothing 
       Me.charBuffer = Nothing 
      End If 
      If Me.eofEvent IsNot Nothing Then 
       Me.eofEvent.Close() 
       Me.eofEvent = Nothing 
      End If 
     End Sub 
     Friend Sub BeginReadLine() 
      If Me.cancelOperation Then 
       Me.cancelOperation = False 
      End If 
      If Me.sb Is Nothing Then 
       Me.sb = New StringBuilder(1024) 
       Me.stream.BeginRead(Me.byteBuffer, 0, Me.byteBuffer.Length, New AsyncCallback(AddressOf Me.ReadBuffer), Nothing) 
       Return 
      End If 
      Me.FlushMessageQueue() 
     End Sub 
     Friend Sub CancelOperation() '<------- Error 6 
      Me.cancelOperation = True 
     End Sub 
     Private Sub ReadBuffer(ar As IAsyncResult) 
      Dim num As Integer 
      Try 
       num = Me.stream.EndRead(ar) 
      Catch generatedExceptionName As IOException 
       num = 0 
      Catch generatedExceptionName As OperationCanceledException 
       num = 0 
      End Try 
      If num = 0 Then 
       SyncLock Me.messageQueue 
        If Me.sb.Length <> 0 Then 
         Me.messageQueue.Enqueue(Me.sb.ToString()) 
         Me.sb.Length = 0 
        End If 
        Me.messageQueue.Enqueue(Nothing) 
       End SyncLock 
       Try 
        Me.FlushMessageQueue() 
        Return 
       Finally 
        Me.eofEvent.[Set]() 
       End Try 
      End If 
      Dim chars As Integer = Me.decoder.GetChars(Me.byteBuffer, 0, num, Me.charBuffer, 0) 
      Me.sb.Append(Me.charBuffer, 0, chars) 
      Me.GetLinesFromStringBuilder() 
      Me.stream.BeginRead(Me.byteBuffer, 0, Me.byteBuffer.Length, New AsyncCallback(AddressOf Me.ReadBuffer), Nothing) 
     End Sub 
     Private Sub GetLinesFromStringBuilder() 
      Dim i As Integer = 0 
      Dim num As Integer = 0 
      Dim length As Integer = Me.sb.Length 
      If Me.bLastCarriageReturn AndAlso length > 0 AndAlso Me.sb(0) = ControlChars.Lf Then 
       i = 1 
       num = 1 
       Me.bLastCarriageReturn = False 
      End If 
      While i < length 
       Dim c As Char = Me.sb(i) 
       If c = ControlChars.Cr OrElse c = ControlChars.Lf Then 
        If c = ControlChars.Cr AndAlso i + 1 < length AndAlso Me.sb(i + 1) = ControlChars.Lf Then 
         i += 1 
        End If 

        Dim obj As String = Me.sb.ToString(num, i + 1 - num) 

        num = i + 1 

        SyncLock Me.messageQueue 
         Me.messageQueue.Enqueue(obj) 
        End SyncLock 
       End If 
       i += 1 
      End While 

      ' Flush Fix: Send Whatever is left in the buffer 
      Dim endOfBuffer As String = Me.sb.ToString(num, length - num) 
      SyncLock Me.messageQueue 
       Me.messageQueue.Enqueue(endOfBuffer) 
       num = length 
      End SyncLock 
      ' End Flush Fix 

      If Me.sb(length - 1) = ControlChars.Cr Then 
       Me.bLastCarriageReturn = True 
      End If 
      If num < length Then 
       Me.sb.Remove(0, num) 
      Else 
       Me.sb.Length = 0 
      End If 
      Me.FlushMessageQueue() 
     End Sub 
     Private Sub FlushMessageQueue() 
      While Me.messageQueue.Count > 0 
       SyncLock Me.messageQueue 
        If Me.messageQueue.Count > 0 Then 
         Dim data As String = DirectCast(Me.messageQueue.Dequeue(), String) 
         If Not Me.cancelOperation Then 
          Me.userCallBack(data) 
         End If 
        End If 
        Continue While 
       End SyncLock 
       Exit While 
      End While 
     End Sub 
     Friend Sub WaitUtilEOF() 
      If Me.eofEvent IsNot Nothing Then 
       Me.eofEvent.WaitOne() 
       Me.eofEvent.Close() 
       Me.eofEvent = Nothing 
      End If 
     End Sub 
    End Class 

    Public Class DataReceivedEventArgs 
     Inherits EventArgs 
     Friend _data As String 
     ''' <summary>Gets the line of characters that was written to a redirected <see cref="T:System.Diagnostics.Process" /> output stream.</summary> 
     ''' <returns>The line that was written by an associated <see cref="T:System.Diagnostics.Process" /> to its redirected <see cref="P:System.Diagnostics.Process.StandardOutput" /> or <see cref="P:System.Diagnostics.Process.StandardError" /> stream.</returns> 
     ''' <filterpriority>2</filterpriority> 
     Public ReadOnly Property Data() As String 
      Get 
       Return Me._data 
      End Get 
     End Property 
     Friend Sub New(data As String) 
      Me._data = data 
     End Sub 
    End Class 
End Namespace 

錯誤1-3似乎是警告,並可能實際工作 尤其是錯誤4和5讓我頭痛「公共Ev ent OutputDataRecieved(sender As Object,e As DataRecievedEventArgs)是一個事件,不能直接調用。使用RaiseEvent語句引發一個事件。」

事件處理不似乎與任何代碼轉換器我已經試過的工作,我缺乏VB技能,它手動轉換。

有一個友好的靈魂出來還有誰能夠正確執行這種轉換類,以它的實際工作?

非常感謝!

羅馬

+4

如果你不知道VB爲什麼還要將其轉換到VB?將它留在C#項目中,並從VB項目中引用它。您可以在同一解決方案中擁有C#和VB項目。 – CaffGeek

+4

將該類編譯爲.NET程序集。將該程序集添加爲您的VB.NET項目的引用。請享用! – Oded

+0

您可以使用此方法而不是將其轉換。 IL將是相同的 –

回答

1

您需要將Overloads關鍵字添加到BeginErrorReadLine方法簽名中。

Public Overloads Sub BeginErrorReadLine() '<-------------Error 3 

事件聲明需要聲明爲Shadows,因爲它們會與基類事件聲明發生衝突。

Public Shadows Event OutputDataReceived As DataReceivedEventHandler '<----------Error 1 

然後在您的FixedOutputReadNotifyUser方法,你不需要像在C#做的,看看它是什麼檢查事件處理程序。 VB會爲你做到這一點。相反,簡單地提高它如下:

Friend Sub FixedOutputReadNotifyUser(data As String) 
    Dim dataReceivedEventArgs As New DataReceivedEventArgs(data) 
    RaiseEvent OutputDataReceived(Me, dataReceivedEventArgs) 
End Sub 

的最後一個問題是原來的類使用區分大小寫的「cancelOperation」字段和「CancelOperation」的方法來區分。最佳選擇是在字段前加一個下劃線,如下所示:Private _CancelOperation As Boolean然後修復該類中的相應引用。

+0

+1。這就是爲什麼我給CaffGeek的答案+1的原因,只是將C#構建到程序集中,然後在VB項目中使用它,這需要幾分鐘的時間,並且需要很少的C#知識。 – MarkJ

+2

但通過翻譯的努力實際上增加了您對所使用的代碼和您的語言的理解。盲目使用別人的代碼而不考慮其後果並不一定是積極的。 –

+1

@JimWooley,+1我同意你的觀點,你應該在使用它之前總是理解代碼。 – CaffGeek

4

在您的解決方案,添加一個新的C#項目。把這個C#代碼在裏面。

從您的vb項目中,添加對c#項目的引用。

您現在可以調用vb中的c#對象。

當它轉換爲IL時,它們都是一樣的。

+0

非常感謝答覆。我目前只安裝了Visual Basic 2010 Express Edition。我只是下載了C#Express 2010以及...希望這個版本可以使用Express版本! – user1665789

+0

@ user1665789,沒問題,歡迎來Stack Overflow。如果這個問題或其他問題解決了您的問題,請將其標記爲答案。 – CaffGeek

0

對於您的「錯誤4」&「錯誤5」,請改爲使用它 - 請注意,您需要將局部變量設置爲以「Event」結尾的隱藏VB後備代理字段。還要注意,你對局部變量的測試是無效的,因爲我們沒有檢查一個事件是什麼,而是一個委託類型的局部變量 - 「錯誤5」的方法是完全相同的:

Friend Sub FixedOutputReadNotifyUser(ByVal data As String) 
    Dim outputDataReceived As DataReceivedEventHandler = Me.OutputDataReceivedEvent 
    If outputDataReceived IsNot Nothing Then 
     Dim dataReceivedEventArgs As New DataReceivedEventArgs(data) 
     If Me.SynchronizingObject IsNot Nothing AndAlso Me.SynchronizingObject.InvokeRequired Then 
      Me.SynchronizingObject.Invoke(outputDataReceived, New Object() { Me, dataReceivedEventArgs }) 
      Return 
     End If 
     outputDataReceived(Me, dataReceivedEventArgs) 
    End If 
End Sub 
0

下面是我現在使用的代碼。我刪除了命名空間,因爲我不知道如何在我的項目中引入第二個命名空間,並將代碼粘貼到新模塊中。然後,如原來的C#解決方案中所建議的,我只是將我的「p as new process」改爲「p as new FixedProcess」。

再次感謝所有的建議!

你們搖滾!

爲了給你一個我想要做的事情的完整圖片,我還包括了表單代碼。我不認爲自己是程序員,所以如果它不像你們大多數人那樣可能做到那麼複雜,請耐心等待。這樣做的目的是通過plink遠程控制SSH會話並在Cisco路由器上自動執行命令。

這段代碼很有效,現在只剩下一個(有希望的)小缺陷:如果我關閉底層的plink.exe,我想關閉輸入和輸出流。到目前爲止,我無法在我的「借閱」課中找到如何做到這一點。

我想在窗體的關閉事件上做到這一點。它殺死了plink.exe進程,但是如果我再次打開表單進行另一個會話,它將雙擊輸出,如果我關閉並重新打開一次,則會扭曲輸出...

任何建議如何正確關閉流?

Imports System 
Imports System.Text 
Imports System.IO 
Imports System.Diagnostics 
Imports System.Threading 
Imports System.ComponentModel 
Imports Microsoft.VisualBasic 

Imports System.Collections.Generic 
Imports System.Linq 


Imports System.Collections 



Module Module2 


    Friend Delegate Sub UserCallBack(ByVal data As String) 
    Public Delegate Sub DataReceivedEventHandler(ByVal sender As Object, ByVal e As DataReceivedEventArgs) 




    Public Class FixedProcess 
     Inherits Process 
     Friend output As AsyncStreamReader 
     Friend [error] As AsyncStreamReader 
     Public Shadows Event OutputDataReceived As DataReceivedEventHandler 
     Public Shadows Event ErrorDataReceived As DataReceivedEventHandler 

     Public CancelAll As Boolean = False 

     Public Overloads Sub BeginOutputReadLine() 
      Dim baseStream As Stream = StandardOutput.BaseStream 
      Me.output = New AsyncStreamReader(Me, baseStream, New UserCallBack(AddressOf Me.FixedOutputReadNotifyUser), StandardOutput.CurrentEncoding) 
      Me.output.BeginReadLine() 
     End Sub 

     Public Overloads Sub BeginErrorReadLine() 
      Dim baseStream As Stream = StandardError.BaseStream 
      Me.[error] = New AsyncStreamReader(Me, baseStream, New UserCallBack(AddressOf Me.FixedErrorReadNotifyUser), StandardError.CurrentEncoding) 
      Me.[error].BeginReadLine() 
     End Sub 

     Friend Sub FixedOutputReadNotifyUser(ByVal data As String) 
      Dim dataReceivedEventArgs As New DataReceivedEventArgs(data) 
      RaiseEvent OutputDataReceived(Me, dataReceivedEventArgs) 

     End Sub 





     Friend Sub FixedErrorReadNotifyUser(ByVal data As String) 
      Dim errorDataReceivedEventArgs As New DataReceivedEventArgs(data) 
      RaiseEvent ErrorDataReceived(Me, errorDataReceivedEventArgs) 

     End Sub 




    End Class 

    Friend Class AsyncStreamReader 
     Implements IDisposable 
     Friend Const DefaultBufferSize As Integer = 1024 
     Private Const MinBufferSize As Integer = 128 
     Private stream As Stream 
     Private encoding As Encoding 
     Private decoder As Decoder 
     Private byteBuffer As Byte() 
     Private charBuffer As Char() 
     Private _maxCharsPerBuffer As Integer 
     Private process As Process 
     Private userCallBack As UserCallBack 
     Public cancelOperation As Boolean 
     Private eofEvent As ManualResetEvent 
     Private messageQueue As Queue 
     Private sb As StringBuilder 
     Private bLastCarriageReturn As Boolean 
     Public Overridable ReadOnly Property CurrentEncoding() As Encoding 
      Get 
       Return Me.encoding 
      End Get 
     End Property 
     Public Overridable ReadOnly Property BaseStream() As Stream 
      Get 
       Return Me.stream 
      End Get 
     End Property 
     Friend Sub New(ByVal process As Process, ByVal stream As Stream, ByVal callback As UserCallBack, ByVal encoding As Encoding) 
      Me.New(process, stream, callback, encoding, 1024) 
     End Sub 
     Friend Sub New(ByVal process As Process, ByVal stream As Stream, ByVal callback As UserCallBack, ByVal encoding As Encoding, ByVal bufferSize As Integer) 
      Me.Init(process, stream, callback, encoding, bufferSize) 
      Me.messageQueue = New Queue() 
     End Sub 
     Private Sub Init(ByVal process As Process, ByVal stream As Stream, ByVal callback As UserCallBack, ByVal encoding As Encoding, ByVal bufferSize As Integer) 
      Me.process = process 
      Me.stream = stream 
      Me.encoding = encoding 
      Me.userCallBack = callback 
      Me.decoder = encoding.GetDecoder() 
      If bufferSize < 128 Then 
       bufferSize = 128 
      End If 
      Me.byteBuffer = New Byte(bufferSize - 1) {} 
      Me._maxCharsPerBuffer = encoding.GetMaxCharCount(bufferSize) 
      Me.charBuffer = New Char(Me._maxCharsPerBuffer - 1) {} 
      Me.cancelOperation = False 
      Me.eofEvent = New ManualResetEvent(False) 
      Me.sb = Nothing 
      Me.bLastCarriageReturn = False 
     End Sub 
     Public Overridable Sub Close() 
      Me.Dispose(True) 
     End Sub 
     Private Sub IDisposable_Dispose() Implements IDisposable.Dispose 
      Me.Dispose(True) 
      GC.SuppressFinalize(Me) 
     End Sub 
     Protected Overridable Sub Dispose(ByVal disposing As Boolean) 
      If disposing AndAlso Me.stream IsNot Nothing Then 
       Me.stream.Close() 
      End If 
      If Me.stream IsNot Nothing Then 
       Me.stream = Nothing 
       Me.encoding = Nothing 
       Me.decoder = Nothing 
       Me.byteBuffer = Nothing 
       Me.charBuffer = Nothing 
      End If 
      If Me.eofEvent IsNot Nothing Then 
       Me.eofEvent.Close() 
       Me.eofEvent = Nothing 
      End If 
     End Sub 
     Friend Sub BeginReadLine() 
      If Me.cancelOperation Then 
       Me.cancelOperation = False 
      End If 
      If Me.sb Is Nothing Then 
       Me.sb = New StringBuilder(1024) 
       Me.stream.BeginRead(Me.byteBuffer, 0, Me.byteBuffer.Length, New AsyncCallback(AddressOf Me.ReadBuffer), Nothing) 
       Return 
      End If 
      Me.FlushMessageQueue() 
     End Sub 
     Friend Sub _CancelOperation() 
      Me.cancelOperation = True 
     End Sub 
     Private Sub ReadBuffer(ByVal ar As IAsyncResult) 

      Dim num As Integer 

      Try 
       num = Me.stream.EndRead(ar) 
      Catch generatedExceptionName As IOException 
       num = 0 
      Catch generatedExceptionName As OperationCanceledException 
       num = 0 
      End Try 
      If num = 0 Then 
       SyncLock Me.messageQueue 
        If Me.sb.Length <> 0 Then 
         Me.messageQueue.Enqueue(Me.sb.ToString()) 
         Me.sb.Length = 0 
        End If 
        Me.messageQueue.Enqueue(Nothing) 
       End SyncLock 
       Try 
        Me.FlushMessageQueue() 
        Return 
       Finally 
        Me.eofEvent.[Set]() 
       End Try 
      End If 
      Dim chars As Integer = Me.decoder.GetChars(Me.byteBuffer, 0, num, Me.charBuffer, 0) 
      Me.sb.Append(Me.charBuffer, 0, chars) 
      Me.GetLinesFromStringBuilder() 
      Me.stream.BeginRead(Me.byteBuffer, 0, Me.byteBuffer.Length, New AsyncCallback(AddressOf Me.ReadBuffer), Nothing) 


     End Sub 
     Private Sub GetLinesFromStringBuilder() 
      Dim i As Integer = 0 
      Dim num As Integer = 0 
      Dim length As Integer = Me.sb.Length 
      If Me.bLastCarriageReturn AndAlso length > 0 AndAlso Me.sb(0) = ControlChars.Lf Then 
       i = 1 
       num = 1 
       Me.bLastCarriageReturn = False 
      End If 
      While i < length 
       Dim c As Char = Me.sb(i) 
       If c = ControlChars.Cr OrElse c = ControlChars.Lf Then 
        If c = ControlChars.Cr AndAlso i + 1 < length AndAlso Me.sb(i + 1) = ControlChars.Lf Then 
         i += 1 
        End If 

        Dim obj As String = Me.sb.ToString(num, i + 1 - num) 

        num = i + 1 

        SyncLock Me.messageQueue 
         Me.messageQueue.Enqueue(obj) 
        End SyncLock 
       End If 
       i += 1 
      End While 

      ' Flush Fix: Send Whatever is left in the buffer 
      Dim endOfBuffer As String = Me.sb.ToString(num, length - num) 
      SyncLock Me.messageQueue 
       Me.messageQueue.Enqueue(endOfBuffer) 
       num = length 
      End SyncLock 
      ' End Flush Fix 

      If Me.sb(length - 1) = ControlChars.Cr Then 
       Me.bLastCarriageReturn = True 
      End If 
      If num < length Then 
       Me.sb.Remove(0, num) 
      Else 
       Me.sb.Length = 0 
      End If 
      Me.FlushMessageQueue() 
     End Sub 
     Private Sub FlushMessageQueue() 
      While Me.messageQueue.Count > 0 
       SyncLock Me.messageQueue 
        If Me.messageQueue.Count > 0 Then 
         Dim data As String = DirectCast(Me.messageQueue.Dequeue(), String) 
         If Not Me.cancelOperation Then 
          Me.userCallBack(data) 
         End If 
        End If 
        Continue While 
       End SyncLock 
       Exit While 
      End While 
     End Sub 
     Friend Sub WaitUtilEOF() 
      If Me.eofEvent IsNot Nothing Then 
       Me.eofEvent.WaitOne() 
       Me.eofEvent.Close() 
       Me.eofEvent = Nothing 
      End If 
     End Sub 
    End Class 

    Public Class DataReceivedEventArgs 
     Inherits EventArgs 
     Friend _data As String 
     ''' <summary>Gets the line of characters that was written to a redirected <see cref="T:System.Diagnostics.Process" /> output stream.</summary> 
     ''' <returns>The line that was written by an associated <see cref="T:System.Diagnostics.Process" /> to its redirected <see cref="P:System.Diagnostics.Process.StandardOutput" /> or <see cref="P:System.Diagnostics.Process.StandardError" /> stream.</returns> 
     ''' <filterpriority>2</filterpriority> 
     Public ReadOnly Property Data() As String 
      Get 
       Return Me._data 
      End Get 
     End Property 
     Friend Sub New(ByVal data As String) 
      Me._data = data 
     End Sub 
    End Class 






End Module 

和我的表單代碼...

Imports System 
Imports System.Text 
Imports System.IO 
Imports System.Diagnostics 
Imports System.Threading 
Imports System.ComponentModel 
Imports Microsoft.VisualBasic 

Imports System.Collections.Generic 
Imports System.Linq 


Imports System.Collections 




Public Class Form3 

    ' Define static variables shared by class methods. 
    Private Shared shellOutput As StringBuilder = Nothing 
    Private Shared numOutputLines As Integer = 0 
    Private Shared stdIN As StreamWriter 
    Private Shared p As New FixedProcess 'as new 
    Private Shared oldOutlineData As String = "" 
    Private Shared PasswordInput As Boolean = False 



    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click 
     ShowISDNStatus() 

    End Sub 

    Public Sub ShowISDNStatus() 
     Dim p_info As New ProcessStartInfo 'as new 
     p_info.FileName = Form1.PlinkPath 
     p_info.Arguments = Form1.KommandoArguments 
     p_info.UseShellExecute = False 
     p_info.CreateNoWindow = True 
     p_info.RedirectStandardOutput = True 
     p_info.RedirectStandardInput = True 
     p_info.RedirectStandardError = True 
     ' Set our event handler to asynchronously read the shell output. 
     AddHandler p.OutputDataReceived, AddressOf dirOutputHandler 
     AddHandler p.ErrorDataReceived, AddressOf dirOutputHandler 



     shellOutput = New StringBuilder 
     p.StartInfo = p_info 
     p.Start() 
     p.BeginOutputReadLine() 
     p.BeginErrorReadLine() 
     stdIN = p.StandardInput 

     'stdIN.WriteLine("enable" & vbCr & "K#limdor1" & vbCrLf) 
     'Timer1.Enabled = True 
     'System.Threading.Thread.Sleep(500) 

     'stdIN.WriteLine("term len 0") 
     'stdIN.WriteLine("show isdn status") 

     stdIN.WriteLine("enable" & vbCr & Form1.TextPassword.Text & vbCrLf) 
     Timer1.Enabled = True 
     System.Threading.Thread.Sleep(500) 
     Me.TextBox2.Text = "" 
     stdIN.WriteLine("term len 0") 
     stdIN.WriteLine("show isdn status") 
     Me.TextBox1.Select(TextBox1.Text.Length, 0) 
     Me.TextBox1.ScrollToCaret() 

    End Sub 

    Private Shared Sub dirOutputHandler(ByVal sendingProcess As Object, ByVal outLine As DataReceivedEventArgs) 
     ''If Not String.IsNullOrEmpty(outLine.Data) Then 
     shellOutput.Append(outLine.Data) 

     'For i = 1 To Len(outLine.Data) 
     ' FormDebug.TextBox1.Text = "Len von OutlineData: " & Len(outLine.Data) & " " & Asc(Mid(outLine.Data, i, 1)) & "---" & Mid(outLine.Data, i, 1) 
     'Next 

     If outLine.Data = "Store key in cache? (y/n) " Then 
      stdIN.WriteLine("y") 
     End If 

     Form3.TextBox1.Text = outLine.Data 

     ''End If 
    End Sub 

    Private Sub Form3_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load 



    End Sub 

    Private Sub Form3_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing 


     p.Kill() 



    End Sub 


    Private Sub TextBox2_PreviewKeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs) Handles TextBox2.PreviewKeyDown 

     If e.KeyCode = Keys.Return Then 

      If PasswordInput = False Then 
       If Me.TextBox2.Text = "en" Then 
        Me.TextBox2.UseSystemPasswordChar = True 
        Me.TextBox2.Text = "" 
        PasswordInput = True 
        Timer1.Enabled = False 
        Me.TextBox1.AppendText("Password:") 

       ElseIf Me.TextBox2.Text = "ena" Then 
        Me.TextBox2.UseSystemPasswordChar = True 
        Me.TextBox2.Text = "" 
        PasswordInput = True 
        Timer1.Enabled = False 
        Me.TextBox1.AppendText("Password:") 

       ElseIf Me.TextBox2.Text = "enab" Then 
        Me.TextBox2.UseSystemPasswordChar = True 
        Me.TextBox2.Text = "" 
        PasswordInput = True 
        Timer1.Enabled = False 
        Me.TextBox1.AppendText("Password:") 

       ElseIf Me.TextBox2.Text = "enabl" Then 
        Me.TextBox2.UseSystemPasswordChar = True 
        Me.TextBox2.Text = "" 
        PasswordInput = True 
        Timer1.Enabled = False 
        Me.TextBox1.AppendText("Password:") 

       ElseIf Me.TextBox2.Text = "enable" Then 
        Me.TextBox2.UseSystemPasswordChar = True 
        Me.TextBox2.Text = "" 
        PasswordInput = True 
        Timer1.Enabled = False 
        Me.TextBox1.AppendText("Password:") 

       ElseIf Me.TextBox2.Text = "" Then 
        stdIN.WriteLine() 
        System.Threading.Thread.Sleep(500) 
        Me.TextBox1.Select(TextBox1.Text.Length, 0) 
        Me.TextBox1.ScrollToCaret() 
       Else 
        stdIN.WriteLine(Me.TextBox2.Text) 
        System.Threading.Thread.Sleep(500) 
        Me.TextBox2.Text = "" 
        Me.TextBox1.Text = shellOutput.ToString 
        Me.TextBox1.Select(TextBox1.Text.Length, 0) 
        Me.TextBox1.ScrollToCaret() 
       End If 

      Else 

       stdIN.WriteLine("enable" & vbCr & Me.TextBox2.Text & vbCrLf) 
       System.Threading.Thread.Sleep(500) 
       Me.TextBox2.Text = "" 
       Timer1.Enabled = True 
       Me.TextBox2.UseSystemPasswordChar = False 
       stdIN.WriteLine("term len 0") 
       Me.TextBox1.Select(TextBox1.Text.Length, 0) 
       Me.TextBox1.ScrollToCaret() 
       PasswordInput = False 

      End If 


     End If 

    End Sub 


    Private Sub TextBox2_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox2.TextChanged 

    End Sub 

    Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged 
     Me.TextBox1.SelectAll() 
     Me.TextBox1.ScrollToCaret() 
    End Sub 

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick 
     ' If Me.TextBox1.Text <> shellOutput.ToString Then Me.TextBox1.Text = shellOutput.ToString 
     Me.TextBox1.Text = shellOutput.ToString 

    End Sub 

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 

     FormDebug.Show() 
     'Dim frm As New Form3 
     'Static Num As Integer 

     'Num = Num + 1 
     'frm.Text = "Copy of Form3 - " & Num 
     'frm.Show() 
    End Sub 
End Class 
+0

...嗯進一步調查看起來應該是這樣的:Public Overridable Sub Close() Me.Dispose(True) End Sub 不幸的是,它似乎需要system.diagnostics.close代替。我也嘗試在命名空間system.diagnostics的單獨項目中創建一個dll,但即使我將這個dll作爲名稱空間添加到我的項目中,它似乎仍然採用原始的close,而不是我的版本... – user1665789