Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Implementing a small Cron service in C#

0.00/5 (No votes)
14 Jul 2005 1  
This article shows how to use the attached C# Cron class to implement a small Cron service.

Introduction

The Cron class provided with this article implements a small and effective Cron implementation for Windows.

Background

You can schedule the execution of Windows programs using the Scheduled Tasks Control Panel application, and there are already many CodeProject articles related to scheduling in other fashions. So if you are reading this article, I am going to assume that you already have your reasons to implement Cron-style scheduling in C#.

This Cron scheduler is originally part of an application I created for my work, but I have separated out the Cron class for this article. (BTW, I have written the code using Java-style initialCaps on the methods and associations. You'll just have to live with that or change it yourself.)

Using the code

The Cron scheduler is implemented in a single class, CronService.Cron (CronService is the namespace I thought up for this article, but you may want to change this into the default namespace for your Cron application).

You can start an instance of this class using the start() method, which simply starts the scheduler and never returns. For instance, you can link the code below with the Cron class to create a regular Windows executable (for use in Windows' Startup Programs folder, for example):

using System;

namespace CronService
{
    class CronMain
    {
        [STAThread]
        static void Main(string[] args)
        {
            Cron cron = new Cron ();
            cron.start ();
        }
    }
}

I could imagine that you want to create a Windows service instead. To learn how that is done, I recommend the CodeProject tutorial Creating a C# Service Step-by-Step by Terry Denham.

Once you have set up a Windows service like described there, it is a simple matter of filling in the template ServiceBase class that you have created. There is only one small caveat: the OnStart method that you will implement here, is expected to return after 20 seconds or so, so you will have to start the perpetually running scheduler in a separate thread.

The example below provides you with a very stripped down version of doing just that. Please use this code only as a hint when creating your own service.

using System.Threading;

namespace CronService
{
    public class CronService : System.ServiceProcess.ServiceBase
    {
        private Cron cron;
        private Thread thr;

        public RecoveryService()
        {
            cron = new Cron ();
            thr = new Thread ( new ThreadStart (cron.start));
            thr.Name = "cron";
        }

        protected override void OnStart(string[] args)
        {
            thr.Start ();
        }
 
        protected override void OnStop()
        {
            thr.Abort();
        }
    }
}

Creating a valid Cron file

The Cron class reads a file cron.tab from its current directory. The syntax of this file is as good as compatible with that described in the UNIX manpage crontab(5).

Environment variables and percentage signs for newlines are not supported, and, unlike the original Cron, the command line is not interpreted by a shell. Instead, the first word is assumed to be the executable, and the rest is passed as arguments to this executable using the System.Diagnostics.Process API.

As crontab fields are separated by whitespace, a single preceding backslash may be used to escape a space character in the command field. And to be complete, a double backslash may be used to escape a single backslash when it's unfortunately placed before an unsuspecting space character. At any other place, a single backslash will do just fine.

An example:

# DoThis every hour
0 * * * * C:\Program\ Files\MyProg\DoThis.exe arg1 arg2
# DoThat -- well, you figure out when :-)
8-9/2 12,13,14-18 * * * C:\Program\ Files\MyProg\DoThat.exe

Points of Interest

The Cron class is small and effective, but did I mention small? There are some limitations that you should be aware of:

  • Cron only reads the cron.tab file at startup. You need to restart Cron if you want changes to cron.tab to become effective. There are no multiple crontabs, nor is there a crontab(1) command.
  • Cron does not mail any program output to the system administrator, as you may be used to from UNIX. Instead, it only reports when a program exits with a nonzero exit code.
  • The reportError() function is left empty as an exercise to the reader.

Closing note: while Paul Vixie achieved immortality with his Cron implementation, I wrote mine in a single day or so. This is of course mainly due to the advanced DateTime and String functions available in the .NET API.

The code within this tutorial is free to use, but please, credit where credit is due.

History

  • July 14, 2005 -- First version of this article.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here