Gnat无需控制台即可创建流程

时间:2012-07-05 19:26:00

标签: ada gnat

我需要一个可以在后台静默运行的应用程序,但仍然可以与当前用户的桌面进行交互,而且不是服务。

我希望应用程序在不生成stdout控制台的情况下启动。

在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;

这只是从控制台分离进程,它不会删除控制台。找到here

的详细信息

所以我试着跟踪窗口的句柄,然后是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命令行选项无法创建控制台窗口或关闭控制台窗口的方法?

1 个答案:

答案 0 :(得分:3)

控制台窗口实际上不是特定于GNAT的,而是Windows上的更多GCC。

您可以使用-Wl,-subsystem,windows-mwindows使其不会弹出。