.NET Console StandardOutput 不返回输入“问题”

发布于 2024-11-17 16:32:24 字数 2854 浏览 3 评论 0原文

我试图完全拦截控制台应用程序,即抓取它的输出并插入输入。

到目前为止,我几乎可以获取输出,并且输入也完全完美。 但是,在您发送一些输入之前,它不会显示控制台输出的“前缀”/“问题”。

例如,当挂接到 CMD.exe 控制台时。当您定期在 Windows 中启动它时,您会得到类似这样的信息:

Microsoft Windows [版本 6.1.7600]
版权所有 (c) 2009 Microsoft Corporation。保留所有权利。

C:\Users\用户名>

但是,输出仅返回:

Microsoft Windows [版本 6.1.7600]
版权所有 (c) 2009 Microsoft Corporation。保留所有权利。

然后,当您插入“D:”之类的内容(转到 D:\ 磁盘)时,您会得到以下内容:

C:\Users\用户名>D:

就是这样。不会给你“D:\>”或者,重新开始这个循环。

这是我当前的代码,但是,我 99% 确信它没有任何问题。除了这一点之外,它工作得很好。

Class MainWindow

Private MainDispatcher As System.Windows.Threading.Dispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher

Private Sub MainWindow_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
    StartProcess("cmd.exe")
End Sub

Private Sub InputTB_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Input.KeyEventArgs) Handles InputTB.KeyUp
    If e.Key = System.Windows.Input.Key.Enter Then
        InputStream.WriteLine(InputTB.Text)
        InputTB.Text = ""
    End If
End Sub

Private InputStream As IO.StreamWriter
Private OutputStream As IO.StreamReader
Public ProcessToMonitor As New Process
Private Sub StartProcess(ByVal FileName As String)

    ProcessToMonitor = New Process
    ProcessToMonitor.StartInfo.FileName = FileName
    ProcessToMonitor.StartInfo.UseShellExecute = False
    ProcessToMonitor.StartInfo.RedirectStandardError = True
    ProcessToMonitor.StartInfo.RedirectStandardOutput = True
    ProcessToMonitor.StartInfo.RedirectStandardInput = True
    ProcessToMonitor.StartInfo.ErrorDialog = False
    ProcessToMonitor.StartInfo.CreateNoWindow = True

    ProcessToMonitor.Start()

    InputStream = ProcessToMonitor.StandardInput
    OutputStream = ProcessToMonitor.StandardOutput

    ConstantReadThread.Priority = System.Threading.ThreadPriority.Lowest
    ConstantReadThread.Start()
End Sub

Private Sub OutputReceived(ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs)
    MainDispatcher.Invoke(New WriteOutputDelegate(AddressOf WriteOutput), e.Data)
End Sub

Private ConstantReadThread As New System.Threading.Thread(AddressOf ConstantRead)
Private Sub ConstantRead()
    Do
        MainDispatcher.Invoke(New WriteOutputDelegate(AddressOf WriteOutput), OutputStream.ReadLine())
    Loop
End Sub

Private Delegate Sub WriteOutputDelegate(ByVal Text As String)
Private Sub WriteOutput(ByVal Text As String)
    OutputTB.Text &= Text & vbNewLine
    OutputTB.ScrollToEnd()
End Sub

End Class

我还知道“OutputDataReceived”,这是我最初使用的,它也有同样的问题,这就是为什么我进入读取循环,我知道它更消耗CPU。

一如既往,非常感谢任何帮助。

-René

P.S. C#.Net 中的解决方案/建议也被接受。

I am trying to completely intercept a console application, that is, grabbing it's output, and inserting the input.

So far, I can pretty much grab the output, and input is completely perfect.
However, it will not show the "prefix"/"question" of the console's output, until you send some input.

As an example, when hooking to the CMD.exe console. When you regularly start it up in Windows, you get something like this:

Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.

C:\Users\Username>

However, the output only returns:

Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.

And then when you insert something like "D:" (to go to the D:\ disk), you get the following:

C:\Users\Username>D:

And that's it. Doesn't give you "D:\>" either, starting the cycle all over again.

This is my current code, however, I am 99% sure there's nothing wrong with it. It works perfectly except for this.

Class MainWindow

Private MainDispatcher As System.Windows.Threading.Dispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher

Private Sub MainWindow_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
    StartProcess("cmd.exe")
End Sub

Private Sub InputTB_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Input.KeyEventArgs) Handles InputTB.KeyUp
    If e.Key = System.Windows.Input.Key.Enter Then
        InputStream.WriteLine(InputTB.Text)
        InputTB.Text = ""
    End If
End Sub

Private InputStream As IO.StreamWriter
Private OutputStream As IO.StreamReader
Public ProcessToMonitor As New Process
Private Sub StartProcess(ByVal FileName As String)

    ProcessToMonitor = New Process
    ProcessToMonitor.StartInfo.FileName = FileName
    ProcessToMonitor.StartInfo.UseShellExecute = False
    ProcessToMonitor.StartInfo.RedirectStandardError = True
    ProcessToMonitor.StartInfo.RedirectStandardOutput = True
    ProcessToMonitor.StartInfo.RedirectStandardInput = True
    ProcessToMonitor.StartInfo.ErrorDialog = False
    ProcessToMonitor.StartInfo.CreateNoWindow = True

    ProcessToMonitor.Start()

    InputStream = ProcessToMonitor.StandardInput
    OutputStream = ProcessToMonitor.StandardOutput

    ConstantReadThread.Priority = System.Threading.ThreadPriority.Lowest
    ConstantReadThread.Start()
End Sub

Private Sub OutputReceived(ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs)
    MainDispatcher.Invoke(New WriteOutputDelegate(AddressOf WriteOutput), e.Data)
End Sub

Private ConstantReadThread As New System.Threading.Thread(AddressOf ConstantRead)
Private Sub ConstantRead()
    Do
        MainDispatcher.Invoke(New WriteOutputDelegate(AddressOf WriteOutput), OutputStream.ReadLine())
    Loop
End Sub

Private Delegate Sub WriteOutputDelegate(ByVal Text As String)
Private Sub WriteOutput(ByVal Text As String)
    OutputTB.Text &= Text & vbNewLine
    OutputTB.ScrollToEnd()
End Sub

End Class

I also know about the "OutputDataReceived", which is what I used at first, which had the same problems, that's why I stepped over to the read loop, I know it's more CPU consuming.

And as always, any help much appreciated.

-René

P.S. Solutions/suggestions in C#.Net also accepted.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

乱世争霸 2024-11-24 16:32:24

您无法获得所需的额外数据,因为这些数据是通过“CMD”作为应用程序本身生成的。我相信您尝试接收的功能甚至没有输出到输出流。

这可能是因为 Windows 向其启动的每个控制台应用程序添加了此额外功能,而不是应用程序实际作为输出流发送出去的功能。

我建议您做的是找出 CMD 开始的默认路径(似乎相当于):

System.Environment.GetFolderPath(Environment.SpecialFolder.Personal)

您可以使用它来模拟相同的功能。

如果您想知道 CMD 在哪里检查应用程序等,请查看系统上的环境变量,更具体地说是“PATH”环境变量。

There is no way you can get the extra data you are looking for, since that is generated through "CMD" as an application itself. I believe the functionality you are trying to receive is not even output to the output stream.

This may be because Windows adds this extra functionality to every single console application it launches, and is not something the application actually sends out as an output stream.

What I suggest you do is to figure out the default path CMD starts out in (appears to be the equivalent of):

System.Environment.GetFolderPath(Environment.SpecialFolder.Personal)

You can use that to simulate the same functionality.

If you wish to know where CMD checks for applications and so forth, see the environment variables on your system, more specifically the "PATH" environment variable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文