【问题标题】:Difference among "Console", "cmd.exe", "shell"?“控制台”、“cmd.exe”、“shell”之间的区别?
【发布时间】:2010-02-26 06:24:40
【问题描述】:

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

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

提前致谢。

【问题讨论】:

    标签: c# windows


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

    其实是这样的:

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

    所以,这两种创建流程的方法真的很不一样; Process 类在展平它们方面做得很好,但是绝对不能用 ShellExecuteEx 函数重现的一个特性是 IO 流重定向,因为它不是由 ShellExecuteEx 函数提供的,它只能在进程启动时通过 CreateProcess 启用。

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

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


    其他答案

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

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

    IIRC,对于 GUI 应用程序,stdout/stdin/stderr 只是位桶,即它们没有指向任何有用的东西,并且对它们的所有 IO 都被丢弃;顺便说一句,nothing stops 一个 GUI 应用程序分配了一个控制台并将它自己的 std* 流重定向到它。

    请记住,控制台、Windows 标准流和 CRT 标准流是三个独立的东西。控制台只是一个接口,默认情况下,控制台应用程序方便地绑定到 Windows 标准流。

    Windows std 流是在 CreateProcess 中指定 stdin/stdout/stderr 重定向时被重定向的流;您可以使用GetStdHandle 函数获取它们的句柄,并使用SetStdHandle 重定向它们。

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

    所有这些通常都可以无缝运行,您甚至不必担心 Windows std 流和 CRT 流之间的区别;但是,当您开始考虑流重定向时,这种差异就变得很重要。

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

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

    非常感谢。意大利马泰奥。你是一个很好的问题解决者。 :D

    谢谢。 :)

    【讨论】:

    • 非常感谢。意大利马泰奥。你是一个很好的问题解决者。 :D
    • 嗨,Matteo,另一个问题。如果我创建一个新进程作为没有附加控制台的分离进程。现在进程的标准输出在哪里?进程的输出到哪里去了?进程的标准输出与控制台的输出不同吗?
    • 如果进程的标准输出流与控制台的输出不同,Shell 会为我们绑定这两个流。进程的输出是否会从 process.stdout 复制到 console.output?效率高吗?
    • 答案附加到原始答案。
    【解决方案2】:

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

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

    【讨论】:

    • 谢谢,ItzWarty。根据您的回答, explorer.exe 和 cmd.exe 都是 shell。 cmd.exe 使用特殊的“控制台”窗口,explorer.exe 使用“Windows”窗口。所以,问题是,如果我设置 ProcessStartInfo.UseShellExecute==True,将使用哪个 shell? cmd.exe 还是 explorer.exe?
    • 实际上,Explorer.exe 是一个文件管理器,类似于 Dolphin。但是,我多次看到它被称为外壳。当您将 useshellexecute 设置为 false 时,应用程序将不会创建 win32 控制台。相反,您实际上可以窃取应用程序的输出 [所以基本上,应用程序不会打开 win32 控制台。相反,所有像 Console.WriteLine 这样的输出/输入都将发送给您]...否则,如果 useshellexecute 设置为 true,它会创建一个 win32 控制台并在那里输出。并在那里获得输入。
    • Explorer.exe 是一个多用途的应用程序,是的,它是一个文件管理器,但它也是一个外壳,就像在用户登录时运行的根应用程序中一样。Windows 桌面实际上是 explorer.exe,并提供所有的shell功能(主要是启动其他应用程序)。
    • 事实上,如果你杀死它,它会删除开始菜单和其他东西。但是,Windows 对话框仍然会起作用,因为您仍然可以创建窗口
    猜你喜欢
    • 2017-01-16
    • 2011-08-12
    • 1970-01-01
    • 2012-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-14
    • 2021-11-10
    相关资源
    最近更新 更多