我试图在我的vb.net项目中读取/使用python程序的输出到目前为止我没有得到任何结果。我想看到的是python程序运行(只是首先),并且所有输出都被重定向到文本框中。
我已经看了一些关于这个的其他帖子,但我要么缺少某些东西或者没有理解某些东西,因为我得到的只是空白输出。 公共类Form1
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脚本,我想获得我可以使用的反馈(将错误插入数据库,完成时发送电子邮件等),所以我希望它能够在运行时捕获进程,而不仅仅是最后的数据转储。
非常感谢任何帮助。
答案 0 :(得分:1)
首先要做的事情 - 难怪你不确定你的代码有什么问题,你正在消除所有可能帮助你诊断错误的错误。这是VB.NET中On Error Resume Next
的唯一目的。该非结构化错误处理仅包含 ,以便与VB的.NET版本向后兼容,现在是时候忘记它曾经存在过。您肯定不想在代码中使用它。 (我会说“在代码中你正在调试”,但所有代码都是调试的潜在候选者,忽略错误只是愚蠢。)
无论如何,关于具体问题。我们知道对MsgBox
的调用有效,但是当您开始与表单上的控件进行交互时,它无法正常工作。所以有些东西在那里分崩离析。
事实证明,OutputDataReceived
事件是在完全不同的线程上引发的,与用于创建进程的线程不同,而不是运行应用程序UI的线程。它实际上只是从系统线程池中检索一个线程。
这就是问题所在:你不能在创建这些对象的线程之外的线程上操作UI对象(至少不会跳过一些箍),这正是你的代码试图在这里做的。事实上,你可能会吞下一个例外,这个例外会让你知道这种情况。
简单的解决方法是将Process
类的SynchronizingObject
属性设置为一个UI组件(如表单或要输出的特定控件)。这会强制所有事件处理程序在创建该组件的同一线程上执行。此时,您的代码应该可以正常工作,因为您不会尝试进行任何跨线程的UI访问。 (消息框不容易受此影响,因为任何线程都可以显示消息框。您不是要尝试访问绑定到另一个线程的现有UI对象。)
或者,您可以通过使用委托和BeginInvoke
方法在事件处理程序方法中自己处理编组,但这对我来说似乎是不必要的工作。