0

我正在尝试在我的 vb.net 项目中读取/使用 python 程序的输出,到目前为止我没有得到任何结果。我想看到的是 python 程序运行(首先自己运行)并且所有输出都被重定向到一个文本框。

我看过其他一些关于这个的帖子,但我要么遗漏了一些东西,要么不理解一些东西,因为我得到的只是空白输出。公开课形式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

最终,我要将参数传递给 python 脚本,并且我想获得我可以使用的反馈(将错误插入数据库,完成后发送电子邮件等),所以我希望它能够捕获过程在运行时,而不仅仅是最后的数据转储。

任何帮助将非常感激。

4

1 回答 1

1

第一件事——难怪你不确定你的代码有什么问题,你正在消除所有可能帮助你诊断它的错误。On Error Resume Next这是VB.NET的唯一目的。包含非结构化错误处理只是为了向后兼容 .NET 之前的 VB 版本,是时候忘记它曾经存在过。您当然不想在代码中使用它。(我会说“在你正在调试的代码中”,但所有代码都是调试的潜在候选者,而忽略错误只是愚蠢的。)

无论如何,关于具体问题。我们知道调用是MsgBox有效的,但是当您开始与表单上的控件进行交互时,它就不能正常工作了。所以有些东西在那里分崩离析。

事实证明,该OutputDataReceived事件是在完全不同的线程上引发的,该线程与用于创建进程的线程不同,也不同于运行应用程序 UI 的线程。它实际上只是从系统线程池中检索一个线程。

这就是问题所在:您不能在创建这些对象的线程之外的线程上操作 UI 对象(至少在不跳过一些圈子的情况下不能),这正是您的代码在这里试图做的。事实上,您可能正在接受一个相当迟钝地通知您这种情况的异常。

简单的解决方法是将类的SynchronizingObject属性设置Process为您的 UI 组件之一(例如表单或要输出到的特定控件)。这会强制所有事件处理程序在创建该组件的同一线程上执行。此时,您的代码应该可以正常工作,因为您没有尝试进行任何跨线程 UI 访问。(消息框不易受此攻击,因为任何线程都可以显示消息框。您不会尝试访问绑定到另一个线程的现有 UI 对象。)

或者,您可以通过使用委托和BeginInvoke方法在事件处理程序方法中自己处理编组,但这对我来说似乎是不必要的工作。

于 2013-03-18T22:27:05.500 回答