Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Win32::EventLog->Backup(), appending contents of new log to a saved one.

by dannyd (Sexton)
on Jan 11, 2011 at 15:01 UTC ( [id://881686]=perlquestion: print w/replies, xml ) Need Help??

dannyd has asked for the wisdom of the Perl Monks concerning the following question:

Greetings Old wise ones,

I am trying to write a script to save a copy of a particular EventLog(Application, System or Security) and if the save subroutine is called again and a saved file exists, then it should add the new events to the existing log.

I am a beginner and am having a real tough time with the documentation trying to figure out how to write a new event to the saved log, in the way it was written by the initial backup method call.

Please Help!!

This is what I have for save,

sub Save { our $DirName = 'WinLog'; &DirCreator($DirName); foreach (@arr) { my $Log_obj = Win32::EventLog->new("$_",""); $FileName = "$_\.evtx"; $Log_obj->Backup("\.\\".$DirName."\\"."$FileName"); switch ($^E) { case /^$/ { print "Log Successfully saved.";} case /^Cannot\ create\ a\ file\ when\ that\ file\ already\ + exists$/ ( <This is where Im stuck!!!> ) else { print "Error : $^E"}; } close ("$Log_obj"); } }
  • Comment on Win32::EventLog->Backup(), appending contents of new log to a saved one.
  • Download Code

Replies are listed 'Best First'.
Re: Win32::EventLog->Backup(), appending contents of new log to a saved one.
by Anonymous Monk on Jan 11, 2011 at 17:38 UTC
    Without remarking on the program logic or identifier naming convention, here's how that sub should look:
    sub Save { my $DirName = 'WinLog'; DirCreator($DirName); foreach (@arr) { my $Log_obj = Win32::EventLog->new($_, ""); my $FileName = "$_.evtx"; $Log_obj->Backup(".\\$DirName.\\$FileName"); given ($^E) { when ('') { print "Log Successfully saved.\n"; } when (/already exists/) { # ... } default { print "Error: $^E\n"; } } $Log_obj->Close; # see Win32::EventLog's docs } }

    Here are some helpful hints.

    You don't need to escape periods in strings or spaces in regexes. You don't have to preceed function calls with '&'. You don't have to quote variables containing strings if there's nothing else inside the quotes.

    When you quoted "$Log_obj" and passed that to close(), you sent a human-readable string that resembles that object, but not the object itself. When you create lexical filehandles, they are closed automatically when the variable goes out of scope. Most importantly, though, $Log_obj is not a filehandle. You needed to do $Log_obj->Close;, which calls the Close method of Win32::EventLog in the context of that object, not the builtin close function.

    Declare lexical variables (variables scoped to the inner-most block) with "my". When you use "our", you're declaring a variable in the symbol table, so other modules and packages can access it; if you're just looking to define a module that's scoped to a package, declare it outside of a sub (or other block), and it's accessible to all code in the package.

    The Switch module is buggy and deprecated. In Perl 5.10 and later, do use feature 'switch'; to enable the given/when construct, as I illustrated. If you're using an earlier version of Perl, use if/else constructs or something lke for ($value) { if (/foo/) { bar(); next; } }.

    By default, $\ will usually be undefined, so you'll want a newline at the end of a print, or you might suffer from buffering.

    And don't forget strictures: "use strict; use warnings;".

      Sorry, that should have been ".\\$DirName\\$FileName".
Re: Win32::EventLog->Backup(), appending contents of new log to a saved one.
by Gulliver (Monk) on Jan 11, 2011 at 17:06 UTC

    One way to do it would be to use a file test like -e to check if the file exists before you call Backup. If it does you could then call Backup with a temp filename and then append that to the existing file. Seems like there should be another method in Win32 to handle that but I don't know.

      Thanks for the suggestion, I probably should have mentioned in the question that I tried appending the entire log, using the code

      open (FH1,">>C\:\\Users\\Administrator\\Desktop\\Perl\_Scripts\\831203 +2\_Security\.evtx"); open (FH2,"<C\:\\Users\\Administrator\\Desktop\\Perl\_Scripts\\8312032 +\_System\.evtx"); while (<FH2>) { print FH1 $_; } close (FH1); close (FH2);

      When I did this, the security log size increased in proportion

      But I was not able to see any of the appended events from system when I opened security log using the Event viewer utility in windows.

      There is also a bit of a logic problem with this method, but im sure that can be resolved if it works

      Could it be that the log files are terminated and the Viewing utility stops reading after some sort of terminator??

      Any insight will be very helpful

      Whether the log file exists is displayed by the $^E variable in the case(So i think that part is ok).Any other ways to do it would be appreciated, but im still trying to figure out how to append to a saved log though.

        Before any other debugging, other than ensuring the code compiles, you should be checking that open() succeeded (unless you're already using autodie):
        my $dst = "C:\\Users\\Administrator\\Desktop\\Perl_Scripts\\8312032_Se +curity.evtx"; my $src = "C:\\Users\\Administrator\\Desktop\\Perl_Scripts\\8312032_Sy +stem.evtx"; open (my $dsth, ">>", $dst) or die qq(can't open "$dst" for appending: $!); open (my $srch, "<", $src) or die qq(can't open "$src" for reading: $!); print {$dsth} <$srch>; close ($srch); close ($dsth);

        or

        use autodie; { open (my $dsth, ">>", $dst); open (my $srch, "<", $src); print {$dsth} <$srch>; }

        That last block could be any type of block providing lexical scope. The print {$filehandle} LIST; construct makes it more obvious that you're printing to a filehandle object, rather than missing a comma in your arguments list, to both the programmer and to Perl. In list context, the diamond operator returns all lines from a file. You don't need to escape colons or underscores in a string or a regular expression.

        For easy of readability, Perl can handle Windows paths with forward slashes (actually, Windows itself handles forward-slash paths fine, which is what Perl sends to the system -- its Windows built-in applications which force only backslash paths on you). So to prevent forgetting to backslash a directory separator and to minimize length of paths strings, you could represent them as:

        my $dst = "C:/Users/Administrator/Desktop/Perl_Scripts/8312032_Securit +y.evtx"; my $src = "C:/Users/Administrator/Desktop/Perl_Scripts/8312032_System. +evtx";

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://881686]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (4)
As of 2024-04-24 03:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found