【问题标题】:Transition to command prompt once my console program finishes?控制台程序完成后转换到命令提示符?
【发布时间】:2021-09-12 01:31:55
【问题描述】:

我正在用 C 和 C++ 编写一些使用 Windows 控制台的可执行文件。

我试图让控制台在我的程序逻辑完成后不关闭......但不仅仅是暂停或等待,我希望它本身成为一个 cmd.exe 命令行控制台,准备好接受新的提示。

基本上我希望通过双击或拖放运行我的程序的行为等同于点击winkey + r 并运行:

cmd /k "program.exe [list of drag+drop files if any]"

(如果从命令行本身运行,则不会打开新控制台。)

这可能吗?

编辑


我一直在对此进行修改,并找到了一个似乎可行的解决方案:

std::getenv("PROMPT") 将在不从命令行运行时返回0(我认为无论如何,不​​确定这是否适用于所有情况),因此可以根据可执行文件的运行方式来分叉逻辑。

在我有限的实验中,以下代码至少对我有用。如果它是从资源管理器中运行的,它会使用它的第一个实例来调用带有参数的 cmd.exe,让那个实例使用原始参数再次调用我们的程序。

int main(int argc, char * argv[]) {
    // checks if we're in the explorer window, if so delegates to a new instance
    if (std::getenv("PROMPT") == NULL) {
        printf("Starting from explorer...\n");
        std::string str("cmd /Q /k \"");
        for (uint32 n = 0; n < argc; ++n) {
            str.append("\"");
            str.append(argv[n]);
            str.append("\"");
            if(n < argc-1)
                str.append(" ");
        }
        str.append("\"\n");
        system(str.c_str());
        return 0;
    }

    // actual code we want to run 
    uint32 fileCount = 0;
    for (uint32 n = 0; n < argc - 1; ++n) {
        fileCount++;
        printf("file %02u >> %s\n", n, argv[n+1]);
    }
    if (fileCount == 0) {
        printf("No inputs...\n");
    }
    return 0;
}

所以我猜从概念上讲,它看起来像这样。

____stays open_______________________   __closes when finished___
program.exe [paramList] ---> cmd.exe -+-> program.exe [paramList]
                                      |
                                      +-> any subsequent commands
                                      |
                                     etc

【问题讨论】:

  • 我很想知道是否有人对此有正确的答案。我怀疑答案实际上是 no - 实现这一点的预期方法是执行 cmd /k 逻辑的包装应用程序。
  • 你可以有一些类似于你的“程序”的东西实际上是一个调用实际.exe的批处理脚本。并使用 stackoverflow.com/a/36663349/4442671 之类的东西来根据调用的位置正确运行。
  • 抱歉,std::getenv() 不是 C,而是 C++。如果您正在编写 C++ 代码,最好不要使用不鼓励使用的 C 函数,例如 printf(),如果您的问题与 C 语言相关,那么您最好不要使用命名空间(它们在 C 中不存在)请,澄清并且不要混合两种语言,否则你最终会以一个不可移植、不可维护的程序结束。当然,充分标记您的问题,因为它被标记为 C 和 C++(但您的代码仅是 C++,因为您在程序中使用命名空间)

标签: c++ c windows console


【解决方案1】:

你可以简单地插入行

system( "cmd" );

在你的程序结束时,它将在你的程序完成执行后调用命令提示符。

但是,这可能无法满足您的以下要求:

(如果从命令行本身运行,则不会打开新控制台。)

虽然使用system( "cmd" ); 不会打开新的控制台窗口(它将使用现有的),但它会创建一个新进程cmd.exe,这意味着如果您的程序是由cmd.exe 调用。此外,如果原来的 cmd.exe 进程是由您自己的程序调用的,那么您现在将有 2 个进程运行您的程序。如果您现在再次从这个新的命令提示符调用您的程序,您现在将有 3 个cmd.exe 进程和 3 个运行您的程序的进程。这可能会很快变得丑陋,尤其是当您反复从批处理文件调用程序时。

为了防止这种情况,您的程序可以尝试以某种方式检测其父进程是否已经是cmd.exe,如果是,它应该正常退出而不是再次调用cmd.exe

不幸的是,Windows API 似乎没有为子进程提供任何官方方法来获取其父进程的进程 ID。但是,根据this page,可以使用未记录的函数来完成此操作。

不过,通常不建议使用未记录的函数。因此,如果您总是从命令提示符调用您的程序可能会更好,以便它可以简单地正常退出。

【讨论】:

    【解决方案2】:

    在我看来,您已将您的程序链接为 Windows 控制台 程序,因此当您运行它时,它总是会打开一个控制台终端。在这种情况下,您的程序会显示它输出的信息在控制台中(好像标准输出已被重定向到打开的窗口)这意味着您不能将其用作 UNIX 过滤器,如 dir 或 copy命令。 (实际上,您不在 unix 系统中,因此控制台是使用链接到您的程序的特殊 Windows 库来模拟的)。

    为了能够在普通窗口终端中 cmd.exe 调用中运行您的程序(正如您使用 dir 命令所做的那样——嗯,dir 是 cmd.exe 的内部,但其他,就像 xcopy.exe 不是),您需要将您的程序构建为不同的程序类型(unix 过滤器命令或无窗口控制台程序,我不记得程序类型名称,因为我不是频繁的 Windows 开发人员) 所以标准输入和标准输出(这些是 Windows 从 MS-DOS 中阻止的东西)被保留在启动它的程序上,并且您的程序能够在没有窗口的情况下运行。

    Windows 控制台程序与不需要控制台即可运行的 Windows 过滤器程序不同。后者就像任何其他类似 ms-dos 的命令(如 dir 或 copy),并且它们的界面更类似于类似 unix 的对应物。

    如果你这样做,你将能够在另一个窗口中从 cmd 运行你的程序,并且它不会创建一个 Windows 终端控制台来显示你的程序输出。

    【讨论】:

      猜你喜欢
      • 2016-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-01
      • 1970-01-01
      • 2020-03-03
      • 1970-01-01
      • 2017-10-11
      相关资源
      最近更新 更多