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

时间:2011-11-17 12:40:23

标签: c# process focus

我在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);

这两种方法对我不起作用,因为过程(或开始和结束过程的动作)正在从任何应用程序中窃取焦点。我的应用程序运行时无法执行任何操作。

2 个答案:

答案 0 :(得分:2)

变化:

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

分为:

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

您的示例中似乎不需要UseShellExecute,因为您直接运行可执行文件,因此在这种情况下不需要shell。

但请注意,将UseShellExecute更改为false会产生以下影响:

  

当UseShellExecute为false时,不是WorkingDirectory属性   用于查找可执行文件。相反,它仅由进程使用   这是开始的,只有在新的背景下才有意义   处理。当UseShellExecute为false时,FileName属性必须为   可执行文件的完全限定路径。

除非你真的想等待进程退出,否则不要使用myProcess.WaitForExit();

  

WaitForExit()重载用于使当前线程等待   直到相关的进程终止。这个方法指示   处理组件为进程等待无限长的时间   和事件处理程序退出。这可能导致应用程序停止   响应。

有关ProcessWindowStyle枚举和可能值的详细信息,另请参阅this

答案 1 :(得分:0)

代码

myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
Johannes Kommer suggested这样的

不适用于我。原因the doc说:

  

要使用“隐藏”,UseShellExecute属性必须为true。

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


隐藏解决方案

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

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.
}

The

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();
}