How to include ProviderName in the command that gets event logs in the past ten hours - windows

$A = #{}
$A.Add("StartTime", ((Get-Date).AddHours(-10)))
$A.Add("EndTime", (Get-Date))
$A.Add("LogName", "System")
(Get-WinEvent -FilterHashtable $A|Select TimeCreated, ProviderName, Message|FL)
The above commands will get all "System" event logs in the past 10 hours. However, I want to get only the event logs of "Microsoft-Windows-WindowsUpdateClient" in the past 10 hours. I tried the following line, which caused an error.
$A.Add("LogName", "System" ; "ProviderName", "*UpdateClient")
How should I include "ProviderName" in the command?

You have to add another key and value using Add method
$A.Add("ProviderName", "*UpdateClient")

Related

How do I write a Windows 10 script to increment a counter by 1 each time a print job prints?

I'd like to write a script for Windows 10 to add 1 to a count in a .txt each time a print job completes. Ideally a separate count for each day, so I can see how many print jobs were completed in a day.
Any help in understanding how to go about this is appreciated!
The print service already logs every time it prints - you just need to enable the appropriate event log channel and consume the resulting log events:
# Enable the Microsoft-Windows-PrintService/Operational log channel
wevtutil.exe set-log Microsoft-Windows-PrintService/Operational /enabled:true
Now that the log channel is enabled, the print service will log an event with event ID 307 everytime it executes a local print job. Since the log events all have timestamps, getting a count per day is as simple as using the Group-Object cmdlet:
# Fetch the print job events from the event log
$printJobEvents = Get-WinEvent -FilterHashtable #{ LogName='Microsoft-Windows-PrintService/Operational'; EventId=307 }
# Group by date logged, to get a count-per-day
$printJobEvents |Group-Object { '{0:yyyy-MM-dd}' -f $_.TimeCreated.Date } -NoElement |Sort-Object Name
One technique that might be useful is to query stats for the spooler service like this:
Get-CimInstance 'Win32_PerfFormattedData_Spooler_PrintQueue' |
Format-Table -Property Name,Jobs,TotalJobsPrinted,TotalPagesPrinted -AutoSize
This gives output like this:
Name Jobs TotalJobsPrinted TotalPagesPrinted
---- ---- ---------------- -----------------
Printer1 0 50 212
Printer2 3 13 118
Printer3 1 33 306
_Total 4 96 636
The stats are reset each time the Print Spooler service restarts, so you'll need to take that into account in your final script, which might make this a trickier option than Mathias' event log solution.

Powershell giving wrong output after scheduling with window's task scheduler

I have a PowerShell script to check the password expiry date of the a system user and send a mail if it is going to expire within 10 days. Script works fine when we run it stand alone. But it show abnormal behaviour after scheduling it with windows task scheduler. Sometimes it works perfectly fine and sometimes it's not.
Output: Password will Expire in -736235 Days.
Expected output: Password will Expire in Days.
It always give -736235 days when if runs incorrectly.
Here is the configuration,
1.General tab
- Run whether user logged in or not
- Run with highest Privilege
- Configure for : Windows server 2012 R2
Action Tab
Program/script: PowerShell
-Add Argument: .\ps.ps1
Start in: D:
Setting Tab(Following Options are checked)
-Allow task to run on demand
Stop task if it running from: 3 days
-if the running task doesn't stop when requested, force stop
If the task is already running then following rule will apply: Stop the existing instance.
Please let me know if you need any other details,
Thanks,
Navdeep
Script is,
$user = Get-ADUser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False -and Name -eq "<user_name>" } –Properties "DisplayName", "msDS-UserPasswordExpiryTimeComputed" | Select-Object -Property "Displayname",#{Name="ExpiryDate";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}}
$DayCount = $user.ExpiryDate - (GET-DATE)
$DayAbsCount = $DayCount.Days
$message.body = "Password will Expire in $DayAbsCount Days.Please reset."
if ( $DayAbsCount -lt 10)
{
$smtp = new-object Net.Mail.SmtpClient($smtpserver)
$smtp.Send($message)
}
,
and the script is running from the same account whose pwd expiration date we needed.

Setting counter on Windows Event log for Email notification

I am having below script:
$pattern = 'Unable to authenticate user!'
$events = Get-WinEvent -ea SilentlyContinue `
-ProviderName "Windows DB Controller - Task Manager Service"|
Where-Object { $_.TimeCreated -gt [datetime]::today -and $_.Message -match $pattern }
$events >> D:\Error.txt
if ($events) {
Send-MailMessage -SmtpServer smtp.domain.com -From No-reply#domain.com -To sunny#domain.com -Subject 'Error found in log' -Body $events
}
I had scheduled it to run on every 10 mins and purposely ,I wanted to achieve following point using above script:
Search the specified error message in the event viewer log only for current-date and as soon as the error message encountered send a email notification to me but didn't want to receive email notification for the error message which appreared today and for which I had already been notified (I mean , wanted to receive error-notification only once for a specific time of current day).
But problem I am facing here is: Getting multiple notifications for same error message for which already being notified.
I hope I am clear enough to put my exact problem.
Could you please help me out, how to resolve this problem ?
If you are running the script every 10 minutes, I would change the condition on the Where-Object so instead of getting all of the events that are "today"; I would change it to get only the events that happened in the last 10 minutes. i.e. the code becomes:
Where-Object { $_.TimeCreated -gt [datetime]::now.AddMinutes(-10) -and $_.Message -match $pattern }
Have a look at this thread:
Powershell - Tail Windows Event Log? Is it possible?
It's on tailing an event log, but the same method should work for what you're tyring to do. Just save the last index number to a file between runs.
How about the following approach:
Register-WmiEvent -Query "select * from __InstanceCreationEvent where TargetInstance ISA 'Win32_NTLogEvent' and TargetInstance.SourceName = 'Windows DB Controller - Task Manager Service' and TargetInstance.Message LIKE '%Unable to authenticate user!%'" -SourceIdentifier "MyEventListener" -Action {
#Your actions
write-host "$($eventargs.NewEvent.TargetInstance.RecordNumber) at $($eventargs.NewEvent.TargetInstance.TimeGenerated)"
}
It uses WMI to subscribe to the event that occurs when an eventlog entry is generated with your criterias. The action itself will only return the new object(so no more duplicates). I've included a sample action to help you understand how to access the object. This method will give you live monitoring.
Inside the action, $eventargs.NewEvent.TargetInstance will give you the object which is an instance of win32_ntlogevent. To see properties of this class, check out TechNet or run the following command:
([wmiclass]'win32_ntlogevent').Properties | ft Name
To make the script run forever, just call your script with powershell -file script.ps1 -noexit or include a while($true) loop at the end of your script. (I'm not sure how the while-loop will affect resource usage longterm, you'd have to test).

tailing log file on windows2008 server

I use the following command to tail a logfile on a w2k8 server from a windows8 client pc:
get-content "file" -wait
The log file shows up and it sits there patiently waiting for new lines to be added,
but new lines never show up when they are added.
It worked fine on w2k3 server but somehow tailing on w2k8 server does not work.
The log file is updated from a C# service:
Trace.Listeners.Add(new TextWriterTraceListener(logFileName, "fileListener"));
Trace.WriteLine(....)
Does anybody know what to do about this?
I repro'd the issue on my WS08 system using Trace class. I tried both Trace.Flush() and writing lots of data (100K) and neither caused get-content -wait to respond.
However I did find a workaround. You'd have to update your C# program. (While experimenting I came to the conclusion that gc -wait is pretty fragile.)
$twtl= new-object diagnostics.TextWriterTraceListener "C:\temp\delme.trace",
"filelistener"
[diagnostics.trace]::Listeners.add($twtl)
# This sequence would result in gc -wait displaying output
[diagnostics.trace]::WriteLine("tracee messagee thingee")
[diagnostics.trace]::flush()
# Here I did file name completion such that c:\temp\delme.trace was in the
# completion list.
# In other words I typed something like d and pressed tab
# And this worked every time
# After searching for quite a while I finally found that
# get-itemproperty c:\temp\d*
# produced the same effect. The following sequence always worked:
# (without requiring a tab press)
[diagnostics.trace]::WriteLine("tracee messagee thingee")
[diagnostics.trace]::flush()
get-itemproperty c:\temp\d*
# To finish up
[diagnostics.trace]::Listeners.remove($twtl)
$twtl.close()
$twtl.dispose()
I think there's a bug somewhere. I suggest filing it on the Connect website.

Query windows event log for the past two weeks

I am trying to export a windows event log but limit the exported events not according to number but according to time the event was logged. I am trying to do that on windows 7 and newer. So far my efforts are focused on using wevtutil.
I am using wevtutil and my command line now is: wevtutil Application events.evtx The problem here is that I export the whole log and this can be quite big so I want to limit it just to the last 2 weeks.
I have found this post but first of all it does not seem to produce any output on my system(yes I have changed the dates and time) and second it seems to be dependent on the date format which I try to avoid.
Here is the modified command I ran:
wevtutil qe Application "/q:*[System[TimeCreated[#SystemTime>='2012-10-02T00:00:00' and #SystemTime<'2012-10-17T00:00:00']]]" /f:text
I had to replace the < and > with the actual symbols as I got a syntax error otherwise. This command produces empty output.
The problem is due to /q: being inside quotes. It should be outside, like:
wevtutil qe Application /q:"*[System[TimeCreated[#SystemTime>='2012-10-02T00:00:00' and #SystemTime<'2012-10-17T00:00:00']]]" /f:text
This works just fine for me.
For the events of the last 2 weeks, you could also use timediff, to avoid hard-coding dates.
Windows uses milliseconds, so it would be 1000 * 86400 (seconds, = 1 day) * 14 (days) = 1209600000.
For your query, that would look like
wevtutil qe Application /q:"*[System[TimeCreated[timediff(#SystemTime) <= 1209600000]]]" /f:text /c:1
I added /c:1 to get only 1 event in the example, since there are many events in the last 2 weeks.
You may also want to only list warning and errors. For that, you can use (Level=2 or Level=3). (For some reason, Level<4 doesn't seem to work for me on Win7)
wevtutil qe Application /q:"*[System[(Level=2 or Level=3) and TimeCreated[timediff(#SystemTime) <= 1209600000]]]" /f:text /c:1
I don't know how you feel about PowerShell, but it's available on all the systems you tagged.
From a powershell prompt, see Get-Help Get-EventLog -Examples for more info.
If you have to do this from a .cmd or .bat file, then you can call powershell.exe -File powershell_script_file_name
where powershell_script_file_name has the Get-EventLog command(s) you need in it.
This example gives all the Security Event Log failures, I use to audit systems:
Get-EventLog -LogName security -newest 1000 | where {$_.entryType -match "Failure"}
I strongly recommend using LogParser for this kind of task:
logparser -i:evt file:query.sql
With query.sql containing something like this:
SELECT
TimeGenerated,EventID,SourceName,Message
FROM Application
WHERE TimeGenerated > TO_TIMESTAMP(SUB(TO_INT(SYSTEM_TIMESTAMP()), 1209600))
ORDER BY TimeGenerated DESC
The somewhat unintuitive date calculation converts the system time (SYSTEM_TIMESTAMP()) to an integer (TO_INT()), subtracts 1209600 seconds (60 * 60 * 24 * 14 = 2 weeks) and converts the result back to a timestamp (TO_TIMESTAMP()), thus producing the date from 2 weeks ago.
You can parameterize the timespan by replacing the fixed number of seconds with MUL(86400, $days) and changing the commandline to this:
logparser -i:evt file:query.sql+days=14
You can also pass the query directly to logparser:
logparser -i:evt "SELECT TimeGenerate,EventID,SourceName,Message FROM ..."

Resources