Модернизация журнала событий Windows для приложения Delphi 5
Я ищу (довольно безболезненное) средство добавления поддержки журнала событий приложений Windows в небольшое устаревшее приложение Delphi 5. Мы просто хотим, чтобы он регистрировался при запуске, завершении работы, невозможности подключения к базе данных и т. Д.
Некоторые из рассмотренных мной решений / компонентов предполагают, что нам нужно создать библиотеку ресурсов, на которую будет ссылаться средство просмотра журнала событий Windows при попытке прочитать наши "записи". Хотя это не кажется слишком обременительным, я думаю, что стоит иметь в виду что-то еще, если / когда мы продолжим разработку приложения в будущем - нам нужно будет поддерживать эту DLL в актуальном состоянии.
В какой-то момент в будущем мы захотим превратить приложение в сервис, вероятно, написанный в D2007.
Так может ли кто-нибудь порекомендовать подходящий маршрут для добавления событий в журнал событий в D5? Я ищу конкретные комментарии "мы использовали это, и это было нормально", а не траул Google (что я могу сделать сам!) Бесплатно или платно, на самом деле не против - но кое-что, что я мог бы перенести на D2007 в будущее важно.
4 ответа
Благодаря ответам J и Питера, я сразу же записал свой код в журнал событий. Есть еще кое-что, особенно если вы хотите, чтобы ваши события отображались "красиво" в журнале событий без стандартного сообщения Windows о невозможности найти описание (согласно нижней части поста J).
Я следовал советам по созданию подходящей DLL и внесению ее в реестр, и очень быстро все разобрался.
Это было все в Delphi5, согласно вопросу, но я не видел ничего, что заставляет меня думать, что это не будет работать и в D2007.
Сводка: запись в журнал событий Windows с использованием Delphi
Если вы пишете службу Windows и вам нужно записать в журнал событий Windows на локальном компьютере, вы можете позвонить в TService. LogMessage как упомянуто здесь.
//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. Недокументированный вспомогательный класс TEventLogger для 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 ReportEvent, как упомянуто здесь и здесь.
Я создал простой класс, чтобы сделать его проще, он доступен на 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.
ReportEvent поддерживает запись записи в журнал событий локального или удаленного компьютера. Для удаленного примера см . Статью EDN Джона Кастера.
Обратите внимание, что вам также нужно будет создать файл сообщений и зарегистрировать ваш источник событий, в противном случае все ваши сообщения журнала будут начинаться примерно так:
Описание для идентификатора события xxx из источника xxxx не может быть найдено. Либо компонент, который вызывает это событие, не установлен на локальном компьютере, либо установка повреждена. Вы можете установить или восстановить компонент на локальном компьютере.
Если событие возникло на другом компьютере, отображаемая информация должна была быть сохранена вместе с событием.
Следующая информация была включена в мероприятие:
1. Для получения дополнительной информации о том, как создать файл сообщения, см. Учебник Финна Толдерлунда или статью Майкла Хекса, или вы можете использовать существующий файл MC и RES, включенный в проект GitHub.
2. Вставьте файл RES в свое приложение, включив MessageFile.res в свой файл DPR. В качестве альтернативы вы можете создать 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 и другие требования к ведению журналов, вы также можете использовать каркасы журналов, такие как log4d и TraceTool.
Смотрите здесь, если вы хотите записать в окно журнала событий в Delphi IDE.
Для простой регистрации событий в D5 я использовал следующий код для добавления сообщений в журнал приложений.
- Добавьте "SvcMgr" к предложению использования
Используйте этот код для добавления вашего текстового сообщения и идентификационного номера (последний параметр в строках LogMessage)
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 для этого в Delphi 6, я не могу сказать вам, доступно ли это в Delphi 5. Попробуйте сами и сообщите нам, есть ли этот материал в D5.
Объявите глобальную переменную / переменную типа TEventLogger. Это объявляется в модуле SvcMgr, поэтому этот модуль необходимо будет добавить в ваш список использования. Если это обычное приложение (т.е. не Служба), убедитесь, что SvcMgr добавлен после модуля Forms.
MyEventLog: TEventLogger;
Создайте экземпляр регистратора.
MyEventLog: = TEventLogger.Create ('MyApplication');
Для записи в журнал событий:
MyEventLog.LogMessage ('MyApplication запущено.'), EVENTLOG_INFORMATION_TYPE);
Не забудьте выпустить его в конце:
MyEventLog.Free;
Есть еще кое-что, что вам нужно сделать, чтобы зарегистрировать приложение в журнале событий Windows, чтобы перед ним появлялось сообщение:
Описание для идентификатора события ( 1000) в источнике ( Microsoft Internet Explorer) не может быть найдено. Локальный компьютер может не иметь необходимой информации реестра или файлов DLL сообщений для отображения сообщений с удаленного компьютера. Следующая информация является частью мероприятия: