Schedule a task to monitor a certain process start - windows

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'...

Keep in mind that using the task scheduler for this requires enabling auditing of ALL! processes on an OS-level. That can create quite a high load.
For monitoring a single process I would recommend creating a "permanent WMI event trigger". Details see here: https://learn-powershell.net/2013/08/14/powershell-and-events-permanent-wmi-event-subscriptions/
As a "consumer" you need to create a small VBscript as an "ActiveScriptEventConsumer" that starts the other process.

Related

Windows 10 - Run a command when connecting to a device, say, a dock or monitor [Automate]

In Windows 10, is there a way to run cmd/powershell commands automatically when PC is connected to a particular device like a dock? (Like connecting a particular device triggers a command)
I want to do something like this-
If [device1 connected] -> Run Command A
If [device1 disconnected] -> Run Command B
If [device2 connected] -> Run Command C
...
Yes.
https://www.winhelponline.com/blog/trigger-launch-program-script-connecting-to-specific-network/ describes using task scheduler to run a script on an Event Log event: anything that creates a notification in an event log can be used as the trigger.
Find an Event in an Event log: note the Log name and the Event ID.
Give your task a name in the General tab, and then click Triggers and then click New. Select "On an event": select the Log noted above, and enter the Event ID.
https://devblogs.microsoft.com/scripting/use-powershell-to-monitor-and-respond-to-events-on-your-server/ describes
using WMI as an permanent event consumer: event consumers can be linked to many Windows Events, including connect/disconnect events, not just Event Log events, but isn't as self-evident.
$consumerPath = Set-WmiInstance -Class ActiveScriptEventConsumer

How to use PowerShell to run some code upon system shutdown?

I'm provisioning a Windows VM that needs to run some PowerShell code when it boots. It also needs to run some different code when it shuts down.
To do the former, I can use New-JobTrigger and Register-ScheduledJob in my initial provisioning script like so:
$StartupTrigger = New-JobTrigger -AtStartup
Register-ScheduledJob -Name "Startup Job" -Trigger $StartupTrigger -Credential $DesiredCredentials -ScriptBlock {
Do-InterestingThings $using:ExternalResource
}
Doesn't even have to be a separate script file, it can just be a script block. Any variables from an outer scope will be serialized and used when the job runs. Pretty neat.
The real problem I'm solving involves creating an external resource whose lifetime is tied to the VM's uptime. When the VM is created, this resource will be created. When the VM is shut down, this resource needs to be cleaned up. How can I use PowerShell to run some code just before the VM is scheduled to shut down (regardless of how it got the order)? It doesn't need to be a script block, it can be a separate script file.
There are two reasonable ways to do this:
Local Group Policy:
This can be done in the local group policy editor: gpedit.msc. Navigate to Computer Configuration/Windows Settings/Scripts (Startup/Shutdown)/Shutdown. You can add 'Scripts' and/or 'PowerShell Scripts' here which get executed before other shutdown processes.
Event-Based Scheduled Task:
From this answer:
scheduled task as follows:
Type : On Event (Basic)
Log : System
Source : User32
EventID : 1074
When a user or command initiates a shutdown or restart as a logged on
user or on a user's behalf, event ID 1074 will fire. By creating a
task to use this to trigger a script, it will start the script and
allow it to finish
Note that this does not delay the shutdown (so has to be quick) and can sometimes fail to trigger before the task scheduler service stops.
Final Note:
Always make sure that your code can handle a dirty shutdown. After all, the fastest way to call a reboot is the power button...

Is it possible to trigger a script execution when stopping a windows service from services.msc?

I want to know if it is possible to configure a service to call a batch/powershell script when I stop it from services.msc.
While in Linux init.d services are fully programmable and even systemd services can have additional procedures I've yet to find a way to accomplish this on Windows.
Thanks in advance
You can configure services to run a program on failure, but if you are stopping the service via services.msc then that likely wouldn't count as a failure.
The only other option I can think of would be to set up a PowerShell script running as a scheduled task that either periodically checks the services running status, or (for a more foolproof option) looks at the event log for events indicating that the service has been stopped (since the last time the script checked) and then performs whatever actions you require.
Per the comment from montonero, you wouldn't need to run the scheduled task periodically as it could be configured to run when the event itself occurs. This is described here: https://blogs.technet.microsoft.com/wincat/2011/08/25/trigger-a-powershell-script-from-a-windows-event/
Use the Event Viewer “Attach Task to This Event…” feature to
create the task.
Launch "Event Viewer" and find the event. Once found, right-click on the event and select "Attach Task to
This Event...".

Launch script after Windows service start

I would like to launch script after windows service start or restart.
Like monitor wsupdate and at start or restart execute a batch script test.bat
Any ideas ?
That could be easily done with a scheduled task:
You just need to:
1) Start and Stop the Service to got the appropriate Events in the Eventlog.
2) taskschd.msc and create a new Costum Task. As Trigger you can select the Events created before with the start and/or stop action.
3) As Action call your cmd/bat, whatever you want.
Hint:
You also can export the Event in the XML Format, explained here:
http://blogs.technet.com/b/askds/archive/2011/09/26/advanced-xml-filtering-in-the-windows-event-viewer.aspx
and then import the XML Snippet into the Scheduld Task.

Detecting System Startup Event

I would like to execute a procedure that should be fired only upon windows system startup, and startup here does not mean program startup. Is there anything that I can do to trigger my procedure. If possible, i would like to avoid messing with the registry. I am using delphi 2010.
There are many options, but all will involve settings that require admin rights. These options include:
Put your routine in a service that is set to start automatically. This will start up when the system starts up and before any user has logged on.
Add an entry to HKLM\Software\Microsoft\Windows\CurrentVersion\Run. This will execute when an interactive user logs on.
Add a scheduled task with an appropriate trigger, e.g. At startup.

Resources