繁体   English   中英

“Console”,“cmd.exe”,“shell”之间的区别?

[英]Difference among “Console”, “cmd.exe”, “shell”?

我不太确定控制台(在“Windows控制台应用程序”),cmd.exe,shell之间的区别。

  • 我知道cmd.exe在运行时是一个独立的进程,是cmd.exe == shell吗? 那么shell只是一个过程?
  • 是console == cmd.exe?
  • MSDN说ProcessStartInfo.UseShellExecute == True表示在启动进程时使用shell,是否意味着进程启动与运行cmd.exe一样,并从该命令提示符运行程序? 这样做有什么意义? 以这种方式启动的流程是否有自己的控制台?

提前致谢。

- MSDN说ProcessStartInfo.UseShellExecute == True表示在启动进程时使用shell,这是否意味着进程启动与运行cmd.exe一样,并从该命令提示符运行程序? 这样做有什么意义? 以这种方式启动的流程是否有自己的控制台?

实际上它的工作原理如下:

  • 如果UseShellExecute为false,则将使用CreateProcess API启动应用程序; 此API允许您指定许多启动选项,其中有可能重定向stdin / stdout / stderr,但只会启动可执行文件。 如果您尝试使用CreateProcess启动文件(例如word文档),它将失败,因为word文档不是可执行文件。
  • 如果UseShellExecute为true,则使用ShellExecuteEx API启动该进程; 此功能是Windows资源管理器(“ ”,至少在微软的术语)使用,当你双击文件夹中的文件相同的功能; 它的主要优点是它“知道”如何启动文档(用相关程序打开它们),它知道shell文件夹,...因为它使用了很多shell工具。 然而它有一些主要的缺点:与裸CreateProcess相比,它相当重量级(因为它必须执行大量的额外工作),如果文件关联/ shell扩展/ ...出现问题,它甚至无法打开可执行文件无法重定向stdin / stdout / stderr。 从理论上说这不可能:毕竟ShellExecuteEx内部调用CreateProcess; 问题是它没有公开这个功能。

因此,创建流程的两种方法实际上是完全不同的; 对于扁平化它们,Process类做得很好,但是使用ShellExecuteEx函数绝对无法再现的功能是IO流重定向,因为ShellExecuteEx函数无法使用它,并且只能在进程启动时通过CreateProcess启用它。

启动程序使用控制台是另一个问题。 控制台在CreateProcess中分配/重用(实际上是IIRC,它与windows PE加载器有关,它检查PE头中所需的子系统); 控制台创建/重用的规则在此处指定。

如果启动的应用程序是GUI应用程序,则根本不会创建任何控制台; 另一方面,如果启动控制台应用程序,它将重用其父进程的控制台,除非它在CreateProcess中指定调用CREATE_NEW_CONSOLE标志。 默认情况下不指定此标志,但我不确定ShellExecuteEx对控制台应用程序的作用,我手头没有Windows框来检查。 我会将此作为练习留给读者。 :P


其他答案

嗨,Matteo,另一个问题。 如果我创建一个新进程作为一个没有附加控制台的分离进程。 现在流程的标准在哪里? 流程的输出在哪里? 进程的标准输出是否与控制台的输出不同?

我不清楚你的意思。 当您使用CreateProcess / ShellExecuteEx启动新进程时,控制台将根据需要进行分配,即如果exe是控制台可执行文件(如PE标头中所指定),则Windows会为其提供一个控制台(即新控制台或父级控制台)根据我上面指定的规则); 如果exe是GUI应用程序,则不会为其分配控制台。

IIRC,对于GUI应用程序,stdout / stdin / stderr只是位桶,即它们没有任何用处,所有IO都被丢弃了; 顺便说一下, 没有什么能阻止 GUI应用程序分配控制台并将其自己的std *流重定向到它。

请记住,控制台,Windows标准流和CRT标准流是三个独立的事情。 控制台只是一个界面,对于控制台应用程序,它默认方便地绑定到Windows标准流。

Windows std流是在CreateProcess中指定stdin / stdout / stderr重定向时重定向的流; 你可以把手,将其与GetStdHandle功能,并与他们重定向SetStdHandle

最后,CRT stdin / stdout / stderr是另一个抽象,由C运行时库构建; 它们默认绑定到Windows标准流。

所有这些通常无缝地工作,你甚至不必担心Windows标准流和CRT流之间的差异; 但是,当您开始考虑流重定向时,这种差异变得很重要。

如果进程的stdout流与控制台的输出不同,那么Shell会为我们绑定这两个流。 是否将进程的输出从process.stdout复制到console.output? 这样有效吗?

shell不参与此过程,是执行管道的内核,遵循CreateProcess中使用的指令(或随后使用其他API从新进程内部进行修改)。 对于您的性能问题,使用这样的分层结构,这是唯一的方法; 而且,复制部分(如果它真的是副本,我怀疑整个事情只是传递指针的问题)是过程中最快的部分,真正的瓶颈是控制台窗口绘制/滚动/等等。 事实上,如果您想运行一个控制台应用程序让它以全速生成数据,您通常会将其标准输出重定向到文件或通过管道。

非常感谢。 Matteo Italia。 你是一个很好的问题。 :d

谢谢。 :)

我所知道的:
Shell:操作系统的接口,最终是内核。 这包括explorer.exe和cmd.exe
控制台:您实例化Win32控制台。 这是输出Console.WriteLine的窗口
cmd.exe:windows命令行解释器。 它实例化Win32控制台

更多阅读:
http://en.wikipedia.org/wiki/Win32_console [win32控制台,如果不需要图形用户界面,则使用的控制台]

暂无
暂无

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

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