I never thought the Task Scheduler could be used at such a granular level, but I was wrong. This is amazingly useful.
You may or may not know that the Task Scheduler can be used to trigger a task based on stuff in the Windows Event Logs. Sure, it can be used to trigger a task when the computer resumes from standby (Log: System, Source: Power-Troubleshooter, EventID: 1) but... did you know that you can trigger a task based on the DATA in the log (specifically the WakeSource)? Here's how:
The back-story:
I wanted to schedule a task that gets executed only when the computer wakes from user input. I have been using a script for a long time that executes the following command:
Code: Select all
powercfg -lastwake | find "USB\ROOT_HUB"
This works most of the time. However, the powercfg command occasionally gets an error which causes a Windows dialog to be displayed which says something about powercfg getting an error, and it waits until someone presses a "Close program" button. When this happens, it totally messes things up with my automation macros. I have been unsuccessful at finding a resolution to the problem, and I am unwilling to re-install Windows in the hope of fixing the problem.
I wrote a program that automatically clicks the "Close program" button and tries to run powercfg again, but this is less than optimal in my configuration.
So... I started looking at the Windows Event Viewer and Task Scheduler to see if there was a way to trigger a task when the computer wakes due to user input on a USB device (keyboard, mouse, remote-control, etc).
I found that it is possible to create a schedule task in the Windows Task Scheduler that only runs when certain criteria are found in a system log entry. Here are the details...
In the case of my problem, I opened the Event Viewer, expanded the "Windows Logs" folder, and then clicked on the "System" log. Next, I scrolled down the list of log entries until I found the one with a source of "Power-Troubleshooter". I then double-clicked on that entry to open a dialog that shows more information about the event. Finally, I clicked on the "Details" tab, and chose the "XML View" radio button. Here's what you will see: The picture doesn't show all of the XML data, but here's the whole thing:
Code: Select all
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-Power-Troubleshooter" Guid="{CDC05E28-C449-49C6-B9D2-88CF761644DF}" />
<EventID>1</EventID>
<Version>1</Version>
<Level>4</Level>
<Task>0</Task>
<Opcode>0</Opcode>
<Keywords>0x8000000000000000</Keywords>
<TimeCreated SystemTime="2013-04-12T22:21:59.251222300Z" />
<EventRecordID>302143</EventRecordID>
<Correlation ActivityID="{D06482C0-1EAB-4EDF-A2C5-71687EF36751}" />
<Execution ProcessID="1816" ThreadID="3396" />
<Channel>System</Channel>
<Computer>HTPC-PC</Computer>
<Security UserID="S-1-5-19" />
</System>
<EventData>
<Data Name="SleepTime">2013-04-12T22:21:11.865241900Z</Data>
<Data Name="WakeTime">2013-04-12T22:21:48.340803200Z</Data>
<Data Name="SleepDuration">7177</Data>
<Data Name="WakeDuration">1841</Data>
<Data Name="DriverInitDuration">1368</Data>
<Data Name="BiosInitDuration">1050</Data>
<Data Name="HiberWriteDuration">0</Data>
<Data Name="HiberReadDuration">0</Data>
<Data Name="HiberPagesWritten">0</Data>
<Data Name="Attributes">20736</Data>
<Data Name="TargetState">4</Data>
<Data Name="EffectiveState">4</Data>
<Data Name="WakeSourceType">4</Data>
<Data Name="WakeSourceTextLength">12</Data>
<Data Name="WakeSourceText">USB Root Hub</Data>
<Data Name="WakeTimerOwnerLength">0</Data>
<Data Name="WakeTimerContextLength">0</Data>
<Data Name="WakeTimerOwner">
</Data>
<Data Name="WakeTimerContext">
</Data>
</EventData>
</Event>
This gives me a nifty filter box that allows me to filter on some things. It's actually not bad, but it doesn't go as deep into the details as I want. To be honest, I filled out this page with as much information as I knew about the event that I wanted to use as a trigger. So, on the "Filter" tab, I filled out all the information I knew.
Then, I clicked on the "XML" tab. This showed me the XML query that was generated by the information I entered on the "Filter" tab.
I then clicked the "Edit query manually" check-box, and updated the query as follows:
Code: Select all
<QueryList>
<Query Id="0" Path="System">
<Select Path="System">
*[System[Provider[@Name='Microsoft-Windows-Power-Troubleshooter'] and (Level=4 or Level=0) and (EventID=1) and TimeCreated[timediff(@SystemTime) <= 120000]]]
and
*[EventData[Data[@Name='WakeSourceText'] and (Data='USB Root Hub')]]
</Select>
</Query>
</QueryList>
I think the rest is self-explanatory. It allows you to find stuff in your Windows Event logs, and create triggers in the Task Scheduler that can start tasks based on just about any data point in the event logs.
I hope this helps some people. Any questions, just post below.