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

Dan*_*ski 35 console winapi

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

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

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

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

Per*_*ner 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));
}
Run Code Online (Sandbox Code Playgroud)


小智 7

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

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

我的解决方案是:

DWORD procId;
DWORD count = GetConsoleProcessList(&procId, 1);
if (count < 2) ...
Run Code Online (Sandbox Code Playgroud)


小智 5

GetConsoleTitle()

我见过执行的代码

if (!GetConsoleTitle(NULL, 0) && GetLastError() == ERROR_SUCCESS) {
    // Console
} else {
    // GUI
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

  • 一些反馈:我希望在使用MinGW/MSYS编译的命令行应用程序中执行此操作.这两种方法都不适合我 - 我无法区分在Windows资源管理器中将文件拖到应用程序上,以及在bash shell中的命令行上执行它. (2认同)