简体   繁体   English

启动外部过程并在完成后设置值

[英]Starting an external process and setting a value after it finishes

I'm working on a WPF app which is set up to always be the topmost window. 我正在使用WPF应用程序,该应用程序始终设置为最顶层的窗口。 I've added a button to this app which launches an external program that allows the user to calibrate the touchscreen monitor our users will be interacting with. 我在此应用程序中添加了一个按钮,该按钮可启动一个外部程序,该程序可让用户校准与用户进行交互的触摸屏显示器。

I've can turn our mainwindow's topmost setting off and launch my app but I need to be able to set our MainWindow.Topmost to true after this external app exits. 我可以关闭主窗口的最顶层设置并启动我的应用程序,但是我需要能够在此外部应用程序退出后将MainWindow.Topmost设置为true。

It's been suggested that I add an event handler when starting the process that can reset topmost when the process ends. 建议在启动过程时添加一个事件处理程序,该事件处理程序可以在过程结束时重置最顶层。 Event Handlers are new to me so I'm not sure how to do this. 事件处理程序对我来说是新手,所以我不确定该怎么做。 Can someone walk me through it? 有人可以引导我通过它吗?

Here's the code I have that currently disables topmost for my main window and launches my application. 这是我当前在我的主窗口中禁用最上面的代码并启动我的应用程序的代码。 There's not much to it so far... 到目前为止还没有太多...

            Application.Current.MainWindow.Topmost = false;
            System.Diagnostics.Process.Start(@"C:\path\to\app.exe");

Many thanks. 非常感谢。

(And I'll be reading up on event handlers and delegates this weekend!) (这个周末我将阅读事件处理程序和代表!)

Create the Process, set EnableRaisingEvents to true and handle the Exited event: 创建流程,将EnableRaisingEvents设置为true并处理Exited事件:

Process p = new Process();
p.StartInfo.FileName = pathToApp;
p.EnableRaisingEvents = true;
p.Exited += OnCalibrationProcessExited;  // hooks up your handler to the Process
p.Start();

// Now .NET will call this method when the process exits
private void OnCalibrationProcessExited(object sender, EventArgs e)
{
  // set Topmost
}

From the comments thread, the Exited event gets raised on a worker thread, so you will need to do use Dispatcher.BeginInvoke to switch over to the UI thread to set Topmost: 从注释线程,在工作线程上引发Exited事件,因此您需要使用Dispatcher.BeginInvoke切换到UI线程来设置Topmost:

private void OnCalibrationProcessExited(object sender, EventArgs e)
{
  Action action = () => { /* set Topmost */ };
  Dispatcher.BeginInvoke(DispatcherPriority.Normal, action);
}

(This assumes the code is in your Window class. If not, you will need to write something like Application.Current.MainWindow.Dispatcher.BeginInvoke(...) instead.) (这假设代码在您的Window类中。如果不是,则需要编写类似Application.Current.MainWindow.Dispatcher.BeginInvoke(...) 。)

Note I have separated creating and configuring the Process object from starting it. 注意我从启动对象开始就将其创建和配置分开。 Although this is more verbose, it is necessary to ensure that all the event handling stuff is in place before the process starts -- otherwise the process could exit before you put the handler in place (unlikely, but theoretically possible!) and your handler would never get called. 尽管这比较冗长,但是有必要在流程开始之前确保所有事件处理内容都到位-否则,在您将处理程序放置到位之前 ,该过程可能会退出(这不太可能,但理论上可能!),并且您的处理程序将永不打电话。

You can wait for the process to exit via Process.WaitForExit : 您可以等待过程通过Process.WaitForExit退出:

Application.Current.MainWindow.Topmost = false;
var process = System.Diagnostics.Process.Start(@"C:\path\to\app.exe");
process.WaitForExit();
Application.Current.MainWindow.Topmost = true;

If you want to provide a timeout value to prevent the process from waiting forever, that is also possible. 如果要提供超时值以防止进程永远等待,那也是可能的。 For example, if you wanted to wait for a maximum of 2 minutes, you could do: 例如,如果您要等待最多2分钟,则可以执行以下操作:

process.WaitForExit(2 * 60000); // 60000ms/minute

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM