我正在寻找一种(相当轻松)的方法来向小型遗留 Delphi 5 应用程序添加一些 Windows 应用程序事件日志支持。我们只是希望它在启动、关闭、无法连接到数据库等时进行记录。

我见过的几个解决方案/组件似乎表明我们需要创建一个资源 DLL,Windows 事件日志查看器在尝试读取我们的“条目”时将链接到该资源 DLL。虽然这看起来并不太繁重,但我想如果/当我们将来进一步开发该应用程序时,还需要记住其他一些事情 - 我们需要使这个 DLL 保持最新。

将来的某个时候,我们希望将应用程序变成服务,可能是用 D2007 编写的。

那么有人可以推荐一个合适的路线来将事件添加到 D5 中的事件日志中吗?我正在寻找具体的'我们用过这个,没问题' 评论而不是 Google 拖网(我可以自己做!) 免费或付费,真的不介意 - 但我将来可以迁移到 D2007 的东西很重要。

有帮助吗?

解决方案 4

感谢的Ĵ的和彼得的反应,我得到了我的代码写入到事件日志,立竿见影。有一点点做,特别是如果你希望你的事件出现“很好”在事件日志中没有有关无法找到描述(如每Ĵ的交)。

我跟着提示此处,以使合适的DLL,并进入其导入注册表,并很快拥有了一切整理出来。

这是所有在Delphi5,按的问题,但我什么也没看见,这让我觉得在D2007它不会也行。

其他提示

概括:使用 Delphi 写入 Windows 事件日志


如果您正在编写 Windows 服务并需要写入本地计算机的 Windows 事件日志,那么您可以调用服务。日志消息 如上所述 这里.

//TMyTestService = class(TService)

procedure TMyTestService.ServiceStart(Sender: TService; var Started: Boolean);
begin
  LogMessage('This is an error.');
  LogMessage('This is another error.', EVENTLOG_ERROR_TYPE);
  LogMessage('This is information.', EVENTLOG_INFORMATION_TYPE);
  LogMessage('This is a warning.', EVENTLOG_WARNING_TYPE);
end;

对于任何其他类型的应用程序,您可以使用 SvcMgr。事件记录器 无证的 如前所述,TService 的帮助程序类用于写入本地计算机的 Windows 事件日志 这里, 这里这里.

uses
  SvcMgr;

procedure TForm1.EventLoggerExampleButtonClick(Sender: TObject);
begin
  with TEventLogger.Create('My Test App Name') do
  begin
    try
      LogMessage('This is an error.');
      LogMessage('This is another error.', EVENTLOG_ERROR_TYPE);
      LogMessage('This is information.', EVENTLOG_INFORMATION_TYPE);
      LogMessage('This is a warning.', EVENTLOG_WARNING_TYPE);
    finally
      Free;
    end;
  end;
end;

您还可以使用 Windows API 报告事件 功能如上所述 这里这里.

我创建了一个简单的类以使其更容易,它是 可以在 GitHub 上找到.

//----------------- EXAMPLE USAGE: ---------------------------------

uses
  EventLog;

procedure TForm1.EventLogExampleButtonClick(Sender: TObject);
begin
  TEventLog.Source := 'My Test App Name';

  TEventLog.WriteError('This is an error.');
  TEventLog.WriteInfo('This is information.');
  TEventLog.WriteWarning('This is a warning.');
end;

//------------------------------------------------------------------


unit EventLog;

interface

type
  TEventLog = class
  private
    class procedure CheckEventLogHandle;
    class procedure Write(AEntryType: Word; AEventId: Cardinal; AMessage: string); static;
  public
    class var Source: string;
    class destructor Destroy;

    class procedure WriteInfo(AMessage: string); static;
    class procedure WriteWarning(AMessage: string); static;
    class procedure WriteError(AMessage: string); static;

    class procedure AddEventSourceToRegistry; static;
  end;

threadvar EventLogHandle: THandle;

implementation

uses Windows, Registry, SysUtils;

class destructor TEventLog.Destroy;
begin
  if EventLogHandle > 0 then
  begin
    DeregisterEventSource(EventLogHandle);
  end;
end;

class procedure TEventLog.WriteInfo(AMessage: string);
begin
  Write(EVENTLOG_INFORMATION_TYPE, 2, AMessage);
end;

class procedure TEventLog.WriteWarning(AMessage: string);
begin
  Write(EVENTLOG_WARNING_TYPE, 3, AMessage);
end;

class procedure TEventLog.WriteError(AMessage: string);
begin
  Write(EVENTLOG_ERROR_TYPE, 4, AMessage);
end;

class procedure TEventLog.CheckEventLogHandle;
begin
  if EventLogHandle = 0 then
  begin
   EventLogHandle := RegisterEventSource(nil, PChar(Source));
  end;
  if EventLogHandle <= 0 then
  begin
    raise Exception.Create('Could not obtain Event Log handle.');
  end;
end;

class procedure TEventLog.Write(AEntryType: Word; AEventId: Cardinal; AMessage: string);
begin
  CheckEventLogHandle;
  ReportEvent(EventLogHandle, AEntryType, 0, AEventId, nil, 1, 0, @AMessage, nil);
end;

// This requires admin rights. Typically called once-off during the application's installation
class procedure TEventLog.AddEventSourceToRegistry;
var
  reg: TRegistry;
begin
  reg := TRegistry.Create;
  try
    reg.RootKey := HKEY_LOCAL_MACHINE;
    if reg.OpenKey('\SYSTEM\CurrentControlSet\Services\Eventlog\Application\' + Source, True) then
    begin
      reg.WriteString('EventMessageFile', ParamStr(0)); // The application exe's path
      reg.WriteInteger('TypesSupported', 7);
      reg.CloseKey;
    end
    else
    begin
      raise Exception.Create('Error updating the registry. This action requires administrative rights.');
    end;
  finally
    reg.Free;
  end;
end;

initialization

TEventLog.Source := 'My Application Name';

end.

报告事件 支持将日志条目写入本地或远程计算机的事件日志。有关远程示例,请参阅 John Kaster 的 EDN 文章.


请注意,您还必须 创建消息文件注册您的事件源 否则你的所有日志消息都将以如下内容开头:

从源XXXX中找不到事件ID XXX的描述。提高此事件的组件不是在您的本地计算机上安装,或者安装损坏。您可以在本地计算机上安装或修理组件。

如果事件起源于另一台计算机,则必须将显示信息保存在事件中。

该活动包含以下信息:

1、有关如何创建消息文件的更多信息请参见 Finn Tolderlund 的教程 或者 迈克尔·海克斯的文章 或者您可以使用现有的 MC 并 GitHub 项目中包含的 RES 文件.

2、通过将 MessageFile.res 包含在 DPR 文件中,将 RES 文件嵌入到您的应用程序中。或者,您可以为消息创建一个 dll。

program MyTestApp;

uses
  Forms,
  FormMain in 'FormMain.pas' {MainForm},
  EventLog in 'EventLog.pas';

{$R *.res}
{$R MessageFile\MessageFile.res}

begin
  Application.Initialize;

3、一次性注册需要管理员权限写入注册表,因此我们通常将其作为应用程序安装过程的一部分来完成。

//For example
AddEventSourceToRegistry('My Application Name', ParamStr(0));
//or
AddEventSourceToRegistry('My Application Name', 'C:\Program Files\MyApp\Messages.dll');

//--------------------------------------------------

procedure AddEventSourceToRegistry(ASource, AFilename: string);
var
  reg: TRegistry;
begin
  reg := TRegistry.Create;
  try
    reg.RootKey := HKEY_LOCAL_MACHINE;
    if reg.OpenKey('\SYSTEM\CurrentControlSet\Services\Eventlog\Application\' + ASource, True) then
    begin
      reg.WriteString('EventMessageFile', AFilename);
      reg.WriteInteger('TypesSupported', 7);
      reg.CloseKey;
    end
    else
    begin
      raise Exception.Create('Error updating the registry. This action requires administrative rights.');
    end;
  finally
    reg.Free;
  end;
end;

如果您需要 Windows 事件日志记录和其他日志记录要求,您还可以使用日志记录框架,例如 对数4d追踪工具


这里 如果您想写入 Delphi IDE 中的事件日志窗口。

为简单的事件记录在D5,我已经使用了下列代码要增加邮件的应用程序的记录。

  • 添加"SvcMgr"的使用条款
  • 使用这个代码添加文字信息和身份证数量(最后一参数上日志信息的线条)

    with TEventLogger.create('My Application Name') do
    begin
      try
        LogMessage('Information Message!', EVENTLOG_INFORMATION_TYPE, 0, 1);
        LogMessage('Error Message!', EVENTLOG_ERROR_TYPE, 0, 2);
        LogMessage('Warning Message!', EVENTLOG_WARNING_TYPE, 0, 3);
        LogMessage('Audit Success Message!', EVENTLOG_AUDIT_SUCCESS, 0, 4);
        LogMessage('Audit Failure Message!', EVENTLOG_AUDIT_FAILURE, 0, 5);
      finally
        free;
      end;
    end;
    

我使用的标准VCL为此在德尔斐6,我不能告诉你这是否是在德尔斐5.你可以尝试一下,让我们知道,如果这东西是存在D5。

  1. 宣布一个全球/形式类型的变量TEventLogger.这是宣布在SvcMgr单元使这个单位将需要增加的使用列表。如果这是一个正常的应用(即不服务),然后确保SvcMgr后加入的形式单元。

    MyEventLog:TEventLogger;

  2. 创建一个实例的记录。

    MyEventLog:=TEventLogger.Create('MyApplication');

  3. 写到的事件日志:

    MyEventLog.日志信息('MyApplication开始。'), EVENTLOG_INFORMATION_TYPE);

  4. 不要忘记它释放在最后:

    MyEventLog.免费的;

还有其他的东西你需要做的登记应用程序用Windows事件日志,以便消息似乎没有这种在面前:

所描述的事件ID(1000)在来源(Microsoft Internet Explorer)无法找到。地方计算机可能没有必要的注册信息或信息等文件显示的消息从一个远程计算机。以下信息事件的一部分:

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top