Write a Windows Service in PowerShell

Previously I showed you the new Windows Application engine (https://www.sapien.com/blog/2017/06/14/new-script-engines-for-windows-powershell/) and the Windows System Tray engine https://www.sapien.com/blog/2017/07/10/creating-a-system-tray-application-with-powershell/.
Today I will show you the last of the three new engines, the Windows Service engine.

Writing a Windows Service can be a challenging experience, even for a programmer. Generally, unless you do that exact thing for a living, nobody writes a Windows Service very often. So most folks don’t have a lot of experience with this particular task.
You do what most programmers do, you Google the task at hand. If you google “write a windows service in powershell” the first hit points to an MSDN magazine article: https://msdn.microsoft.com/en-us/magazine/mt703436.aspx
My compliments to the author, Jean-Francois Larvoire, who did a great job explaining the intricate details of building a service in Windows PowerShell.
If you do this very often, you should definitely read that article.

But, for most of us, this is not a very frequent task. So I will show you a way of doing this without knowing much about services or C#. All you need is PowerShell. Instead of using a script from somewhere on the internet we use a one-liner today.

Get-Process solitaire -ErrorAction SilentlyContinue | Stop-Process –PassThru

I am assuming you can see that this will simply terminate any process named ‘Solitaire’. We will call our service “SolitaireKiller”
Just as previously with the System Tray Application in the last post, the script needs a loop, so it executes the code inside again and again. Also like the tray app, we need to sleep in between iterations so we don’t hog a CPU core for no reason.
For terminating a solitaire game it is not necessary to do that within a second of startup anyway, so we just go with a minute. I don’t think many folks will finish a game in that time.

while($true) {
Get-Process solitaire -ErrorAction SilentlyContinue | Stop-Process –PassThru
Start-Sleep –Seconds 60
}

Run that as a script and it will just kill any Solitaire game you are playing within a minute. We do want to get a notification when a process was terminated, so we make a little adjustment to our script

while($true) {
$ProcessList = Get-Process solitaire -ErrorAction SilentlyContinue
if($ProcessList) {
Write-Host “Terminating Windows Solitaire process”
$ProcessList | Stop-Process –Force | Out-Null
}
Start-Sleep –Seconds 60
}

That’s all. So now we make that a service. Package your script with the Windows Service engine and the PowerShell version most appropriate for your script.

image

Make sure you enter all pertinent information in the Version settings.

image

 

Services need to be installed on a system. To make your life easer, all that is also already build in. All you need to do is run the service executable from an elevated command prompt with /i (as in install)
image

Now you can look at your service control panel and you will see the Solitaire Killer service. Remember the items you wrote in the ‘Product name’ and ‘Description’ fields for the version information? They are automatically used for the service name and description.

image

So now go ahead and start that service. Launch a game of Solitaire and wait. Within a minute it will be gone.
Now look at your event log. What you wrote there with Write-Host (or any other PowerShell output mechanism) will show up here in the Application Event Log.

image

 

image

To remove the service from your system, simply stop the service and use the /u parameter (as in uninstall) and it will be gone. Please note that it may take a few seconds to exit and that you may need to restart the services control panel to see that.

 

You can download the script and the packaged executables from here: https://sapien.s3.amazonaws.com/Blog_Post_Files/SolitaireKiller.zip

As always, if you have any ideas, comments, feedback, please use our feedback forum and reference this post.
https://www.sapien.com/forums/viewforum.php?f=23