0

将写入 Windows 事件日志的 Ada 应用程序?我曾尝试在 Ada 中使用系统调用,但它不起作用这是 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;

它正在使用包 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;
4

2 回答 2

2

我不是微软专家,但在其他操作系统上system()通常声明为:

int system(const char *command);

这与以下内容完全不同:

procedure System_even (EventCreate : String;
                       ID          : Integer;
                       Application : String;
                       Source      : String);

更改您的导入以使配置文件匹配。- 或者更好的是,使用gcc -fdump-ada-spec让您的编译器为您生成正确的 Ada 规范。

于 2018-04-16T18:49:05.267 回答
0

Jacob 已经涵盖了讨论,但我最终在系统调用之上生成了一个快速绑定。我能够使用 GPS 在 Windows 10 中生成应用程序事件来编译和运行它:

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;

主文件

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;

我只测试了几个输入用例,所以它还没有完全测试,但我想给你一个快速绑定的例子。它是使用 GNAT GPL 2017 for windows 编译和测试的

参考

用于 Windows 的 system() api

适用于 Windows 的 EventCreate api

C 中的 Rosetta 代码示例,了解如何执行此操作

于 2018-04-29T21:09:54.727 回答