Inc*_*onk 7 delphi console-application
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';
Run Code Online (Sandbox Code Playgroud)
当然,如果您的软件能够在早期的Windows版本上运行,您应该使用LoadLibrary()而GetProcAddress()不是.
由于您只关心进程句柄的数量是否大于1,因此可以使用非常小的句柄缓冲区来调用它,例如:
var
HandleCount: DWORD;
ProcessHandle: DWORD;
begin
HandleCount := GetConsoleProcessList(@ProcessHandle, 1);
// ...
end;
Run Code Online (Sandbox Code Playgroud)
如果您的句柄数大于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;
Run Code Online (Sandbox Code Playgroud)
这段代码只是为了让你开始,我确信有些角落的情况没有得到妥善处理.
我过去使用过类似下面的东西:
program ConsoleTest;
{$APPTYPE CONSOLE}
uses Windows;
function GetConsoleWindow: HWND; stdcall; external kernel32 name 'GetConsoleWindow';
function IsOwnConsoleWindow: Boolean;
//ONLY POSSIBLE FOR CONSOLE APPS!!!
//If False, we're being called from the console;
//If True, we have our own console (we weren't called from console)
var pPID: DWORD;
begin
GetWindowThreadProcessId (GetConsoleWindow,pPID);
Result:= (pPID = GetCurrentProcessId);
end;
begin
writeln ('Hello ');
if IsOwnConsoleWindow then begin
writeln ('Press enter to close console');
readln;
end;
end.
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2441 次 |
| 最近记录: |