控制台程序完成后转换到命令提示符



我正在用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 >> %sn", 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

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

为了能够在普通窗口终端中的cmd.exe调用中运行程序(正如您使用dir命令所做的那样——好吧,dir是cmd.exe的内部,但其他程序(如xcopy.exe(则不是(,你需要将你的程序构建为不同的程序类型(unix filter命令或无窗口控制台程序,我不记得程序类型名称,因为我不是一个经常使用windows的开发人员(,所以标准输入和标准输出(这些都是windows从MS-DOS获得的东西(保留在启动它的程序上,并且您的程序能够在没有任何窗口的情况下运行。

Windows控制台程序与不需要控制台运行的Windows筛选器程序不同。后者与任何其他类似ms-dos的命令(如dir或copy(一样,它们的接口与类似unix的命令更相似。

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

您可以简单地插入行

system( "cmd" );

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

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

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

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

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

遗憾的是,Windows API似乎没有为子进程提供任何官方方式来获取其父进程的进程ID。然而,根据这个页面,可以使用未记录的函数来实现这一点。

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

相关内容

最新更新