Win32控制台应用程序是否可以检测它是否已从资源管理器运行?

时间:2009-02-04 10:25:01

标签: winapi console

我必须创建一个需要某些参数的控制台应用程序。如果它们丢失或错误,我会打印出错误信息。

现在问题:如果有人通过双击控制台窗口从资源管理器启动程序立即消失。 (但是应用程序对于资源管理器来说并非完全没用,你可以将文件拖到它上面并且它可以工作)

总是等待按键,但如果用户确实从命令行启动它,我不希望这样。

有没有办法区分这些情况?

6 个答案:

答案 0 :(得分:29)

请参阅http://support.microsoft.com/kb/99115,“信息:防止控制台窗口消失”。

这个想法是使用GetConsoleScreenBufferInfo来确定光标没有从最初的0,0位置移动。

来自@tomlogic的代码示例,基于引用的知识库文章:

// call in main() before printing to stdout
// returns TRUE if program is in its own console (cursor at 0,0) or
// FALSE if it was launched from an existing console.
// See http://support.microsoft.com/kb/99115
#include <stdio.h>
#include <windows.h>
int separate_console( void)
{
    CONSOLE_SCREEN_BUFFER_INFO csbi;

    if (!GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE), &csbi))
    {
        printf( "GetConsoleScreenBufferInfo failed: %lu\n", GetLastError());
        return FALSE;
    }

    // if cursor position is (0,0) then we were launched in a separate console
    return ((!csbi.dwCursorPosition.X) && (!csbi.dwCursorPosition.Y));
}

答案 1 :(得分:5)

GetConsoleTitle()

我见过代码执行

if (!GetConsoleTitle(NULL, 0) && GetLastError() == ERROR_SUCCESS) {
    // Console
} else {
    // GUI
}

但是......我发现AttachConsole()更有帮助

在C ++中(我的头脑中,我不是C ++程序员)

if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
    // GUI
} else {
    // Console, and you have a handle to the console that already exists.
}

更有效。另外,如果你发现自己处于一个GUI环境中,并希望尽可能长时间呆在那里,但后来发现了一些灾难性的事情可能会真正使用转储到控制台窗口(你不能被编写一个编辑框)窗口将它批次或附加到NT系统日志并抛出一个MessageBox())然后您可以在此过程中{GUI}方法失败时AllocConsole()

答案 2 :(得分:3)

我相信cmd.exe在启动时设置CMDCMDLINE和CMDEXTVERSION environemntal变量。因此,如果设置了这些,你的程序很可能是从shell开始的。

这不是万无一失的,但它确实存在。

也可以用一些复杂的,可能不可靠的方式确定你的父PID,或者我收集。你可能想看一下。

答案 3 :(得分:1)

我找到了一个更好的解决方案,使用GetConsoleProcessList将附加的进程数获取到当前控制台。 如果只有该进程是附加进程,则该进程存在时将关闭。

我在帖子https://devblogs.microsoft.com/oldnewthing/20160125-00/?p=92922中找到了它 但是它有一个错误(至少在Windows 10中如此),因为文档禁止使用null调用此函数。

我的解决方法是:

DWORD procId;
DWORD count = GetConsoleProcessList(&procId, 1);
if (count < 2) ...

答案 4 :(得分:0)

如何在显示错误消息时等待键击,而不是其他时间?

答案 5 :(得分:0)

这就像一个魅力:

@echo off
for %%x in (%cmdcmdline%) do if /i "%%~x"=="/c" goto nonconsole

:console
<do something>
goto exit

:nonconsole
<do something>
pause

:exit

this thread复制。我也尝试过自己评估%cmdcmdline%,但是引用字符(&#34;)存在问题,如果&#34;%cmdcmdline%&#34; ==&#34;%ComSpec%&#34;从工作中转移[目标] 。