在不窃取焦点的情况下启动进程 (C#) [英] Starting a process without stealing focus (C#)

查看:31
本文介绍了在不窃取焦点的情况下启动进程 (C#)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要能够在不窃取焦点的情况下启动进程(控制台和窗口).在 .NET 框架中,我发现这样做的唯一方法是 Microsoft.VisualBasic.Interaction.Shell 和 Microsoft.VisualBasic.AppWinStyle.[Minimized|Normal]NoFocus(映射到传递给 ShellExecute 的 SW_SHOWMINNOACTIVE/SW_SHOWMA).

I need to be able to start processes (both console and windowed) without it stealing focus. The only way within the .NET framework that I found to do this is Microsoft.VisualBasic.Interaction.Shell with Microsoft.VisualBasic.AppWinStyle.[Minimized|Normal]NoFocus (which map to SW_SHOWMINNOACTIVE/SW_SHOWMA being passed through to ShellExecute).

在我的代码的当前版本(它确实窃取焦点)中,我使用 System.Diagnostics.Process,并依赖于提供给我的一些功能,而 Interaction.Shell 方法没有.

In the current version of my code (which does steal focus), I am using System.Diagnostics.Process, and relying on some of the functionality that gives me, which the Interaction.Shell method does not.

2 个问题(一个是严肃的,一个是为了发泄我的挫败感,我真的不希望有一个好的答案)

2 questions (one serious, and one venting my frustration that I don't really expect a good answer to)

1.) 我别无选择,只能自己包装 CreateProcess 或 ShellExecuteEx,还是我错过了其他一些解决方案?我真的希望避免这种情况,因为除了这种疏忽之外,Process 是一个如此完整和有用的包装器,并且会有如此多的功能需要实现、P/Invoke 调用以进行调试,以及各种各样的痛苦.

1.) Am I correct that I have no choice but to wrap CreateProcess or ShellExecuteEx myself, or am I missing some other solution? I was really hoping to avoid this, as Process is such a complete and useful wrapper other than this oversight, and there would be so much functionality to implement, P/Invoke calls to debug, and all sorts of assorted pain.

2.) 为什么 Microsoft 的一个团队会创建这样一个(否则)完整的包装器,然后从 ProcessWindowStyle 中排除一半可能的值,而另一个团队创建了一个类似的包装器,虽然不那么完整,但提供了所有有用的信息窗口样式?

2.) Why would one team at Microsoft create such a (otherwise) complete wrapper, and then exclude half of the possible values from ProcessWindowStyle, while another team created a similar wrapper that was much less complete, but provided all the useful window styles?

推荐答案

VB.Net 团队做了很多工作来简化开发人员有关 Windows 检测的工作,我认为添加对 VB dll 的引用和在您的 C# 程序中使用它.

The VB.Net team has done much more to ease things for the developer regarding instrumentation of windows, and I see no problem adding a reference to a VB dll and use that in your C# program.

这是两个重点不同的团队,仅此而已.如果 Microsoft.VisualBasic.Interaction.Shell 解决了您的问题,您应该不会为它感到难过.

It's two teams with different focus, that's all. And you shouldn't feel bad about using Microsoft.VisualBasic.Interaction.Shell if it solves your issue.

如果不想引用dll,也可以使用Reflector查看实际实现,自己实现代码.

You can also use Reflector to see the actual implementation and implement the code yourself if you don't want to reference the dll.

int pid = Interaction.Shell("notepad.exe", AppWinStyle.NormalFocus);
Process p = Process.GetProcessById(pid);
p.Exited += ((o, e) => Console.WriteLine("Exit"));
p.EnableRaisingEvents = true;
Console.ReadLine();

这里我使用 Shell 方法来启动进程,从 pid 获取进程的句柄,并挂钩事件.您甚至可以执行 p.Kill() 以中止进程.

Here I use the Shell method to kick off the process, get a handle to the process from the pid, and hook on events. You can even do p.Kill() in order to abort the process.

它开始变得有点不合我的口味,但它确实有效.将NEWWINDOW"替换为随机 guid 或其他内容以使其独一无二.

It's starting to become a bit hackish to my taste, but it works. Replace "NEWWINDOW" with a random guid or something to make it unique.

Microsoft.VisualBasic.Interaction.Shell(@"cmd.exe /c ""start cmd.exe /k title NEWWINDOW""", AppWinStyle.NormalFocus);
foreach (var process in Process.GetProcessesByName("cmd"))
{
    if (process.MainWindowTitle.EndsWith("NEWWINDOW"))
    {
        process.Exited += ((o, e) => Console.WriteLine("Exit"));
        process.EnableRaisingEvents = true;
    }
}

这篇关于在不窃取焦点的情况下启动进程 (C#)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆