【问题标题】:Code conversion from c# to vb.net including eventhandlers从 c# 到 vb.net 的代码转换,包括事件处理程序
【发布时间】:2012-09-13 17:50:05
【问题描述】:

您好,我找到了一个用 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让我头疼“Public Event OutputDataRecieved(sender As Object, e As DataRecievedEventArgs)是一个事件,不能直接调用。使用RaiseEvent语句引发事件。”

事件处理程序似乎不适用于我尝试过的任何代码转换器,而且我缺乏手动转换它的 VB 技能。

是否有一个友好的灵魂可以正确转换这个类以使其真正起作用?

非常感谢!

罗马

【问题讨论】:

  • 如果您不了解 VB,为什么还要麻烦将其转换为 VB?将其保留在 C# 项目中,并从 VB 项目中引用它。您可以在同一个解决方案中拥有一个 C# 和一个 VB 项目。
  • 将类编译成 .NET 程序集。添加程序集作为对 VB.NET 项目的引用。享受吧!
  • 你可以使用这个方法而不是转换它。 IL 将是相同的

标签: c# vb.net event-handling raiseevent


【解决方案1】:

在您的解决方案中,添加一个新的 c# 项目。将这段 c# 代码放入其中。

从您的 vb 项目中,添加对 c# 项目的引用。

您现在可以从 vb 调用 c# 对象。

转换成IL后还是一样

【讨论】:

  • 非常感谢您的回复。我目前只安装了 Visual Basic 2010 Express Edition。我也正在下载 C# Express 2010...希望这与 Express Editions 一起工作!
  • @user1665789,没问题,欢迎来到 Stack Overflow。如果这个或其他问题解决了您的问题,请将其标记为答案。
【解决方案2】:

您需要将 Overloads 关键字添加到 BeginErrorReadLine 方法签名中。

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

事件声明需要声明为阴影,否则它们会与基类事件声明冲突。

 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,然后在类中修复相应的引用。

【讨论】:

  • +1。这就是为什么我还给 CaffGeek 的回答 +1,说只需将 C# 构建到程序集中,然后从 VB 项目中使用它,这将需要几分钟并且几乎不需要 C# 知识。
  • 但是通过翻译工作实际上可以增加您对所使用的代码和您的语言的理解。盲目地使用别人的代码而不考虑后果并不一定是积极的。
  • @JimWooley,+1 我同意你在使用代码之前应该始终理解代码。
  • 我真的很想感谢大家的回答,我从他们所有人那里学到了答案,但最终使用了 Jims 代码建议,他们的工作就像一个魅力!
  • 我该怎么做? - 对不起,我是这个论坛的新手。
【解决方案3】:

对于您的“错误 4”和“错误 5”,请改用它 - 请注意,您需要将局部变量设置为以“事件”结尾的隐藏 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

【讨论】:

    【解决方案4】:

    下面是我现在使用的代码。我删除了命名空间,因为我不知道如何在我的项目中包含第二个命名空间并将代码粘贴到一个新模块中。然后按照原始 c# 解决方案中的建议,我只是将“p 作为新进程”更改为“p 作为新的 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
    

    【讨论】:

    • ...hmm 进一步的调查看起来应该是这样的: Public Overridable Sub Close() Me.Dispose(True) End Sub 不幸的是,它似乎取而代之的是 system.diagnostics.close。我还尝试使用命名空间 system.diagnostics 在单独的项目中创建一个 dll,但即使我将此 dll 作为命名空间添加到我的项目中,它似乎仍然采用原始关闭而不是我的版本...
    猜你喜欢
    • 2012-01-21
    • 1970-01-01
    • 2016-12-16
    • 1970-01-01
    • 2013-08-24
    • 2021-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多