2009-02-04 65 views
34

我必须创建一个需要特定参数的控制台应用程序。如果他们缺少或错误,我会打印出一条错误消息。Win32控制台应用程序是否可以检测是否已从资源管理器运行?

现在问题:如果有人通过双击控制台窗口从资源管理器启动程序,则立即消失。 (但该应用程序不是完全没有用的资源管理器,你可以拖动文件到它,它会工作)

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

有什么方法可以区分这些情况吗?

+1

+1!刚刚创建时问了一个类似的Q. – 2013-01-21 10:11:54

回答

27

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

想法是使用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

这相当原始:) 虽然这是一个黑客它正是我所需要的,它是更简单,然后获得PPID。 – 2009-02-05 07:07:14

+0

如果没有参数传递给应用程序,那么您应该只使用这种方法,这样您仍然可以从cmd.exe执行“cls&app filename” – Anders 2009-02-16 02:31:36

3

我相信cmd.exe设置CMDCMDLINE和CMDEXTVERSION environemntal变量时,它启动。所以如果这些设置你的程序最可能是从一个shell启动。

这不是万无一失,但它是一些东西。

也可以用一些令人费解和可能不可靠的方式来确定您的家长PID,或者我可以收集。你可能想看看。

+1

我尝试了环境变量,它们不存在,既不是从cmd.exe运行,也不是从外部运行时。然而,输入`echo%cmdcmdline%`确实会产生一些东西,所以这个变量显然只在cmd.exe本身有效,而不是它的子进程。 – Timwi 2010-08-20 02:10:12

0

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

5

GetConsoleTitle()

我见过的代码执行

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

但是...我ve发现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()之后进行此操作。

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%,但是有一个关于引号字符(“)的问题,如果”%cmdcmdline%“==”%ComSpec%“goto [target]无法正常工作,则会阻止类似之类的内容。

相关问题