如何检查程序是否从控制台运行?

时间:2012-01-25 19:54:20

标签: c++ c winapi

我正在编写一个将一些诊断转储到标准输出的应用程序。

我希望以这种方式运行应用程序:

  • 如果是从独立的命令提示符(通过cmd.exe)运行,或者将标准输出重定向/管道传输到文件,请在完成后立即退出,
  • 否则(如果是从窗口运行并且控制台窗口是自动生成的),那么 另外在退出之前等待按键(让用户在窗口消失之前读取诊断信息)

我如何区分? 我怀疑检查父进程可能是一种方式,但我并没有真正进入WinAPI,因此这个问题。

我在MinGW海湾合作委员会。

5 个答案:

答案 0 :(得分:22)

您可以使用GetConsoleWindowGetWindowThreadProcessIdGetCurrentProcessId方法。

1)首先,您必须使用GetConsoleWindow函数检索控制台窗口的当前句柄。

2)然后你得到控制台窗口句柄的进程所有者。

3)最后,将返回的PID与应用程序的PID进行比较。

检查此示例(VS C ++)

#include "stdafx.h"
#include <iostream>
using namespace std;
#if       _WIN32_WINNT < 0x0500
  #undef  _WIN32_WINNT
  #define _WIN32_WINNT   0x0500
#endif
#include <windows.h>
#include "Wincon.h" 

int _tmain(int argc, _TCHAR* argv[])
{   
    HWND consoleWnd = GetConsoleWindow();
    DWORD dwProcessId;
    GetWindowThreadProcessId(consoleWnd, &dwProcessId);
    if (GetCurrentProcessId()==dwProcessId)
    {
        cout << "I have my own console, press enter to exit" << endl;
        cin.get();
    }
    else
    {
        cout << "This Console is not mine, good bye" << endl;   
    }


    return 0;
}

答案 1 :(得分:4)

我在C#中需要这个。这是翻译:

[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();

[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentProcessId();

[DllImport("user32.dll")]
static extern int GetWindowThreadProcessId(IntPtr hWnd, ref IntPtr ProcessId);

static int Main(string[] args)
{
    IntPtr hConsole = GetConsoleWindow();
    IntPtr hProcessId = IntPtr.Zero;
    GetWindowThreadProcessId(hConsole, ref hProcessId);

    if (GetCurrentProcessId().Equals(hProcessId))
    {
        Console.WriteLine("I have my own console, press any key to exit");
        Console.ReadKey();
    }
    else
        Console.WriteLine("This console is not mine, good bye");

    return 0;
}

答案 2 :(得分:3)

典型的测试是:

if( isatty( STDOUT_FILENO )) {
        /* this is a terminal */
}

答案 3 :(得分:3)

微软的I18N大师Michael Kaplan提供a series of methods on his blog,让你可以检查控制台上的一些东西,包括控制台是否被重定向。

它们是用C#编写的,但移植到C或C ++会非常简单,因为它都是通过调用Win32 API完成的。

答案 4 :(得分:0)

尝试了许多不同的api和调用之后,我发现只有一种可行的方法:

bool isConsole = isatty(fileno(stdin));

无法使用Stdout,因为您可以运行控制台应用程序并使用>log.txt开关将输出重定向到文件。怀疑也可以重定向输入,但是运行控制台应用程序时很少使用该功能。