feuerstein08
Goto Top

Mit Powershell aus dem Eventlog den Messageinhalt in Excel schreiben

Hallo Zusammen,

ich versuche aus dem System-Eventlog bestimmte Informationen in eine csv-Datei zu schreiben.

Beispiel :get-eventlog -newest 5 -logname application |where {$_.source -eq "AutoEnrollment"} | select-object * | % ($Message = $_.Message)

Nun möchte ich die "Messages" dieser Fehlermeldungen in je >eine< Zelle einer csv schreiben.
Bei längeren Meldungen wird das leider immer in mehrere Zellen geschrieben.

Danke!

Content-Key: 118703

Url: https://administrator.de/contentid/118703

Ausgedruckt am: 28.03.2024 um 13:03 Uhr

Mitglied: 77559
77559 22.06.2009 um 10:51:48 Uhr
Goto Top
Hallo Feuerstein08,

warum nicht einfacher:

get-eventlog -newest 5 -logname application -source AutoEnrollment | select-object Message

Die Bildschirmausgabe weicht ja immer ab, wie schreibst du in die Datei?
Ich habe hier keine AutoEnrollment Einträge, wie sehen die Messsages denn aus?
Wenn die Zeilenwechsel Bestandteil der Messages sind, musst du sie gfs. rausfiltern.
Wenn in den Messages Anführungszeichen enthalten sind, müssen die auch ggfs ersetz/escaped werden damit eine gültige csv entsteht.

Gruß
LotPings
Mitglied: Feuerstein08
Feuerstein08 22.06.2009 um 13:43:53 Uhr
Goto Top
Hallo LotPings,

es geht nicht um das AutoEnrollment (sollte nur ein Beispiel sein).
Es geht hier um das automatische Suchen von bestimmten Event- oder Source-oder ...-Einträgen im Eventlog (auch wieder egal ob System, Appl. oder ...)

Ich möchte einen PS-Job regelmäßig auf meine Server loslassen, der mir das anhand einer Config-Datei (hier sind dann die zu suchenden Felder beschrieben) das
Gesuchte rausschreibt und (da x-Server) in eine Excel kompatible Datei ausgibt.
Soweit - so schön. Klappt auch alles, bis auf die Tatsache, das mir die Messages, sofern sie nicht nur Einzeiler sind, NICHT in ein Feld geschrieben werden, sondern in die nächste Zeile, erstes Feld ... und das gilt es zu optimieren.

Ich möchte also die einzelnen Inhalte der Variablen in einezelne Felder einer csv-Datei schreiben.

BEISPIEL (irgendeinen Index-Eintrag nehmen ... hier Nr. 70):
get-eventlog -logname system | where-object {$_.Index -eq 70} |select-object *| % {$1 = $_.Index; $2 = $_.EventID; $3 = $_.MachineName; $4 = $_.Category; $5 = $_.CategoryNumber; $6 = $_.EntryType; $7 = $_.Message; $8 = $_.Source; Write-host 1: $1; Write-Host 2: $2; Write-Host 3: $3; Write-Host 3: $3; Write-Host 4: $4; Write-Host 5: $5; Write-Host 6: $6; Write-Host 7: $7; Write-Host 8: $8; "$1`t$2`t$3`t$4`t$5`t$6`t$7`t$8" | out-file -filepath "c:\test.csv" -append}

Ausgabe:
1: 70
2: 17
3: SERVER001
3: SERVER001
4: (0)
5: 0
6: Error
7: Time Provider NtpClient: An error occurred during DNS lookup of the manually
configured peer 'time.windows.com,0x1'. NtpClient will try the DNS lookup again in 15
minutes.
The error was: A socket operation was attempted to an unreachable host. (0x80072751)
8: W32Time

Bzw. die "c:\test.csv"

DAS möchte ich nun in eine CSV ausgeben, wobei die Nr. 7 die Probleme macht ...

Könnte es an Steuerzeichen in der Message liegen (CRLF) und wenn "Ja" : wie bekomme ich das entsprechend hin?

Vielen Dank!
Mitglied: 77559
77559 22.06.2009 um 15:33:07 Uhr
Goto Top
Zitat von @Feuerstein08:
Könnte es an Steuerzeichen in der Message liegen (CRLF) und wenn "Ja" : wie bekomme ich das entsprechend hin?
JA.
Mit einer berechneten Eigenschaft die Message um das CRLF erleichtern:
get-eventlog -logname system -newest 5| Select Index,EventID,MachineName,Category,CategoryNumber,EntryType,@{Name="MyMSG"; Expression = {$_.Message -replace "`r`n", ""}},Source | export-csv "c:\test\test.csv"  

Gruß
LotPings
Mitglied: Feuerstein08
Feuerstein08 22.06.2009 um 16:43:56 Uhr
Goto Top
Hallo LotPings,

ich muss sagen "Hut ab" - funktioniert einwandfrei (und wesentlich effektiver und schneller als meine Version).
Könntest du mir noch kurz erläutern, was es mit dem "@" auf sich hat?
Ist das eine Powershell interne Variable (foreach?)
Kannst du mir ein Tutorial oder eine gute Seite nennen, wo ich das mit den internen Variablen und die Handhabung mit den Expressions nachlesen kann? (Möchte ja schlauer werden face-wink

Und zu guter letzt, wie kann ich diese Ausgabe so umformulieren, das ich anstatt der Komma-Trennung die Tabulatoren >`t< reinbekomme?
Dann reicht ein einfacher Doppelklich auf die csv-Datei - so hat Excel beim öffnen immer ein wenig Probleme damit (oder mache ich hier auch etwas falsch?).

Vielen Dank für deine Hilfe!
Mitglied: Feuerstein08
Feuerstein08 22.06.2009 um 17:24:38 Uhr
Goto Top
... und wie bekomme ich Datum und Zeit da noch rein. Einfach simpel Date und Time haben nicht hingehauen ... ??

Danke!
Mitglied: 77559
77559 22.06.2009 um 17:27:54 Uhr
Goto Top
Zitat von @Feuerstein08:
Könntest du mir noch kurz erläutern, was es mit dem "@" auf sich hat? Ist das eine Powershell interne Variable (foreach?)
Siehe get-help select -full
und get-help export-csv -full

Das ist eine berechnete Eigenschaft. In Powershell bin ich auch noch ein "Einäugiger" und muss viel googlen bzw. in der Newsgroup "microsoft.public.windows.powershell" mitlesen.

Kannst du mir ein Tutorial oder eine gute Seite nennen, wo ich das mit den internen Variablen und die Handhabung mit den Expressions nachlesen kann? (Möchte ja schlauer werden face-wink
Da ich mir mein Wissen nur Online angeeignet habe, kann ich kein Buch empfehlen, ich such mal bei Gelegenheit Links raus.

Und zu guter letzt, wie kann ich diese Ausgabe so umformulieren, das ich anstatt der Komma-Trennung die Tabulatoren >`t< reinbekomme?
get-eventlog -logname system -newest 5| Select Index,EventID,MachineName,Category,CategoryNumber,EntryType,@{Name="MyMSG"; Expression = {$_.Message -replace "`r`n", ""}},Source | export-csv "c:\test\test.csv" -delimiter "`t"  

Dann reicht ein einfacher Doppelklich auf die csv-Datei - so hat Excel beim öffnen immer ein wenig Probleme damit (oder mache ich hier auch etwas falsch?).
Excel sollte mit dem Standard csv Format eigentlich auch klarkommen.

Gruß
LotPings
Mitglied: 77559
77559 22.06.2009 um 17:38:21 Uhr
Goto Top
Zitat von @Feuerstein08:
... und wie bekomme ich Datum und Zeit da noch rein. Einfach simpel
Date und Time haben nicht hingehauen ... ??

Tja welche DateTime?

Schau dir mal dies an:
get-eventlog -logname system -newest 1| gm
Da gibts es "TimeGenerated" und "TimeWritten"

Hier nochmal alles zusammen:
get-eventlog -logname system -newest 5| Select TimeGenerated,TimeWritten,Index,EventID,MachineName,Category,CategoryNumber,EntryType,@{Name="MyMSG"; Expression = {$_.Message -replace "`r`n", ""}},Source | export-csv "c:\test\test.csv" -delimiter "`t"  

Gruß
Mitglied: Feuerstein08
Feuerstein08 22.06.2009 um 17:52:59 Uhr
Goto Top
Hallo LotPings,

supi!!
Das mit den TimeGenerated hatte ich zwar eben auch rausgefunden, aber an den Delimiter hätte ich zu knabbern gehabt.
Das mit den Büchern ist so eine Sache ... man blättert zu selten darin rum und das suchen ist in Papierform doch eher umständlich (wozu gibt es den mittlerweile fast alles "Online"?).

Wenn du auf dieses Posting hier eventuell noch mal so 1-2 gute Links packst, wär das echt klasse.
Ansonsten hast du mir SEHR geholfen.

Super schnell - super gut!
Vielen Dank noch einmal!
Gruß
Feuerstein08
Mitglied: Feuerstein08
Feuerstein08 22.06.2009 um 17:56:57 Uhr
Goto Top
Hmm - der Delimiter funktioniert so leider nicht.... Stellungsparameter?

Gruß
Feuerstein08
Mitglied: Feuerstein08
Feuerstein08 22.06.2009 um 17:59:14 Uhr
Goto Top
OK - der Delimiter scheint erst ab der V2 zu funktionieren.
Ich habe (und muss leider) die V1 benutzen.

Hast du noch einen Workaround für mich und der Tabulatorgeschichte?

Danke
Feuerstein08
Mitglied: 77559
77559 22.06.2009 um 18:27:06 Uhr
Goto Top
Zitat von @Feuerstein08:
OK - der Delimiter scheint erst ab der V2 zu funktionieren. Ich habe (und muss leider) die V1 benutzen.
Schade, hab hier überall v2, entweder ctp3 oder schon dabei.

Hast du noch einen Workaround für mich und der Tabulatorgeschichte?
Speicher mal mit export-csv mit der Erweiterung .txt - dann müsste der ImportDialog von excel kommen.
Alternativ
  • hab ich im Hinterkopf dass man auch xls erzeugen kann, habe ich aber gerade nicht greifbar
  • in der Datei Suchen nach "," ersetzen mit "`t".

Habe gerade nicht soviel Zeit.

Gruß
Mitglied: 77559
77559 22.06.2009 um 19:40:31 Uhr
Goto Top
Dies sollte auch mit v1 gehen:
$str = get-eventlog -logname system -newest 5| Select TimeGenerated,TimeWritten,Index,EventID,MachineName,Category,CategoryNumber,EntryType,@{Name="MyMSG"; Expression = {$_.Message -replace "`r`n", ""}},Source | ConvertTo-Csv -NoTypeInformation  
$str = $str -replace ",", "`t"  
$str |out-file -filepath "c:\test\test.csv"  

Gruß
Mitglied: Feuerstein08
Feuerstein08 25.06.2009 um 22:13:28 Uhr
Goto Top
Hallo LotPings,

schade - hautt aber auch nicht hin. Das cmdlet "Convertto-csv" gubt es in der v1.0 nicht.
Ist aber nicht so schlimm - ich regel das einfach über ein erneutes einlesen der ersten Datei in eine neue aus.

Eine letzte Frage hätte ich noch (wenn du noch magst??):
Wenn du dir das nachfolgende Beispiel einmal ansiehst, dann sind da "eigentlich" 2 gleiche Abfragen drin, die aber einmal das korrekte Ergebnis und einmal das komplette System Eventlog ausgibt.

Das Array ($IDToQuery) lese ich im kompletten Skript über eine Datei ein - hier nur zur Demo in dem Skript.
Ich möchte gern die Variante mit der zusammengebauten $query nutzen.
Das bringt mir aber das komplette Log ...
Was ist da falsch?

Danke für die Hilfe!

if ((Test-Path "C:\Test") -ne $true)	  
	{new-item -path c:\ -name test -type directory}

$csv_file_1 = "c:\test\Eventlog1.csv"  
$csv_file_2 = "c:\test\Eventlog2.csv"  

$IDToQuery =@()
$IDToQuery = "4","9"  

Write-Host ""  
Write-Host IDToQuery =  $IDToQuery :: Anzahl = $IDToQuery.Count 

#########################################
# Query erstellen 						#
#########################################
$query = ""  
If ($IDToQuery.Count -gt 0)
	{$query = '($_.EventID -contains $IDToQuery)'}  
#  ... hier würden noch weitere Array Abfragen kommen
#  dadurch erweitert sich die <query>

Write-Host Query = $query

####################
# Header erstellen #
####################
"Computer`tEventID`tTimeGenerated`tMachineName`tCategoryNumber`tEntryType`tSource`tMessage" | out-file -filepath $csv_file_1 -Append  
"Computer`tEventID`tTimeGenerated`tMachineName`tCategoryNumber`tEntryType`tSource`tMessage" | out-file -filepath $csv_file_2 -Append  

#######################
# Eigentliche Abfrage #
#######################

# So möchte ich die Query gestalten (und ausbauen) - erhalte aber leider das komplette Log ...
get-eventlog -logname system | where-object { $query } | Select Index,EventID,TimeGenerated,MachineName,CategoryNumber,EntryType,@{Name="MyMSG"; Expression = {$_.Message -replace "`r`n", ""}},Source | select-object * | % {$EventID = $_.EventID; $MachineName = $_.MachineName; $TimeGenerated = $_.TimeGenerated; $CategoryNumber = $_.CategoryNumber; $EntryType = $_.EntryType; $Message = $_.MyMSG; $Source = $_.Source; "$CompName`t$EventID`t$TimeGenerated`t$MachineName`t$CategoryNumber`t$EntryType`t$Source`t$Message"} | out-file -filepath $csv_file_1 -Append  

# richtiger Output, aber ich will ja die Bedingungen nicht einzeln reinschreiben, sondern flexibel gestalten
get-eventlog -logname system | where-object {(($_.EventID -eq 4) -or ($_.EventID -eq 9))} | Select Index,EventID,TimeGenerated,MachineName,CategoryNumber,EntryType,@{Name="MyMSG"; Expression = {$_.Message -replace "`r`n", ""}},Source | select-object * | % {$EventID = $_.EventID; $MachineName = $_.MachineName; $TimeGenerated = $_.TimeGenerated; $CategoryNumber = $_.CategoryNumber; $EntryType = $_.EntryType; $Message = $_.MyMSG; $Source = $_.Source; "$CompName`t$EventID`t$TimeGenerated`t$MachineName`t$CategoryNumber`t$EntryType`t$Source`t$Message"} | out-file -filepath $csv_file_2 -Append  
Mitglied: 77559
77559 26.06.2009 um 10:24:51 Uhr
Goto Top
Hallo Feuerstein08,

das war auch für mich eine Nuss face-wink

Die Lösung ist die Kommandozeile in einem String zusammenzubauen und dann mit invoke-expression auszuführen.
Dieses Script erzeugt bei mir identischen Output für beide Varianten.
Ob das auch unter V1 geht, musst du selber testen.
Ich habe auch noch ein paar Dinge geändert, Header in Variable, unsinningen Select-Object * entfernt, MyMsg in Message geändert (man kann Eigenschaften überschreiben)

if ((Test-Path "D:\Test\Posh") -ne $true)	  
	{new-item -path c:\ -name test -type directory}

$csv_file_1 = "D:\Test\Posh\Eventlog1.csv"  
$csv_file_2 = "D:\Test\Posh\Eventlog2.csv"  

$IDToQuery =@()
$IDToQuery = "4","9"  

Write-Host ""  
Write-Host IDToQuery =  $IDToQuery :: Anzahl = $IDToQuery.Count 

#########################################
# Query erstellen 						#
#########################################
$query = ""  
If ($IDToQuery.Count -gt 0)
	{$query = '(($_.EventID -eq 4) -or ($_.EventID -eq 9))'}  
#  ... hier würden noch weitere Array Abfragen kommen
#  dadurch erweitert sich die <query>

Write-Host Query = $query

####################
# Header erstellen #
####################
$Header = "Computer`tEventID`tTimeGenerated`tMachineName`tCategoryNumber`tEntryType`tSource`tMessage"  
$Header | out-file -filepath $csv_file_1 
$Header | out-file -filepath $csv_file_2 

#######################
# Eigentliche Abfrage #
#######################
# So möchte ich die Query gestalten (und ausbauen) - erhalte aber leider das komplette Log ...
$cmd='get-eventlog -logname system | where-object {' + $query + '}| Select Index,EventID,TimeGenerated,MachineName,CategoryNumber,EntryType,Source,@{Name="Message";Expression={$_.Message -replace "`r`n", ""}}| %{$EventID=$_.EventID; $MachineName=$_.MachineName; $TimeGenerated=$_.TimeGenerated; $CategoryNumber=$_.CategoryNumber; $EntryType=$_.EntryType; $Message=$_.Message; $Source=$_.Source;"$CompName`t$EventID`t$TimeGenerated`t$MachineName`t$CategoryNumber`t$EntryType`t$Source`t$Message"}| out-file -filepath $csv_file_1 -Append'  
Invoke-Expression $cmd

# richtiger Output, aber ich will ja die Bedingungen nicht einzeln reinschreiben, sondern flexibel gestalten
get-eventlog -logname system | where-object {(($_.EventID -eq 4) -or ($_.EventID -eq 9))} `
| Select Index,EventID,TimeGenerated,MachineName,CategoryNumber,EntryType,Source,@{Name="Message";Expression={$_.Message -replace "`r`n", ""}} `  
| %{$EventID=$_.EventID; $MachineName=$_.MachineName; $TimeGenerated=$_.TimeGenerated; $CategoryNumber=$_.CategoryNumber; $EntryType=$_.EntryType; $Message=$_.Message; $Source=$_.Source; `
"$CompName`t$EventID`t$TimeGenerated`t$MachineName`t$CategoryNumber`t$EntryType`t$Source`t$Message"} `  
| out-file -filepath $csv_file_2 -Append

Gruß
LotPings
Mitglied: Feuerstein08
Feuerstein08 26.06.2009 um 18:29:34 Uhr
Goto Top
Hallo LotPings,

klasse - ich werde das nachher gleich testen und berichten.

Vielen Dank soweit (und schön, das es für dich scheinbar auch noch "Nüsse" zu knacken gibt face-wink.

CU
Feuerstein08
Mitglied: Feuerstein08
Feuerstein08 27.06.2009 um 10:08:25 Uhr
Goto Top
Hallo LotPings,

klappt soweit alles super. Die anderen Bedingungen waren schnell eingetragen und brachten die erwarteten Ergebnsse.
Einzig an den "Messages" beiße ich mir wieder die Zähne aus ...

Auch hier lese ich aus einer Datei die zu suchenden "Satzfragmente" aus und möchte diese mit den jeweiligen Messages vergleichen.
Das klappt nicht face-sad

Beispiel: Diese Events sollten gefunden werden, wenn ich das nachfolgende Array nutze:

Das ist die Original Message:
The time service is now synchronizing the system time with the time source server001.Sosoft.local (ntp.d|10.1.1.11:123->10.1.1.1:123).

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

# Ich möchte ein Array bilden, dessen Inhalt ich gegen die Message vergleichen kann 
# und "natürlich" nur die Treffer-Events erhalte. 

# Das Array (hier nicht aus einer Datei erstellt):
$Mess = "The time service"  
$Mess += "The time provider"  

#Die Abfrage
Get-EventLog -LogName system | where {$_.Message -match $Mess}

Hier stimmt irgendetwas mit dem Vergleichsoperator (-contains, -match, -like) nicht und scheinbar auch bei der Erstellung des Arrays.
Muss ich die Strings anders "einkleiden"?
Oder kann ich so keine Teilvergleiche anstellen?

Manuell klappt eine einzelne Abfrage ...
get-eventlog -logname system |where {$_.Message -match "WinHTTP Web Proxy Auto-Discovery Service service was"}  

Danke für die Hilfe!
Mitglied: 77559
77559 27.06.2009 um 10:46:27 Uhr
Goto Top
Sorry Feuerstein08,

aber so geht das nicht.
Die eigentliche Frage ist längst beantwortet und das solltest du auch entsprechend abhaken. Desen Beitrag als "gelöst" markieren
Deine Ergänzungen habe ich alleine austüfteln müssen weil Andere diese Fragen in diesem alten Thread gar nicht beachten (können).

Also mache bitte für die neuen Fragen einen neuen Beitrag auf.

Gruß
LotPings
Mitglied: Feuerstein08
Feuerstein08 27.06.2009 um 18:06:24 Uhr
Goto Top
Hallo LotPings,

hast vollkommen Recht!

Danke soweit und ich mache einen neuen Beitrag mit der Frage bzgl. der Messages auf.

Gruß
Feuerstein.