如何判断Delphi应用程序是否“拥有”其控制台?

Delphi控制台应用程序可以从现有控制台窗口的命令行运行,可以通过双击其图标来运行它.在后一种情况下,它将创建自己的控制台窗口,并在应用程序终止后关闭它.

如何判断我的控制台应用程序是否已创建自己的窗口?

我想检测到这一点,以便我可以显示“按Enter键关闭窗口”这样的消息,让用户阅读窗口关闭显示内容.显然,如果从命令行运行应用程序,那么这样做是不合适的.

我正在使用Delphi 2010,以防万一.

解决方法

你基本上有两件事要测试:

>应用程序控制台是否在进程之间共享?如果使用cmd.exe运行控制台应用程序,它将认共享控制台,因此您无需显示“按Enter键关闭窗口”消息.
>输出是否重定向文件?如果是这样,也没有必要显示消息.

对于第一个,有一个简单的解决方案,形式为GetConsoleProcessList() Windows API函数.不幸的是,它仅适用于Windows XP及更高版本,但也许这对你来说已经足够了.它不在Delphi 2009 Windows单元中,因此您必须自己导入它:

function GetConsoleProcessList(lpdwProcessList: PDWORD;
  dwProcessCount: DWORD): DWORD; stdcall; external 'kernel32.dll';

当然,如果您的软件能够在早期的Windows版本上运行,则应使用LoadLibrary()和GetProcAddress().

由于您只关心进程句柄的数量是否大于1,因此可以使用非常小的句柄缓冲区来调用它,例如:

var
  HandleCount: DWORD;
  ProcessHandle: DWORD;
begin
  HandleCount := GetConsoleProcessList(@ProcessHandle,1);
  // ...
end;

如果您的句柄数大于1,则您有其他进程保持控制台处于打开状态,因此您可以跳过显示该消息.

您可以使用GetFileInformationByHandle() Windows API函数来检查控制台输出句柄是否引用了真实文件

var
  StdOutHandle: THandle;
  IsNotRedirected: boolean;
  FileInfo: TByHandleFileinformation;
begin
  StdOutHandle := GetStdHandle(STD_OUTPUT_HANDLE);
  IsNotRedirected := not GetFileinformationByHandle(StdOutHandle,FileInfo)
    and (GetLastError = ERROR_INVALID_HANDLE);
  // ...
end;

这段代码只是为了让你开始,我确信有些角落的情况没有得到妥善处理.

相关文章

 从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都...
  从网上看到《Delphi API HOOK完全说明》这篇文章,基本上...
ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c+&#x...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的...