如何避免进程从C#应用程序中窃取焦点?

5

我在C#中试图按顺序启动多个进程,但遇到了一些问题。这些进程花费大约30秒左右来完成它们的过程,我不想让它们从任何应用程序中窃取焦点。我尝试了两种方法(以下代码都在循环语句中):

myProcess.StartInfo.UseShellExecute = true;
myProcess.StartInfo.FileName = "References\\InclinacaoHGrid.exe";
myProcess.StartInfo.CreateNoWindow = true;

myProcess.StartInfo.Arguments = i.ToString() + " " + j.ToString() + " " +
                                        valA + " " + valS + " " + valP + " " + pathNodes;
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
myProcess.EnableRaisingEvents = true;
myProcess.Exited += new EventHandler(myProcess_Exited);
myProcess.OutputDataReceived += new DataReceivedEventHandler(myProcess_OutputDataReceived);
myProcess.Start();
myProcess.WaitForExit();

使用Interaction.Shell并设置参数"AppWinStyle.MinimizedNoFocus":

int pid = Interaction.Shell("References\\InclinacaoHGrid.exe " + i.ToString() + " " + j.ToString() + " " +
                                        valA + " " + valS + " " + valP + " " + pathNodes, AppWinStyle.NormalNoFocus,true);

这两种方法对我不起作用,因为进程(或启动和结束进程的操作)会窃取焦点。当我的应用程序运行时,我无法做任何事情。


可能是[启动进程而不窃取焦点(C#)]的重复问题(https://dev59.com/D3I95IYBdhLWcg3w2h56)。 - Doc Brown
2个回答

2

更改:

myProcess.StartInfo.UseShellExecute = true;
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;

Into:

myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

在您的示例中,似乎不需要使用UseShellExecute,因为您直接运行可执行文件,因此在这种情况下不需要shell。
请注意,将UseShellExecute更改为false会产生以下影响:
UseShellExecute为false时,WorkingDirectory属性不用于查找可执行文件。相反,它仅被启动的进程使用,并且仅在新进程的上下文中具有意义。当UseShellExecute为false时,FileName属性必须是可执行文件的完全限定路径。
如果您不想等待进程退出,请不要使用myProcess.WaitForExit();
还可以参见此处以获取有关ProcessWindowStyle枚举和可能值的更多信息。

0

代码

myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

Johannes Kommer 建议的对我不起作用。因为文档说:

要使用 Hidden,UseShellExecute 属性必须为 true。

但我发现 startInfo.CreateNoWindow = true;startInfo.WindowStyle = ProcessWindowStyle.Hidden; 具有相同的效果。


隐藏解决方案

以下是完全隐藏该进程窗口的代码:

var startInfo = new ProcessStartInfo();
startInfo.FileName = "E:\ffmpeg.exe";

startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
startInfo.Arguments = "-i \"E:\\Download\\Video\\Test\\20.mp4\" -ss 00:00:20 -vframes 1 \"E:\\Download\\Video\\Thumbs\\20.png\"";

using (var proc = Process.Start(startInfo))
{
    proc.WaitForExit();
    //Beware, there is case the exe ask for user confirmation
    //But the the Process Windows is hidden, thus user can't choose Y/N
    //Thus the proc never exit.
}

这个

startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;

可以被替换为

startInfo.UseShellExecute = true;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;

当进程的窗口被隐藏时,你的焦点不会被夺走。但是当进程需要你的确认时(例如:覆盖现有文件[Y/N]?),问题就出现了,因为窗口被隐藏了,所以你无法选择[Y/N],从而陷入困境。如果你不喜欢这种情况,请阅读我的最小化解决方案。


最小化解决方案

尽管焦点仍然被窃取,但它已经被最小化,因此不会弹出到您的面前,当它要求确认时,您可以打开它并选择Y。这是最小化的代码:

var startInfo = new ProcessStartInfo();
startInfo.FileName = "E:\ffmpeg.exe";

startInfo.WindowStyle = ProcessWindowStyle.Minimized;
startInfo.Arguments = "-i \"E:\\Download\\Video\\Test\\20.mp4\" -ss 00:00:20 -vframes 1 \"E:\\Download\\Video\\Thumbs\\20.png\"";

using (var proc = Process.Start(startInfo))
{
    proc.WaitForExit();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接