Вопрос

I need an application that will run silently in the background, yet still interact with the current user's desktop, and is not a service.

I want the application to start without spawning a stdout console.

In C, it seems to be done using FreeConsole in Kernel32.dll, so I imported the function:

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;

This only detaches the process from the console, it doesn't remove the console. Details about this behavior found here

So I tried to keep track of the handle to the window, and then CloseHandle() it.

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");

This doesn't do anything either. I bet the Get_Console_Handle returns an incorrect handle.

My question is, is there a Gnat command line option to not create a console window, or a way of closing the console window?

Это было полезно?

Решение

The console window is not actually GNAT specific, more GCC on Windows.

You can either use -Wl,-subsystem,windows or -mwindows to make it not pop up.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top