Programmatically Triggering a Task Scheduler Job with Windows Events

Intro

Do you use Windows Task Scheduler to run scheduled batch jobs? It could be used for a great deal of things, e.g. sending out scheduled email reports or run a machine processes at a timed interval. I use it for running daily data imports, running optimization scripts on the database, sending scheduled emails and Push Notifications etc. In this quick tutorial, I will show you how to trigger a scheduled job programmatically. And just in case you are thinking, what’s the big deal? Use SCHTASKS, then you should already know that SCHTASKS fails at running tasks that require elevated permissions on the same local server instance.

Problem Statement

Why trigger a scheduled job programmatically?

Task Scheduler is used to schedule a batch job / script / program to run at a schedule. Software like Google Chrome, Apple iTunes, Graphics Drivers, Adobe Flash, etc. all schedule jobs in the Task Scheduler to check for updates. While these are fairly simple use cases and work perfectly well as long as you want to run the job on a schedule. The problem is when you want to trigger them manually. An example would be an Updater Script that runs periodically to check for software updates. Now what if you want to provide the end user a functionality to also trigger the update check manually by pressing a button on your app’s UI. Or what if you have a financial web app running on a server that uses Task Scheduler to send out monthly billing statements to customers. Now you would need to give your users a way to request for the last statement at the press of a button as well, else you risk having frustrated customers.

Why not use SCHTASKS?

Ok for those who don’t know, SCHTASKS is the command line interface to Task Scheduler and can be used to create, edit and run jobs manually. Since it can run jobs, the first thought would be to kick off the job using a simple command like SCHTASKS /Run /TN <task-name>

From within C# you could use Process.Start to achieve the needful. Try the same thing if your job needs elevated permissions or another user account to run and you will see SCHTASKS failing. This is critical because a scheduled job may need to access restricted resources like an encrypted folder or perform administrative system functions. So how do we get around that?

Solution

Scheduled jobs can be configured to have triggers. The primary trigger in 90% of the use cases is a scheduled time when the job would need to kick off. However there are a few more trigger options as you will see in this screenshot below

You will notice that your job can be triggered by a number of trigger mechanisms, schedule being the most popular use case. But we want a programmable trigger. “On an event” is perfect for our case because we can generate an event in the Event Log. Let’s get working and see how to make it happen.

Step 1. Create the “Event Source”

You can use the eventcreate.exe command or use a PowerShell command shown below

Command Line

eventcreate /ID 1 /L APPLICATION /T INFORMATION  /SO MYEVENTSOURCE /D "My first log"

PowerShell 2.0

New-EventLog -LogName Application -Source MYEVENTSOURCE

What the above does is create a distinct Event Source for us. This allows are job to “listen” for events coming from a specific event source. If we define our own event source specific to our application, we can then take custom actions based on the eventid.

Now, let us review where we are:

  • We know how to create Scheduled Jobs/Tasks with Event based Triggers
  • We know how to create a Custom event source for our application
  • We can define a set of unique event IDs specific to our application (it can be any random numbers) that our code knows how to handle
  • What remains to be seen is how can we log an event into the Windows Event Log programmatically

Step 2. Create a Scheduled Task with an Event Trigger

The below screenshot explains it all. Scheduled Tasks are easy to create. Usually most tasks have a time schedule, for example, daily at 12 am. All we are doing different is adding a trigger whose trigger is an event, as shown in the screenshot below.

Now define the trigger to listen to an event as shown below

Notice how we picked our custom MYEVENTSOURCE in the Source select box. The number in the event id, 24311, is a custom event id and can be any number you want. You may have different tasks listen for event ids. For example, I may configure a job to run for Client A when the event ID is 24311 or a Client B when the event ID is 24312. It purely is our choice.

Step 3. Log an Event from code

You can do this with almost any programming language, but in my example I will use C#.


var source = "MYEVENTSOURCE";

try
{
    EventLog.WriteEntry(source, "Run Import", EventLogEntryType.Information, 24311);
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

Yep, now watch your Scheduled Task kick off automatically when this C# snippet logs an event.

Conclusion

Well, now you know this neat trick that can start your job programmatically on-demand. I have found this extremely useful in scenarios where I was earlier planning to use a Windows Service, but I could eventually void writing and configuring services by simply using the powerful Task Scheduler which is a part of your Windows OS and configuring programmatic event triggers. Hope this helps you in some way.

Upgrading MonoDevelop to the latest stable build on Linux Mint / Ubuntu

All those developing with MonoDevelop on Linux Mint or Ubuntu must have noticed that the software repository does not provide the latest release of MonoDevelop (3.0.3.5 as of this writing). The only way to get to the updated version is to compile it on your own. Compiling a big project like Monodevelop on Linux usually scares the crap out of some, specially those migrating in from Windows backgrounds. Although there is nothing special about it, you satisfy project dependencies and compile using the provided tools. Also it is basically a standard linux three step process, configure, make and make install.

In spite of all of that, there are some of us who believe in keeping things simple. That allows us to channel our creative energy and spirit into other things that matter. I obviously don’t want to fight dependencies after dependencies and have no energy left to work on my own project. So here is a the best way I have found to make a clean build of Monodevelop from fresh stable source code. Actually the credit goes to John Ruiz who put up this simple shell script that does the job for us. Get his script fromĀ https://raw.github.com/jar349/tools/master/install-monodevelop.sh and save it to a folder. Usually it would land up in your Downloads folder in your home. Make sure to give it “execute” permissions. You can use the UI, right click the file, go to Properties, select Permissions tab, and check the box that says “Allow executing file as a program” With that done, now you need to start your Terminal, navigate to the Downloads folder and run the script as ./install-monodevelop.sh

It will do a bunch of stuff and by the end of its run, it will have monodevelop built and installed. Simply type monodevelop on the command line to run! Yep you are done!

Android Development Beginning

Having begun learning Android development a little while back, and today I made some excellent progress. In order to get all my knowhow straight, I planned to create a simple app that would show me a list of people in a group. The list of people will be shown using a ListView control on the Android UI. The App would fetch this information from a RESTful Web Service written in ASP.NET C# on the Mono platform. I plan to use JSON as my choice of data communication format. Internally, the ASP.NET service will pull this information from a PostgreSQL Server.

Here is how I approached the task. I quickly threw in a table on my PostgreSQL installation which contained the names of people I want to show. On Monodevelop, I created a ASP.NET project with a simple ASPX page that dumps out a JSON for the list of users. To fetch the data from PostgreSQL we need a library called npgsql. Its pretty slick and gets the job done. Using standard mechanisms, I was able to pull data from the database and convert into a readable JSON.
The most important and challenging part (for me) came after this. That is, how to consume this service in my Android application. Coming from C# Windows Forms background, I am used to doing this in a line or two and if the call is small enough, I don’t even bother making it Async. But Android really wanted me to make the network call on a separate thread, and it did make sense! They enforced a good practice from the very beginning. Alright, so my quick reading led me AsyncTask<> class. I found some really nice tutorials on it’s implementation, specially this one: http://www.vogella.com/articles/AndroidPerformance/article.html
I faced an interesting situation here. I was trying to access my local ASP.NET server via a standard URL format like http://localhost:8080/ but that always threw an exception at me that the connection was refused. Then I tried browsing that URL from the Android emulator and that too failed. It took a while but it did strike me then, that localhost would be a loopback address on the emulator itself, not the host development machine. A quick search showed me that the emulator then uses the IP 10.0.2.2 for loopback on the host machine. Modifying my url to http://10.0.2.2:8080/ worked on the Android browser. Pretty sure it would run in my code as well, I ran my App, which to my not-my-surprise, threw the same exception.
Digging further over the internet, I realized I had missed a very basic step. Asking permissions on Android to use the Internet service. So all I had to do was put in a line in the Manifest file like:
The next I ran the App, and viola! it worked! But hey, that didn’t work all the way till showing it on the UI as a list. It only pulled the JSON string into the variable.
I now had to parse the JSON and appropriately get it into a Java consumable format. Gson by Google came to my rescue, which is a nice little framework for working with JSON on Java. I added references to it on my project and wrote some test code to see how it works. It was simple, clean and perfect. You use a Gson class, initialize it, and simply call the fromJson method to convert a JSON string to the desirable type.
Now came another roadblock, i.e. to bind it to the list view. The way ListView works is that it has an Adapter for it which can be of any custom implementation type. I used a standard ArrayAdapter and set it to the ListView. What kept tripping it off was the fact that the ListView would not consume the adapter on a thread other than the UI thread. Now this is pretty basic in the Windows Forms world and I should have thought the same would be true here. Solution would have to be similar as well, and as I found out, there is a very much similar method in Android called the runOnUiThread which takes a delegate, similar to the Invoke method on controls in Windows Forms. Now I gave a final run and yeah it was the Eureka moment to see everything working. Even after 6 years of programming, sometimes the smallest of achievements in new areas turns me on. Yeah to an extent that I spent this much writing about it… Though this write up is just for my own log purpose in an effort to track the development process of whatever it is that I am developing.
I am following a self imposed Agile Development methodology and am attempting to follow a Sprint cycle. Sprints are short burst of all round developments that enable us to understand the end-to-end process from the very beginning. For example, in my really silly simple project, I learned how to get PostgreSQL installed on my Linux box, how to get it working on C# in Mono and finally how to consume it on an Android App. This allowed me to do an integrated test of all three work environments that will form the major part of my upcoming days in deep development…
I will sign off now and log my next effort!