0

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 スクリプトに引数を渡す予定です。その際に使用できるフィードバックを取得したいので (エラーをデータベースに挿入する、完了時にメールを送信するなど)、プロセスをキャプチャしてもらいたいと考えています。最後にデータダンプだけではありません。

どんな助けでも大歓迎です。

4

1 に答える 1

1

まず最初に、コードの何が問題なのかわからなくても不思議ではありません。コードの診断に役立つ可能性のあるすべてのエラーを黙らせているのです。On Error Resume Nextそれが VB.NETの唯一の目的です。この構造化されていないエラー処理は、VB の .NET 以前のバージョンとの後方互換性のためにのみ含まれていました。コードで使用したくないことは確かです。(「デバッグしているコードで」と言いたいのですが、すべてのコードがデバッグの潜在的な候補であり、エラーを無視するのはばかげています。)

とにかく、特定の問題に進みます。への呼び出しが機能することはわかっていMsgBoxますが、フォーム上のコントロールを操作し始めると正しく機能しません。そこで何かが崩壊している。

このOutputDataReceivedイベントは、プロセスの作成に使用されたスレッドとは異なるスレッド、およびアプリケーションの UI を実行しているスレッドとは異なるスレッドで発生することがわかりました。実際には、システム スレッド プールからスレッドを取得するだけです。

ここに問題があります。これらのオブジェクトを作成したスレッド以外のスレッドで UI オブジェクトを操作することはできません (少なくとも、いくつかのフープをジャンプしない限り)。これはまさに、コードがここで実行しようとしていることです。実際、あなたはおそらく、この状況を鈍感に知らせる例外を飲み込んでいるのでしょう。

簡単な修正はSynchronizingObject、クラスのプロパティをProcessUI コンポーネントの 1 つ (フォームや出力先の特定のコントロールなど) に設定することです。これにより、すべてのイベント ハンドラーが、そのコンポーネントを作成した同じスレッドで実行されるようになります。この時点で、クロススレッド UI アクセスを試みていないため、コードは正常に動作するはずです。(どのスレッドでもメッセージ ボックスを表示できるため、メッセージ ボックスはこれに対して脆弱ではありません。別のスレッドにバインドされている既存の UI オブジェクトにアクセスしようとしているわけではありません。)

または、デリゲートとメソッドを使用して、イベント ハンドラー メソッドでマーシャリングを自分で処理することもできますがBeginInvoke、これは不要な作業のように思えます。

于 2013-03-18T22:27:05.500 に答える