hvordan man skriver i Windows-logfiler med Ada-sprog?

Indlæg af Hanne Mølgaard Plasc

Problem



en Ada-applikation, som vil skrive ind til Windows-logfiler?
Jeg har forsøgt at bruge systemopkald i Ada, men det virker ikke
dette er main.adb


with System;

with Interfaces.C;
use Interfaces.C;

with Ada.Text\_IO;
use Ada.Text\_IO;

with Ada.Integer\_Text\_IO;
use Ada.Integer\_Text\_IO;

with c\_interface;
use c\_interface;



with Interfaces.C.Strings;
use Interfaces.C.Strings;

with Ada.Strings.Unbounded; 
use Ada.Strings.Unbounded;

with Ada.Strings.Unbounded.Text\_IO; 
use Ada.Strings.Unbounded.Text\_IO;


procedure main is

begin

   System\_even("error",888,"Demo","this is serious");
   --Put\_Line("hello");
   delay 2.0;

end main;


og det bruger søjle c\_interface.ads


with Interfaces.C;
use Interfaces.C;

with Interfaces.C.Strings;
use Interfaces.C.Strings;

package c\_interface is use Interfaces;

   procedure System\_even (EventCreate : String;
                          ID          : Integer;
                          Application : String;
                          Source : String);

private
   pragma Import (C, System\_even,"system");

end c\_interface;

Bedste reference


Jeg er ikke en Microsoft-ekspert, men på andre operativsystemer system() er oftest erklæret som:


int system(const char *command);


Det er på ingen måde det samme som:


procedure System\_even (EventCreate : String;
                       ID          : Integer;
                       Application : String;
                       Source      : String);


Skift din import, så profilerne matcher. - Eller endnu bedre, brug gcc -fdump-ada-spec for at få din compiler til at generere den korrekte Ada-specifikation for dig.

Andre referencer 1


Jacob dækkede allerede diskussionen, men jeg endte med at skabe en hurtig binding oven på systemopkaldet. Jeg kunne generere applikationshændelser i Windows 10 ved hjælp af GPS for at kompilere og køre det:


Windows\_Event\_Log.ads


package Windows\_Event\_Log is

   type Event\_Type is
      (Error,
       Warning,
       Information,
       Success\_Audit,
       Failure\_Audit);

   type Event\_Category is
      (Application,
       System);

   -- Calls command
   procedure Event\_Create
      (Type\_Of\_Event : Event\_Type;
       ID            : Positive;
       Category      : Event\_Category;
       Source        : String;
       Message       : String);

   -- For Debug
   function Make\_Event\_String
      (Type\_Of\_Event : Event\_Type;
       ID            : Positive;
       Category      : Event\_Category;
       Source        : String;
       Message       : String)
       return String;

end Windows\_Event\_Log;


Windows\_Event\_Log.adb


with Interfaces.C.Strings;
with Ada.Characters.Latin\_1;
with Ada.Containers.Indefinite\_Holders;

package body Windows\_Event\_Log is

   package String\_Holders is new Ada.Containers.Indefinite\_Holders(String);

   -- Conversion arrays
   Type\_String : constant array(Event\_Type) of String\_Holders.Holder :=
      (Error         => String\_Holders.To\_Holder("ERROR"),
       Warning       => String\_Holders.To\_Holder("WARNING"),
       Information   => String\_Holders.To\_Holder("INFORMATION"),
       Success\_Audit => String\_Holders.To\_Holder("SUCCESSAUDIT"),
       Failure\_Audit => String\_Holders.To\_Holder("FAILUREAUDIT"));

   Category\_String : constant array(Event\_Category) of String\_Holders.Holder :=
      (Application => String\_Holders.To\_Holder("APPLICATION"),
       System      => String\_Holders.To\_Holder("SYSTEM"));

   function Make\_Event\_String
      (Type\_Of\_Event : Event\_Type;
       ID            : Positive;
       Category      : Event\_Category;
       Source        : String;
       Message       : String)
       return String
   is begin
      return
         "EventCreate /t "
         & Type\_String(Type\_Of\_Event).Element
         & " /id "
         & Positive'Image(ID)
         & " /l "
         & Category\_String(Category).Element
         & " /so "
         & Source
         & " /d """
         & Message
         & """ >nul 2>&1";              -- Suppress output and error
   end Make\_Event\_String;

   -- Thin binding to the system call
   function System(Str : Interfaces.C.Strings.chars\_ptr) return Interfaces.C.int
      with
         Import,
         Convention => C,
         External\_Name => "system";

   procedure Event\_Create
      (Type\_Of\_Event : Event\_Type;
       ID            : Positive;
       Category      : Event\_Category;
       Source        : String;
       Message       : String)
   is
      Event\_String : String := Make\_Event\_String
         (Type\_Of\_Event => Type\_Of\_Event,
          ID            => ID,
          Category      => Category,
          Source        => Source,
          Message       => Message)
         & Ada.Characters.Latin\_1.NUL; -- needed for C strings

      Event\_Chars\_Ptr : Interfaces.C.Strings.chars\_ptr :=
         Interfaces.C.Strings.New\_String(Event\_String);  --allocates memory

      -- This line actually makes the system call
      Result : Interfaces.C.int := System(Event\_Chars\_Ptr);
   begin

      -- Free the allocated memory from New\_String
      Interfaces.C.Strings.Free(Event\_Chars\_Ptr);
   end;

end Windows\_Event\_Log;


main.adb


with Windows\_Event\_Log;
with Ada.Text\_IO; use Ada.Text\_IO;

procedure Main is

   Event\_Type : Windows\_Event\_Log.Event\_Type := Windows\_Event\_Log.Warning;
   ID         : Positive := 458;
   Category   : Windows\_Event\_Log.Event\_Category := Windows\_Event\_Log.Application;
   Source     : String   := "SomeString";
   Message    : String   := "This is another joke";

begin
   -- Debug print
   Put\_Line
      ("Generated Command => "
       & Windows\_Event\_Log.Make\_Event\_String
          (Type\_Of\_Event => Event\_Type,
           ID            => ID,
           Category      => Category,
           Source        => Source,
           Message       => Message));

   -- Actual Command Sent
   Windows\_Event\_Log.Event\_Create
      (Type\_Of\_Event => Event\_Type,
       ID            => ID,
       Category      => Category,
       Source        => Source,
       Message       => Message);
end Main;


Jeg har kun testet et par af indgangssagerne, så det er langt fra fuldt testet, men jeg ville gerne give dig et eksempel på at gøre en hurtig binding til det. Den blev udarbejdet og testet ved hjælp af GNAT GPL 2017 til Windows


Referencer


system () api til Windows [10]


EventCreate api for Windows [11]


Rosetta Code Eksempel i C for at gøre det [12]