I'm trying to tie two applications together, so that when one is started the other starts too.
I expected to find this in Task Scheduler under Events > Application or something like that, but only some applications have event sources there.
So I researched and found that you can detect a process start by registering a WMI event.
Register-WMIEvent -Query "SELECT * FROM __InstanceCreationEvent WITHIN 3 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name = 'notepad.exe'" -sourceIdentifier 'NotepadStarted' -action {if(!(ps AutoHotKey)) { start Automator.ahk}}
However this is meant to run all the time, which means a powershell.exe process in the background, and WMI polling every 3 seconds (WITHIN 3
- yes I do need it to respond ASAP). The PC is powerful enough for this job as is, but if in the future I want to watch more than one app, this approach may turn out to use too much resources.
Is there a better way of watching for a process start on Windows? Without polling or running a script continually in the background, but rather simply scheduling a task to respond to the event of Notepad having started?
I have found a way through Auditing, which seems to work alright. We're trying to get the process to raise an event when it starts, then in Task Scheduler to home in on that event as the trigger for our action.
UPDATE: Conjoined Twins - IFTTT-style application actions using auditing and scheduled tasks under Windows. It's a Powershell script that helps you set this up.
LATER EDIT: OK it does produce a few false positives. The action may fire without the program having actually been executed. So beware.
Go to your application.exe
, right click > Properties > Security tab > Advances > Auditing tab > Edit
Add your username and tick Traverse folder / execute file. Click all of the OKs. Every successful execution of application.exe
will now show up in Event Viewer. Go there to check them out:
Event Viewer > Windows Logs > Security You can Filter current log for EventID 4663
Here is an event like that from my machine:
An attempt was made to access an object.
Subject:
Security ID: PC\Redacted
Account Name: Redacted
Account Domain: PC
Logon ID: 0xxxxxxx
Object:
Object Server: Security
Object Type: File
Object Name: C:\Program Files\Some Application\application.exe
Handle ID: 0x1e1c
Process Information:
Process ID: 0x374
Process Name: C:\Windows\explorer.exe
Access Request Information:
Accesses: Execute/Traverse
Access Mask: 0x20
You'll see more than one of these, it's not just one-to-one, 1 program start = 1 event. There are A handle was open, A handle was closed events as well.
In Task Scheduler you have to now create an event to target the program start.
Create New Task > Triggers Tab > New
Select Begin task: On an event from the drop-down.
Click the Custom radio button then Edit Event Filter... button
In the XML tab tick Edit query manually and paste something like this in:
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">*[EventData[Data[@Name='ObjectName'] and (Data='C:\Program Files\Some Application\application.exe')]]
</Select>
</Query>
</QueryList>
¹
Pictures and more details at Quick Development Tips: How to monitor a folder and trigger an action for incoming files, in Windows 7
Once this is done, all that's left is to set up your Action, the program you want to run when application.exe
starts. For me it was an AutoHotKey script - I just clicked Browse and navigated to it.
Now when I start the app I get that AutoHotKey script automating some initial steps. It wouldn't have worked to just create a batch file with application.exe & script.ahk
in it, because sometimes the app starts from opening a file, sometimes it's started by something else, or who knows. This way no matter how it starts, script.ahk happens.
¹ Side note: Here's a catch. This XPath query works for Data='C:\no\wildcards\allowed.exe'
but you'll be disappointed to find that you can't use wildcards or any other kind of matching. So if you want to select a file that doesn't move or change name, that's fine. But if you want to select a newly created file of unknown name inside a folder you're watching - you can't. At most you can do Data='variant1' OR Data='variant2'...