简体   繁体   English

vb.net-将输出重定向到表单文本框

[英]vb.net - redirect output to form textbox

I am trying to read/use the output from a python program in my vb.net project so far I'm not getting any results. 到目前为止,我尝试读取/使用vb.net项目中python程序的输出,但未得到任何结果。 What I'd like to see is the python program run (just by itself first) and all of the output get redirected into a textbox. 我想看到的是python程序运行(仅靠自身运行),所有输出都重定向到文本框中。

I've looked at some other posts about this, but I'm either missing something or not understanding something, as all I'm getting is blank output. 我已经看过其他有关此内容的文章,但是我要么错过了什么,要么不了解什么,因为我得到的只是空白输出。 Public Class Form1 公开课表格1

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim PythonPath = "C:\Python27\"
    Dim strPath As String = Application.StartupPath
    MessageBox.Show(PythonPath & "python.exe  """ & strPath & "\Resources\import_logs.py"" ")

    Dim start_info As New ProcessStartInfo(TextBox1.Text)

    ' Make the process and set its start information.
    Dim process As New Process()
    process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
    process.StartInfo.FileName = PythonPath & "\python.exe"
    process.StartInfo.Arguments = """" & strPath & "\resources\import_logs.py"""""
    process.StartInfo.UseShellExecute = False
    process.StartInfo.CreateNoWindow = True
    process.StartInfo.RedirectStandardOutput = True
    'process.StartInfo.RedirectStandardError = True

    AddHandler process.OutputDataReceived, AddressOf proccess_OutputDataReceived

    process.Start()
    process.BeginOutputReadLine()
End Sub

Public Sub proccess_OutputDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
    On Error Resume Next
    ' output will be in string e.Data
    ' modify TextBox.Text here
    'Server_Logs.Text = e.Data  ` Does not display anything in textbox
    MsgBox(e.Data) 'It works but I want output in text box field
End Sub
End Class

Eventually I'm going to pass arguments to the python script and I'd like to get feedback that I can then use (insert error into a database, email when it's done, etc), so I'd like it to capture the process while running and not just a data dump at the end. 最终,我将把参数传递给python脚本,并希望获得可以使用的反馈(将错误插入数据库,完成后通过电子邮件等),因此,我希望它捕获过程运行时,而不仅仅是结束时的数据转储。

Any help would be much appreciated. 任何帮助将非常感激。

First things first—it's no wonder you aren't sure what's wrong with your code, you're silencing all errors that could possibly help you to diagnose it. 首先是第一件事-难怪您不确定您的代码有什么问题,您正在消除所有可能有助于诊断的错误。 That's the only purpose of On Error Resume Next in VB.NET. 这是VB.NET中“ On Error Resume Next的唯一目的。 That unstructured error handling was included only for backwards compatibility with the pre-.NET versions of VB and it's time to forget that it ever existed. 包括非结构化错误处理仅是为了与VB之前的.NET版本向后兼容,现在是时候忘记它曾经存在了。 You certainly don't want to use it in code. 当然不想在代码中使用它。 (I would say "in code that you're debugging", but all code is a potential candidate for debugging and ignoring errors is just dumb.) (我会说“在您正在调试的代码中”,但是所有代码都是潜在的调试对象,而忽略错误只是愚蠢的事情。)

Anyway, on to the specific problem. 无论如何,针对特定的问题。 We know that the call to MsgBox works, but it doesn't work right when you start interacting with controls on your form. 我们知道对MsgBox的调用有效,但是当您开始与窗体上的控件进行交互时,它无法正常工作。 So something is falling apart there. 因此,某些东西正在分崩离析。

It turns out that the OutputDataReceived event is raised on an entirely different thread, a different one than was used to create the process and a different one than is running your application's UI. 事实证明, OutputDataReceived事件是在完全不同的线程上引发的,该线程与用于创建进程的线程不同,并且与运行应用程序的UI的线程不同。 It actually just retrieves a thread from the system thread pool. 它实际上只是从系统线程池中检索线程。

And that's where the problem lies: you cannot manipulate UI objects on a thread other than the one that created those objects (at least not without jumping through some hoops), which is precisely what your code tries to do here. 这就是问题所在:除了创建线程的对象之外,您不能在线程上操纵UI对象(至少在没有经过一些箍的情况下),这正是您的代码在这里试图做的。 In fact, you're probably swallowing an exception that would have rather obtusely informed you of this situation. 实际上,您可能正在吞下一个异常情况,该异常情况会以令人费解的方式告知您这种情况。

The simple fix is to set the SynchronizingObject property of the Process class to one of your UI components (like the form, or the specific control you want to output to). 简单的解决方法是将Process类的SynchronizingObject属性设置为您的UI组件之一(例如窗体或您要输出到的特定控件)。 This forces all event handlers to execute on the same thread that created that component. 这将强制所有事件处理程序在创建该组件的同一线程上执行。 At that point, your code should work fine, because you're not trying to do any cross-thread UI access. 到那时,您的代码应该可以正常工作,因为您没有尝试进行任何跨线程UI访问。 (Message boxes are not vulnerable to this because any thread can display a message box. You're not trying to access an existing UI object that is bound to another thread.) (消息框不容易受到此攻击,因为任何线程都可以显示消息框。您并不是要访问绑定到另一个线程的现有UI对象。)

Alternatively, you could handle the marshalling yourself in the event handler method through the use of delegates and the BeginInvoke method, but this seems like unnecessary work to me. 或者,您可以通过使用委托和BeginInvoke方法来处理事件处理程序方法中的编组,但这对我来说似乎是不必要的工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM