我已经尝试了几个小时来弄清楚如何做到这一点,但我有一个python脚本,它被制作成一个exe,所以它作为一个控制台应用程序我试图用WPF编写一个GUI包装器我将它设置为使用命令参数执行exe的位置,但我想从控制台捕获输出并将其显示在文本框中,我无法弄明白。我已经尝试了多个代码片段,但它不执行任何操作,在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;
}
}
}
答案 0 :(得分:0)
如果我理解正确,那么你希望你的WPF应用程序在python可执行文件运行时不断更新TextBox
的内容吗?
我已经删除了你的代码并使用了Windows命令ping -t 127.0.0.1 -w 10000
,它每秒生成一个新行来测试你的代码。在我的机器上,您的代码按预期工作:WPF文本框中的输出每秒更新一次。
如果在下面的代码中将ping
命令替换为python可执行文件,会发生什么?你的python脚本是否在每一行之后输出换行符(如Process.OutputDataReceived Event中所述)?
<强> MainWindow.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();
}));
}
}
}
<强> MainWindow.xaml 强>
<Window x:Class="SO_Continous_Process_Output.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBox Name="tb_outputtext" Text="{Binding ProcessOutput}"></TextBox>
</Grid>
</Window>
Python脚本
我编写了一个python脚本来测试输出是否有效,我必须设置flush=True
才能使其正常工作。
import time
while True:
print('hi!', flush=True)
time.sleep(1)