2015-05-14 17 views
18

In che modo la mia app Delphi può scrivere facilmente nel registro eventi di Windows?Scrittura nel registro eventi di Windows utilizzando Delphi

Qual è la differenza tra TEventLogger e ReportEvent? Come si usa la funzione ReportEvent?

+2

Ricerca in eccesso L'overflow per questa domanda apparentemente semplice restituisce risposte sparse tra molte domande. Ho creato una nuova domanda semplice e ho speso del tempo per combinare le risposte e aggiungere informazioni extra che non erano nelle altre risposte. L'ho fatto perché non era la prima volta che venivo qui a cercare questa risposta e pensavo che la risposta dettagliata e il progetto di esempio potessero aiutare anche gli altri. –

+2

Avresti potuto farlo nell'altra domanda. Va bene anche qui. Le domande sono collegate ora. Va tutto bene. http://blog.stackoverflow.com/2010/11/dr-strangedupe-or-how-i-earned-to-stop-worrying-and-love-duplication/ –

+0

Ah ok, grazie David, ora capisco meglio come Funziona. –

risposta

25

Se si sta scrivendo un servizio di Windows e la necessità di scrivere al registro eventi di Windows del computer locale, allora si può chiamare TService.LogMessage come detto here.

//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; 

Per qualsiasi altro tipo di applicazioni che è possibile utilizzare lo SvcMgr. TEventLoggerundocumented classe di supporto per TService per scrivere il registro eventi di Windows della macchina locale come indicato in here, here e here.

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; 

È inoltre possibile utilizzare la funzione API di Windows ReportEvent come detto here e here.

Ho creato una classe semplice per semplificare, è available on 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 Supporta la scrittura di una voce di registro per registro eventi sia una macchina locale o remoto. Per un esempio remoto vedere John Kaster's EDN article.


noti che si avrebbe anche per create a message file e register your event source altrimenti tutti i messaggi di log inizierà con qualcosa di simile:

la descrizione dell'ID evento xxx da xxxx fonte non può essere trovato. Il componente che solleva questo evento non è installato su sul computer locale o l'installazione è corrotta. È possibile installare o riparare il componente sul computer locale.

Se l'evento è stato originato su un altro computer, le informazioni di visualizzazione dovevano essere salvate con l'evento.

Le seguenti informazioni è stato incluso con l'evento:

1, Per ulteriori informazioni su come creare un file di messaggio vedi Finn Tolderlund's tutorial o Michael Hex's article oppure è possibile utilizzare un MC esistente e RES file included in the GitHub project.

2, Incorporare il file RES nell'applicazione includendo MessageFile.res nel file DPR. In alternativa puoi creare una DLL per i messaggi.

program MyTestApp; 

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

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

begin 
    Application.Initialize; 

3, L'iscrizione una tantum richiede diritti di amministratore di scrittura al Registro di sistema in modo che noi di solito fatto come parte del processo di installazione dell'applicazione.

//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; 

Se avete bisogno di registrazione di eventi di Windows e di altri requisiti di registrazione è anche possibile utilizzare quadri di registrazione, come log4d e TraceTool


Vedi here se si desidera scrivere nel registro eventi finestra nell'IDE di Delphi.

+4

Ben fatto! Solo per la tua lezione di registro. Preferirei che i loro metodi fossero i metodi di istanza piuttosto che i metodi di classe per evitare la registrazione ripetitiva e la cancellazione della fonte dell'evento. Registrerei la fonte dell'evento quando l'istanza della classe verrà creata e cancellata quando distrutta. Oppure crea un threadvar globale e inizializzalo una volta. – TLama

+0

Se si annulla la registrazione quando l'istanza viene distrutta, non è possibile che le voci del registro eventi esistenti non vengano più lette? In altre parole, l'istanza doveva essere attiva affinché l'operatore potesse visualizzare le voci del registro eventi precedenti? Penso piuttosto che la registrazione della sorgente di eventi dovrebbe essere parte dell'installazione e annullare la registrazione alla disinstallazione dell'eseguibile. –

+0

Ciao TOndrey, sospetto che TLama abbia inteso la chiamata API "RegisterEventSource", non "Registra la fonte dell'evento aggiungendola al registro" :-) –

Problemi correlati