【问题标题】:Gnat create process without console没有控制台的 Gnat 创建进程
【发布时间】:2012-07-05 19:26:00
【问题描述】:

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

我希望应用程序在不产生标准输出控制台的情况下启动。

在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 命令行选项,或关闭控制台窗口的方法?

【问题讨论】:

  • -mwindows 能否在 Windows 上与 GNAT 一起使用?对于*nix,你不需要任何东西,不应该产生控制台窗口。
  • @oenone 我没有在手册页中看到 -mwindows,但我会尝试一下。在 Windows 上,GNAT 会自动将控制台附加到应用程序。
  • @oenone 有效,如果你能回答,我会投票并接受它。
  • 完成。这不是 GNAT 做的,而是 GCC。

标签: ada gnat


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2010-09-08
    • 2015-01-01
    • 1970-01-01
    • 2020-01-26
    • 2015-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-20
    相关资源
    最近更新 更多