Powershell Write-EventLog / Get-WinEvent Message issues - powershell

The first command creates an entry in the event log, it seems to be working because I can see the message data in event viewer. The issue is when reading it back from powershell the message field is empty.
write-eventlog System -source 'Microsoft-Windows-Kernel-General' -eventid 999 -message 'Kernel something or other'
get-winevent -filterHashTable #{Logname = 'System'; ID = '999'}| select-object -first 10
Maybe this picture explains it better. Notice the message column is blank.

The event is being written correctly, to read it back use this:
get-winevent -filterHashTable #{Logname = 'System'; ID = '999'}|
select-object -first 10 | select timecreated,providername,
#{n="Message";e={$_.properties.Value}}
The reason you can't see it in the message column is evident when launching eventvwr:
The description for Event ID 999 from source Microsoft-Windows-Kernel-General cannot be found. Either the component that raises this event is not installed on your local computer or the installation is corrupted. You can install or repair the component on the local computer.
If you want to write custom messages from custom sources use New-EventLog cmdlet, here is the Scripting Guy's tutorial: http://blogs.technet.com/b/heyscriptingguy/archive/2013/06/20/how-to-use-powershell-to-write-to-event-logs.aspx

Here is the snip that ended up making it work. Credit to Raf for the link where I found this answer.
$source = "Some Name"
If ([System.Diagnostics.EventLog]::SourceExists("$source") -eq $false)
{New-EventLog -LogName $log -Source "$source"}

Related

How can I read analytical Windows events from 'Applications and Services Logs' using PowerShell?

I use Get-EventLog to read events. Using this cmdlet, I can successfully read the System and the Security event logs for example. I can also list all available logs by issuing the following command:
Get-EventLog -LogName * | Select-Object -Property Log
Output:
Log
---
Application
HardwareEvents
Internet Explorer
Key Management Service
OAlerts
Parameters
Security
State
System
Windows PowerShell
But this list does not contain all of the logs you can find under Applications and Services logs, e. g.: I'd like to read the events from this path that can be traversed inside the Event Viewer:
Applications and Services Logs > Microsoft > Windows > DNS-Server > Analytical
I'm doing this on a Windows DNS-Server with Show Analytic and Debug Logs enabled under View and also a configured and enabled Analytical log for DNS-Server.
Tl;dr:
Use Get-WinEvent instead and add the -Oldest parameter:
Get-WinEvent -LogName Microsoft-Windows-DNSServer/Analytical -Oldest
Get-EventLog is a legacy cmdlet to read the Windows event log and it cannot be used to read all available event logs (look for the note in the documentation of this cmdlet):
Get-EventLog uses a Win32 API that is deprecated. The results may not be accurate. Use the Get-WinEvent cmdlet instead.
With Get-WinEvent you can list all available logs using Get-WinEvent -ListLog * or you can filter for all DNS related logs:
Get-WinEvent -ListLog *DNS* | Select-Object -Property LogName
Output:
LogName
-------
DNS Server
Microsoft-Windows-DNS-Client/Operational
Microsoft-Windows-DNSServer/Audit
Add the -Force parameter to also see Debug and Analytical events:
LogName
-------
DNS Server
Microsoft-Windows-DNS-Client/Operational
Microsoft-Windows-DNSServer/Analytical
Microsoft-Windows-DNSServer/Audit
You can read the events by passing those names to the -LogName parameter:
Get-WinEvent -LogName Microsoft-Windows-DNSServer/Audit
You'll get an error when trying to read the Microsoft-Windows-DNSServer/Analytical log:
Get-WinEvent : The Microsoft-Windows-DNSServer/Analytical event log can be read only in the forward chronological order because it is an analytical or a debug log. To see events from the Microsoft-Windows-DNSServer/Analytical event log, use the Oldest parameter in the command.
So just add -Oldest and you are good to go:
Get-WinEvent -LogName Microsoft-Windows-DNSServer/Analytical -Oldest

Selecting specific lines/data from Get-Winevent message in powershell

I am trying to extract a specific line from the message output of a get-winevent cmdlet and haven't been able to find a way to do this (I could be searching incorrectly but am still learning more advanced scripting methods). What I am running is this:
Get-WinEvent -ComputerName $DC -FilterHashtable #{Logname='Security';Keywords='9007199254740992';Data=$userid} -MaxEvents 1 | Select Message | Format-List
Which will return with a message similiar to this (Changed some info to generic info):
Message : The computer attempted to validate the credentials for an account.
Authentication Package: MICROSOFT_AUTHENTICATION_PACKAGE_V1_0
Logon Account: jdoe
Source Workstation: Generic-Computername
Error Code: 0x0
I am attempting to create an easy way to find a computer someone last logged into for faster troubleshooting but I am unable to filter out only the Source Workstation line, I could just not have the correct syntax for a good search to find the results I am looking for but I have been searching for about a week now and haven't found anything close to what I am looking for, any help would be great!
Im not sure what information you want to retrieve but im pretty sure there is a better way then using Get-WinEvent to obtain that information. However, if you just want to get the value of Source Workstation you can do that with a regex:
$event = Get-WinEvent `
-ComputerName $DC `
-FilterHashtable #{Logname='Security';Keywords='9007199254740992';Data=$userid} `
-MaxEvents 1 `
| Select -expand Message
[regex]::Match($event, 'Source Workstation:\s*(.*)\s*').Groups[1].Value

Get-EventLog - valid message missing for some event log sources

I'm pulling and filtering System Event Log data using get-eventlog. What I'm finding is that get-event log is not able to correctly return the message associated with some entries. These entries appear normally in the event log viewer. E.g.
get-eventlog -logname system | ? { $_.source -eq "Microsoft-Windows-Kernel-General" }
returns 8 entries, all of which have a message of the following form:
The description for Event ID '12' in Source 'Microsoft-Windows-Kernel-General' cannot be found.
The local computer may not have the necessary registry information or message DLL files to display the message, or you may not have permission to access them.
The following information is part of the event:'6', '1', '7601', '18798', '1', '0', '2015-06-13T08:33:32.359599800Z'
If I filter the system event log for the same source, I can clearly see the fully formed message. e.g
The operating system started at system time ‎2015‎-‎06‎-‎13T08:33:32.359599800Z.
I ran the following to see if any other providers were unable to return valid event messages:
get-eventlog -LogName system | ? { $_.Message -like "The description for Event ID*" } | Group-Object -Property Source | Select-Object -Property Name
Name
----
Microsoft-Windows-Kernel-General
DCOM
WinRM
Microsoft-Windows-Iphlpsvc
I checked in the event log viewer to find the corresponding entries for the DCOM, WinRM and Iphlpsvc sources and confirmed that the correct message was visible.
I've run the test scripts in a admin-level PowerShell console.
Any ideas?
EDIT: Further research has revealed that PsLogList also appears to suffer from the same problem, whereas WEVTUTIL does not.
EDIT: Following suggestion by Windos, I tried get-winevent. I had tried this previously and found that it would return no Message data at all. I tried again and found the same result. I then tried
Get-WinEvent -ProviderName "Microsoft-Windows-Kernel-General"
which produced the following error
Could not retrieve information about the Microsoft-Windows-Kernel-General provider. Error: The locale specific resource for the desired message is not present.
A little googling led me to 'https://p0w3rsh3ll.wordpress.com/2013/12/13/why-does-my-get-winevent-command-fail/' who had also experienced the same error message. He suggested this was due to regional settings. I'm in Australia, so my 'format' setting in Control Panel was 'English (Australia)'. I changed this to 'English (United States)', launched a new PS console, confirmed with get-culture that I was now in the US and re-ran the get-winevent commands.
Get-WinEvent -ProviderName "Microsoft-Windows-Kernel-General" | select-object -property Message
lo and behold ...
Message
-------
The system time has changed to ?2015?-?07?-?12T01:06:52.405000000Z from ?2015?-?07?-?12T01:05:51.764208900Z.
The system time has changed to ?2015?-?07?-?12T01:05:09.671000000Z from ?2015?-?07?-?12T01:04:09.226010500Z.
The system time has changed to ?2015?-?07?-?12T01:03:49.119000000Z from ?2015?-?07?-?12T01:02:48.060593100Z.
The system time has changed to ?2015?-?07?-?12T01:02:32.128000000Z from ?2015?-?07?-?12T01:01:29.610105600Z.
The system time has changed to ?2015?-?06?-?13T08:41:12.267000000Z from ?2015?-?06?-?13T08:41:12.404273100Z.
The operating system started at system time ?2015?-?06?-?13T08:33:32.359599800Z.
The operating system is shutting down at system time ?2015?-?06?-?13T08:33:05.091743100Z.
The system time has changed to ?2015?-?06?-?13T08:32:58.947000000Z from ?2015?-?06?-?13T08:32:58.947959900Z.
Sadly though - no change got get-eventlog
get-eventlog -logname system | ? { $_.Source -eq "microsoft-windows-kernel-general" } | select-object -property Message
Message
-------
The description for Event ID '1' in Source 'Microsoft-Windows-Kernel-General' cannot be found. The local computer m...
The description for Event ID '1' in Source 'Microsoft-Windows-Kernel-General' cannot be found. The local computer m...
The description for Event ID '1' in Source 'Microsoft-Windows-Kernel-General' cannot be found. The local computer m...
The description for Event ID '1' in Source 'Microsoft-Windows-Kernel-General' cannot be found. The local computer m...
The description for Event ID '1' in Source 'Microsoft-Windows-Kernel-General' cannot be found. The local computer m...
The description for Event ID '12' in Source 'Microsoft-Windows-Kernel-General' cannot be found. The local computer ...
The description for Event ID '13' in Source 'Microsoft-Windows-Kernel-General' cannot be found. The local computer ...
The description for Event ID '1' in Source 'Microsoft-Windows-Kernel-General' cannot be found. The local computer m...
Not sure on the how or why, but it looks like if you opt for Get-WinEvent rather than Get-EventLog you'll get the info you're after.
It should be noted that when changing commands the 'Source' parameter is known as 'ProviderName' so your command becomes:
Get-WinEvent -LogName System | Where { $_.ProviderName -eq 'Microsoft-Windows-Kernel-General' }

powershell takes a long time to close connection?

I'm trying to run this powershell script on several remote network servers, but it takes a long time to complete the task and move to the next one.
Here's a basic script that will query a single remote server and return the data I want in a fast manner, but takes a long time to complete the entire script.
Get-EventLog -ComputerName WebServer1 -LogName System -EntryType Error -After ((Get-Date).Date.AddDays(-1))
I was running it through the Powershell ISE and from the command line in Powershell and both have the same behavior.
Any help is appreciated!
Thanks
As for the reason: mjolinor outlined that - Get-EventLog parses the whole logfile, and then filters the output to meet your parameters. What we want to do right now is to parse the event log one by one from the newest entries while the condition is true.
$i = 0
$EventParser = do
{
Get-EventLog -ComputerName Localhost -LogName System -EntryType Error -Newest $i; $i++
}
while
(
(Get-EventLog -ComputerName Localhost -LogName System -EntryType Error -Newest $i | Select -Last 1).TimeWritten -ge ((Get-Date).Date.AddHours(-24))
)
$EventParser|Where-Object { $_.TimeWritten -ge ((Get-Date).Date.AddHours(-24)) } | Sort-Object -Property Index -Descending | Get-Unique -OnType
I have measured your command and the loop I have written - here is the output for my machine
For $EventParser:
TotalMilliseconds : 634,6669
For your command (I changed webserver1 to localhost)
TotalSeconds : 14,3049668
I hope the script above will do the trick to speed up log parsing.
PS.
I have ran into one thing that I couldn't figure out. As you see, I am actually filtering the output twice for, I believe, the same condition (!). If I remove the last-line Where-Object statement, I receive 35 entries for my machine and it lists output even from 4 days ago ?? (Normally I receive 19 entries both from mine and original command). I have had to, to my surprise, re-apply the filter to receive the desired scope. Can you assist with that in a comment or should I post a question on that?
EDIT:
Now the problem doesn't occur. Edit: I have tweaked the code a little bit, I noticed that in some cases it may return duplicated entries.
Best regards,
AlexP

PowerShell: get-eventlog takes too long to complete

I am trying to script the review of the past 30 days of the Application and System Event Logs on remote servers, looking for only Warnings, Errors, or Critical entries.
Borrowing from what I have found here and in other forums, I have come up with:
$Date = Get-Date
$Range = $Date.AddDays(-30)
$Range = $range.ToShortDateString();
$LogName = Read-Host "Which Log? (Application, System)"
$Server = Read-Host "Please Enter Server Name"
get-eventlog $LogName -ComputerName $Server -After $range | where {$_.EntryType -eq "Error" -or $_.EntryType -eq "Warning" -or $_.EntryType -eq "Critical"}
This seems to run fairly quickly, but then hangs several (5-10+) minutes before returning to a prompt, if it does....
Note: if I remove the code:
-After $range
I can simply break the output with ctrl-c and get on with my day, but I'd rather it run as intended and then stop...
So: Any ideas on how to eliminate this hang?
I am also open to ideas on how to make the code more elegant (and faster)!
And I wouldn't mind the script checking both the Application and System logs without having to run twice....
Using the -EntryType string-array parameter on Get-EventLog is much faster than retrieving the entire event log and then filtering with Where-Object
Try get-eventlog -Logname System -EntryType ("Error", "Warning")
However... if I put "Critical" in the -EntryType array, I get: The argument "Critical" does not belong to the set "Error,Information,FailureAudit,SuccessAudit,Warning" specified by the ValidateSet attribute. which makes me wonder whether you should be heeding the advice as listed in Get-Help Get-EventLog:
The cmdlets that contain the EventLog noun (the EventLog cmdlets) work
only on classic event logs. To get events from logs that use the
Windows Event Log technology in Windows Vista and later versions of
Windows, use Get-WinEvent.
Using Get-WinEvent instead, I think this is what you want:
Get-Winevent -FilterHashtable #{LogName="System","Application"; Level=1,2,3; startTime=$range}
That will check for events of level 1, 2, or 3 (Critical, Error, Warning, respectively), and search both the Application and System logs in the same invocation.
I found that for remote systems, I could query several systems at once faster than I could individually, using the same command, if I wrapped it into an Invoke-Command. This is my solution. The more systems, the more time it saved. YMMV
$command = {Get-EventLog -LogName Application -After (Get-Date).AddHours("-24")}
Invoke-Command -ComputerName "foo1","foo2","foo3","foo4" -ScriptBlock $command