为什么会启动 conhost.exe?
我正在从 .Net 启动 Java 进程(“java.exe”)。使用 Process.Start()。除了 Java 进程之外,还会以某种方式启动另一个名为 conhost.exe 的进程。我将 Java 进程的输出重定向到 .Net 进程。
- 为什么 conhost.exe 甚至会启动?
- 如何从 .Net 跟踪它?我想跟踪这个特定的实例,因为我不是直接创建它(而是 Java.exe 进程),所以我没有它的 PID。
I'm launching a Java process ("java.exe") from .Net. using Process.Start(). In addition to the Java process, another process called conhost.exe is launched somehow. I am redirecting the output from the Java process to the .Net process.
- Why is conhost.exe even launched?
- How do I track it from .Net? I want to track this specific instance, and since I'm not creating it directly (but rather the Java.exe process), I don't have it's PID.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
在早期版本的 Windows 中,控制台窗口托管在 CSRSS 中,这是一个具有高度特权、受信任的系统关键进程。在 Win7 上,控制台窗口现在托管在 conhost.exe 中,该程序的权限较少。这样做可能是为了安全和安全。可靠性原因 - 控制台系统中的安全问题不会危及整个盒子,控制台代码崩溃也不会导致系统蓝屏。
In earlier versions of Windows, console windows were hosted in CSRSS, which is a highly privileged, trusted, system critical process. On Win7, it appears that console windows are now hosted in conhost.exe, which has less rights. This was probably done for security & reliability reasons - a security issue in the console system won't compromise the entire box, and a crash in the console code won't blue screen the system.
抱歉,破坏了这样一个旧线程,但我认为这个问题很有趣并且值得回答。
为什么会启动 conhost.exe?
正如其他帖子中所解释的,这现在是托管控制台应用程序的默认方式。更多详细信息可以在另一个答案链接的文章中找到:什么是 conhost.exe 以及它为何运行?
如何从 .Net 跟踪它?我想跟踪这个特定的实例,并且由于我不是直接创建它(而是 Java.exe 进程),所以我没有它的 PID。
正如其他人指出的那样,应该没有理由“跟踪”conhost 进程。话虽如此,有一种方法可以从 java.exe 进程 ID 中获取 conhost 进程 ID。您所要做的就是枚举系统中每个 conhost 进程拥有的所有进程句柄,如果这些句柄之一指向与您的 jama.exe 具有相同 Id 的进程,则这将是您所在的 conhost.exe 句柄后。将其隐藏为进程 ID,您将获得 conhost.exe 的 PID
所以这是理论。在实践中如何实现这一目标?有一篇优秀文章显示了一些执行非常相似操作的代码。我对此代码进行了一些修改以适应我们手头的任务。最后,您使用
Utility.GetConhostIdByProcessId
静态函数并将 java.exe 的 PID 传递给它,它将返回相关 conhost.exe 的 PID。对该方法的测试调用可以在下面示例中的 Main 函数。现在是代码:
请注意,我仅在 x64 Windows 7 上使用 x86 和 x64 编译选项测试了此代码。我用 VS2010 for .NET 4 编译了它。这段代码可读性较差,我不能保证它可以在所有相关平台和体系结构上工作。然而它在这里工作(tm)并且对于这个深奥的任务很有用。
Sorry, for necroing such an old thread, but I thought that the question is interesting and worth an answer.
Why is conhost.exe even launched?
As explained in other posts this is now a default way to host console applications. Further details can be found in the article linked in another answer here: What is conhost.exe and Why Is It Running?
How do I track it from .Net? I want to track this specific instance, and since I'm not creating it directly (but rather the Java.exe process), I don't have it's PID.
As other has noted there should be little reason to "track" the conhost process. Having said that, there is a way to obtain conhost process id from your java.exe process Id. All you have to do is enumerate all the process handles that every conhost process in the system has, and if one of these handles point to a process with the same Id as your jawa.exe, this will be the conhost.exe handle you are after. Covert it to Process Id and you get the PID for conhost.exe
So this is theory. How to achieve this in practice? There an excellent article that shows some code that is doing something very similar. I have modified this code a bit to suit our task at hand. In the end you
Utility.GetConhostIdByProcessId
static function and pass the PID of your java.exe to it, and it will return you the PID of relevant conhost.exe A test call to this method can be found in the Main function in the example below.And now the code:
Note, that I only tested this code on x64 Windows 7 with both x86 and x64 compilation option. I compiled it with VS2010 for .NET 4. This code is less than readable and I can't guaranty that it will work on all relevant platforms and architectures. However it works here (tm) and is useful for this esoteric task.
更新:我猜你可以找到原因关于旧的新事物。添加它可能是为了恢复由于安全原因从 Windows Vista 中删除的某些功能(例如拖放)。
更新前: conhost 似乎会在任何 cmd.exe 打开时启动。这可能是 Windows 7 上的一些新的、未记录的东西。
Update: I guess that you can find the reasoning on the oldnewthing. It was probably added to restore some functionality (like drag and drop) that was removed from Windows Vista due to security reasons.
Before Update: conhost seems to launch on any cmd.exe opening. It's probably some new, undocumented thing on windows 7.
我刚刚写了一篇文章试图解释该过程的目的。它面向普通人,但有很多屏幕截图可以说明。
什么是 conhost.exe以及为什么它运行?
底线是 conhost.exe 位于 CSRSS 进程和 cmd.exe 之间,因此您可以使用拖放来运行它。再次下降。
I just wrote up an article attempting to explain the purpose of the process. It's geared towards regular people, but there's lots of screenshots to illustrate.
What is conhost.exe and Why Is It Running?
The bottom line is that conhost.exe sits between the CSRSS process and cmd.exe, so you can use drag & drop again.
当使用“Process.Start()”启动进程时,可以选择直接创建进程,或者启动“cmd.exe”并让“cmd.exe”处理详细信息。 “UseShellExecute”标志对此进行控制。如果您选择将详细信息保留给“cmd.exe”,这在您想要调用文件并让 shell 运行适当的程序来处理它的情况下很常见,例如通过“运行”一个“.txt”文件,那么在 Win7 上,这实际上会运行“cmd”,它本身运行“conhost”。另一方面,如果您不使用“ShellExecute”,则“Start()”将不会运行“cmd”,并且您将不会间接启动“conhost”。
When one launches a process using 'Process.Start()' one has the option of creating the process directly, or of launching 'cmd.exe' and letting 'cmd.exe' handle the details. The 'UseShellExecute' flag controls this. If you elect to leave the details to 'cmd.exe', which is common in situations where you want to invoke a file and let the shell run the appropriate program to handle it, e.g. by "running" a '.txt' file, then on Win7 this will actually run 'cmd', which itself runs 'conhost'. If, on the other hand, you don't use 'ShellExecute' then 'Start()' won't run 'cmd' and you won't indirectly launch 'conhost'.
坦白说,我对 Java 一无所知,所以我无法帮助你解决 #1 的问题。不过,我可以帮助解决#2。
要使用 .NET 跟踪它,您可以使用 System.Diagnostics。
首先,您必须通过名称“conhost.exe”获取每个进程,启动 Java,然后再次获取所有进程并进行比较。
要获取特定实例,请使用进程 ID:
然后,当您想要终止进程时,运行完全相同的循环,如果进程 ID 未存储在初始循环中,则调用 singleProcess。杀();在它上面。然后,您将保持所有初始 conhost.exe 进程处于活动状态,并且仅终止在程序中启动 Java 和 Java 进程退出之间创建的进程。
To be blatant, I don't know anything about Java, so I can't help you with #1. I can help with #2, though.
To track it with .NET, you can use System.Diagnostics.
First, you have to get each of the processes by the name "conhost.exe", launch Java, then get all the processes again, and compare.
To get the specific instances, use the process ID:
Then when you want to kill the processes, run the exact same loop, and if the process ID was not stored in the initial loop, then call singleProcess.Kill(); on it. Then you will have kept all the initial conhost.exe processes alive, and only kill the ones created between the time you launch Java in your program and the time your Java process exits.
它是一个托管控制台窗口的进程。它是在 Windows 7 (iirc) 中引入的,在旧版本中,该功能是在 csrss.exe 进程的上下文中执行的。
It is a process that hosts the console window. It was introduced in Windows 7 (iirc), in older versions the functionality was executed in the context of the csrss.exe process.
根据 zespri 的回答,我编写了更新的方法。
此代码能够处理长于 16 位的进程 ID。
还修复了一个逻辑错误以及一些内存和句柄泄漏。添加了一些故障安全措施。
我添加了一种方法,用于处理 conhost.exe 有多个关联进程的情况。当控制台程序正在运行并且其父进程为 cmd.exe 时,可能会发生这种情况,但在其他一些情况下,关联的进程甚至不具有子父关系。
非常感谢zespri提供的原始代码,有很多值得学习的地方!
方法更新的更多说明:
对于 WinXP+,最好使用 SYSTEM_EXTENDED_HANDLE_INFORMATION,因为 SYSTEM_HANDLE_INFORMATION 仅返回 16 位长的进程 ID。如果系统的句柄负载很重,那么进程 ID 往往会开始具有高于 65k 的值,例如 8 位十进制数字。上述代码使用的系统调用将简单地屏蔽掉进程 ID 的高位。您可以在 Process Hacker 的源代码中找到 SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX 及其用法。
更新:
我于 2014 年 6 月 27 日添加了针对 64 位代码的重要错误修复。
UNICODE_STRING 结构的打包是错误的,代码试图以某种棘手的方式弥补这一点。虽然在Win7中没有表现出来,但在Win8下崩溃得很好。
其他结构体的 Pack=1 打包也不正确,但意外地没有改变它们的计算布局。
重要的更改部分是:
Based on zespri's answer I wrote updated methods.
This code is able to handle process id-s that are longer than 16-bit.
Also one logic bug was fixed and some memory and handle leaks. Added some failsafety.
I added a method for case when conhost.exe has multiple associated processes. This can happen when there is a console program running and has cmd.exe as its parent process, but also some other cases, where the associated processes are not even in child-parent relationship.
Thanks a lot for zespri for the original code, there is lot to learn from it!
More explanation for the method updates:
For WinXP+ it is better to use SYSTEM_EXTENDED_HANDLE_INFORMATION since SYSTEM_HANDLE_INFORMATION returns only 16-bit long process id-s. If system is heavily loaded with handles then process id-s tend to start having values above 65k, for example 8 decimal digits. The system call that the above code uses would simply mask off the high bits of process id-s. You can find SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX and its usage in Process Hacker's source code.
UPDATE:
I added important bugfixes for 64-bit code on 27.06.2014.
The packing of the UNICODE_STRING struct was wrong and the code tried to compensate for that in some tricky manner. Although it did not manifest in Win7, it crashed nicely under Win8.
The other structs' packing with Pack=1 was incorrect too, but accidentally did not change their computed layout.
The important changed parts were:
这就提出了一个相关的问题:您想要 .NET 应用程序生成的 Java 应用程序的控制台窗口吗?如果没有,您可以执行
javaw
命令而不是java
。我还没有在 Vista 上进行过实验,但它可能会消除conhost.exe
进程。This raises a related question: do you want a console window for the Java application spawned by the .NET app? If not, you can execute the
javaw
command instead ofjava
. I haven't experimented with it on Vista, but it may eliminate theconhost.exe
process.