我需要一个在后台静默运行的应用程序,但仍与当前用户的桌面交互,而不是服务。
我希望应用程序在不产生标准输出控制台的情况下启动。
在 C 中,似乎是在 Kernel32.dll 中使用 FreeConsole 完成的,所以我导入了该函数:
procedure Free_Console
is
use System;
type Shared_Library_Function
is access function
return Interfaces.C.Int;
pragma Convention(Stdcall, Shared_Library_Function);
function To_Shared_Library_Function
is new Ada.Unchecked_Conversion(System.Address, Shared_Library_Function);
function Load_Library(
File_Name : in Interfaces.C.Char_Array)
return System.Address;
pragma Import(Stdcall, Load_Library, "LoadLibrary", "_LoadLibraryA@4");
function Get_Function_Address(
Module : in System.Address;
Function_Name : in Char_Array)
return System.Address;
pragma Import(stdcall, Get_Function_Address, "GetProcAddress", "_GetProcAddress@8");
Library : System.Address := Load_Library(To_C("kernel32.dll"));
Pointer : System.Address := Get_Function_Address(Library, To_C("FreeConsole"));
begin
if Pointer /= System.Null_Address then
declare
Result : Interfaces.C.Int := 1;
begin
Result := To_Shared_Library_Function(Pointer).all;
end;
else
-- TODO Handle Error
null;
end if;
end Free_Console;
这只会将进程与控制台分离,不会删除控制台。在此处找到有关此行为的详细信息
所以我试图跟踪窗口的句柄,然后 CloseHandle() 它。
function Get_Console_Handle
return System.Address
is
use System;
STD_INPUT_HANDLE : constant Interfaces.C.Unsigned_Long := -10;
STD_OUTPUT_HANDLE : constant Interfaces.C.Unsigned_Long := -11;
STD_ERROR_HANDLE : constant Interfaces.C.Unsigned_Long := -12;
type Shared_Library_Function
is access function(
Standard_Handle : Interfaces.C.Unsigned_Long)
return System.Address;
pragma Convention(Stdcall, Shared_Library_Function);
function To_Shared_Library_Function
is new Ada.Unchecked_Conversion(System.Address, Shared_Library_Function);
function Load_Library(
File_Name : in Interfaces.C.Char_Array)
return System.Address;
pragma Import(Stdcall, Load_Library, "LoadLibrary", "_LoadLibraryA@4");
function Get_Function_Address(
Module : in System.Address;
Function_Name : in Char_Array)
return System.Address;
pragma Import(stdcall, Get_Function_Address, "GetProcAddress", "_GetProcAddress@8");
Library : System.Address := Load_Library(To_C("kernel32.dll"));
Pointer : System.Address := Get_Function_Address(Library, To_C("GetStdHandle"));
begin
if Pointer /= System.Null_Address then
return To_Shared_Library_Function(Pointer).all(STD_OUTPUT_HANDLE);
else
return System.Null_Address;
end if;
end Get_Console_Handle;
--winbase.CloseHandle
function Close_Handle(
Object_Handle : in System.Address)
return Interfaces.C.Int;
pragma Import(Stdcall, "CloseHandle");
这也没有任何作用。我敢打赌 Get_Console_Handle 返回的句柄不正确。
我的问题是,是否有不创建控制台窗口的 Gnat 命令行选项,或关闭控制台窗口的方法?