C# WPF应用程序程序捕获Python脚本控制台输出

2024-09-30 14:20:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经花了好几个小时想弄清楚如何做到这一点,但是我有一个python脚本,它被制作成一个exe,所以它可以作为一个控制台应用程序。我正试图用WPF为它编写一个GUI包装器,我把它设置为它执行命令参数的地方,但是我想从控制台捕获输出并显示在文本框和我想不通。我尝试过多个代码片段,但它要么什么都不做,要么在python exe完成后输出,要么锁定GUI直到python exe完成,然后将完成的输出转储到文本框中。在

有人能不能看看能不能帮我?在

public partial class MainWindow : Window


{

    //string output = string.Empty;
    private static StringBuilder output = new StringBuilder();
    private object syncGate = new object();
    private Process process;
    private bool outputChanged;


    public MainWindow()
    {
        InitializeComponent();
    }

    private void RB_Mii_Checked(object sender, RoutedEventArgs e)
    {   
    }

    //If we click the button we copy the bin file to the work directory
    private void btn_SelMiiQR_Click(object sender, RoutedEventArgs e)
    {
        //Copy the encrypted.bin file to the working directory
        OpenFileDialog openFileDialog = new OpenFileDialog();
        openFileDialog.Filter = "Input.bin (*.bin)|*.bin|All files (*.*)|*.*";
        openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        if (openFileDialog.ShowDialog() == true)
        {
            var fileName = openFileDialog.FileName;
            String exePath = System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0].FullyQualifiedName;
            //If the file exists delete the existing file and copy the newone.
            if (System.IO.File.Exists(System.IO.Path.GetDirectoryName(exePath) + "\\App\\" + System.IO.Path.GetFileName(fileName)))
            {
                System.IO.File.Delete(System.IO.Path.GetDirectoryName(exePath) + "\\App\\" + System.IO.Path.GetFileName(fileName));
            }
                System.IO.File.Copy(fileName, System.IO.Path.GetDirectoryName(exePath) + "\\App\\" + System.IO.Path.GetFileName(fileName));
        }

    }

    //If the button was clicked use the input.bin file and attempt to brute force the movable_sedpart1.bin
    private void BTN_MIIBF_Click(object sender, RoutedEventArgs e)
    {
        //If the mfg has input year or no input use it
        if (TB_MFGYR.Text.Length == 0 || TB_MFGYR.Text.Length == 4)
        {
            string DStype = null;
            string MFGYR = null;
            //Grab the Year if it has value
            if (TB_MFGYR.Text.Length == 4)
            {
                 MFGYR = TB_MFGYR.Text;
            }
            else
            {
                MFGYR = null;
            }

            if (RB_N3ds.IsChecked == true)
            {
                DStype = "new";
            }

            else if (RB_O3DS.IsChecked == true)
            {
                DStype = "old";
            }


            //Execute Command with Arguments
            String exePath = System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0].FullyQualifiedName;
            string dir = System.IO.Path.GetDirectoryName(exePath)+"\\App\\";

            //Start the process and export thr console output to the textbox
            CreateProcess(dir + "seedminer_launcher.exe", "Mii " + DStype + " " + MFGYR, dir);


        }
        //Else display Error Message WIP
        else
        {
            tb_outputtext.Text = null;
            tb_outputtext.Text = "MFG Year must have 4 characters or none";
        }
    }

    //Execute a new process
    private void CreateProcess(string fileName, string arguments, string workdir)
    {
        // Process process = new Process();
        process = new Process();
        process.StartInfo.FileName = fileName;
        process.StartInfo.Arguments = arguments;
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.CreateNoWindow = true;
        process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.RedirectStandardError = true;
        process.StartInfo.WorkingDirectory = workdir;
        process.OutputDataReceived += proc_OutputDataReceived;


        process.Start();
        process.BeginOutputReadLine();

    }

    void proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        this.Dispatcher.Invoke((Action)(() =>
        {
            tb_outputtext.Text = tb_outputtext.Text + "\n" + e.Data;
            tb_outputtext.ScrollToEnd();
        }));

    }


    private void ReadData()
    {
        var input = process.StandardOutput;
        int nextChar;
        while ((nextChar = input.Read()) >= 0)
        {
            lock (syncGate)
            {
                output.append((char)nextChar);
                if (!outputChanged)
                {
                    outputChanged = true;
                    var dispatcher = Application.Current.MainWindow.Dispatcher;
                    Dispatcher.BeginInvoke(new Action(OnOutputChanged));
                }
            }
        }
        lock (syncGate)
        {
            process.Dispose();
            process = null;
        }
    }

    private void OnOutputChanged()
    {
        lock (syncGate)
        {
            tb_outputtext.AppendText(output.ToString());
            outputChanged = false;
        }
    }


}

Tags: thetextiotruenewstringifbin
1条回答
网友
1楼 · 发布于 2024-09-30 14:20:08

如果我理解正确,那么您希望您的WPF应用程序在运行python可执行文件时不断更新TextBox上的内容?在

我已经剥离了您的代码,并使用了Windows命令ping -t 127.0.0.1 -w 10000,该命令每秒生成一行新行来测试代码。在我的机器上,您的代码按预期工作:WPF文本框中的输出每秒更新一次。在

如果用下面代码中的python可执行文件替换ping命令,会发生什么情况?您的python脚本是否在每一行后面输出换行符(如Process.OutputDataReceived Event中所述)?在

主窗口.xaml.cs

using System;
using System.Diagnostics;
using System.Windows;

namespace SO_Continous_Process_Output
{
    public partial class MainWindow : Window
    {
        private Process process;

        public MainWindow()
        {
            InitializeComponent();

            CreateProcess("ping", "-t 127.0.0.1 -w 1000", "");
        }

        //Execute a new process
        private void CreateProcess(string fileName, string arguments, string workdir)
        {
            // Process process = new Process();
            process = new Process();
            process.StartInfo.FileName = fileName;
            process.StartInfo.Arguments = arguments;
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.CreateNoWindow = true;
            process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardError = true;
            process.StartInfo.WorkingDirectory = workdir;
            process.OutputDataReceived += proc_OutputDataReceived;

            process.Start();
            process.BeginOutputReadLine();
        }

        void proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            this.Dispatcher.Invoke((Action)(() =>
            {
                tb_outputtext.Text = tb_outputtext.Text + "\n" + e.Data;
                tb_outputtext.ScrollToEnd();
            }));
        }
    }
}

主窗口.xaml

^{pr2}$

更新

Python脚本

我编写了一个python脚本来测试输出是否有效,并且必须设置flush=True才能使其工作。在

import time

while True:
    print('hi!', flush=True)
    time.sleep(1)

相关问题 更多 >