Click here to Skip to main content
15,885,216 members
Articles / Programming Languages / C#
Article

Winding Back the System Clock

Rate me:
Please Sign up or sign in to vote.
2.08/5 (8 votes)
5 Jul 2006CPOL4 min read 35.4K   15   6
Launch an application after temporarily change the system clock.

Introduction

I recently launched the Beta version of an application which I had been using for some time, and was somewhat alarmed when I was delivered a message advising that the Beta version's time had expired! This I had not been expecting, and I was in quite a spot as the project I was developing was not finished.

Clearly, the application had looked at the system clock, and I wondered if putting the clock back for the time being would enable me to continue using the application. I manually changed the year back to 2005, and found that the application now launched normally. Further, it continued to run normally even after I reset the clock.

Now, using a backdated system clock is no way to live, so I wondered if I could backdate the clock, launch the application, then reset the clock, all within one utility. The answer turns out to be yes, and it is quite straightforward, which is not to say that discovering how to achieve it was straightforward.

I ideally wanted to devise a console application, since there was no need for a form. I just wanted to launch the application by clicking an item on the Taskbar, as I had always done.

A working example

Launching an application from within another is easily done. Let us see if we can launch Solitaire from within a console application. The following code will do it (I copied SOL.EXE to C:\ to keep the source simple - be aware you must specify a fully qualified path to the application which you wish to launch):

Start up a new console application project, and paste the following:

C#
using System;
// For Process.Start
using System.Diagnostics;

// using System.Runtime.InteropServices; For later

namespace ConsoleApplication_LaunchSolitaire
{
    class Program
    {
        static void Main(string[] args)
        {
            Process.Start(@"C:\SOL.EXE");
        }
    }
}

When you run this application, you will see the DOS screen for a moment and Solitaire will launch.

That DOS screen is something of a nuisance, so we will need to get rid of it. But first, how would we set the clock back to 2005 before launching Solitaire? I found a lot of information (and mis-information!) on this matter, most of which was not very helpful, before coming across some definitive code at PINVOKE.NET. See SetLocalTime (kernel32).

Armed with this, we are now able to backdate the clock, launch Solitaire, then reset the clock. The full code is as follows (if you read Yuan Xiaohui's article first, the code should be self explanatory):

C#
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace ConsoleApplication_LaunchSolitaire
{
    class Program
    {
        [DllImport("Kernel32.dll")]
        public static extern bool SetLocalTime(ref SYSTEMTIME Time);

        // The structure needs to be spelt out in full, even though
        // we will only be using wYear
        public struct SYSTEMTIME
        {
            public ushort wYear;
            public ushort wMonth;
            public ushort wDayOfWeek;
            public ushort wDay;
            public ushort wHour;
            public ushort wMinute;
            public ushort wSecond;
            public ushort wMilliseconds;

            public void FromDateTime(DateTime time)
            {
                wYear =         (ushort)time.Year;
                wMonth =        (ushort)time.Month;
                wDayOfWeek =    (ushort)time.DayOfWeek;
                wDay =          (ushort)time.Day;
                wHour =         (ushort)time.Hour;
                wMinute =       (ushort)time.Minute;
                wSecond =       (ushort)time.Second;
                wMilliseconds = (ushort)time.Millisecond;
            }
        }

        static void Main(string[] args)
        {
            int offset = DateTime.Now.Year - 2005;
            SYSTEMTIME st = new SYSTEMTIME();

            // Set clock to 2005
            DateTime t2005 = DateTime.Now.AddYears( - offset );
            st.FromDateTime(t2005);
            SetLocalTime(ref st);

            // Launch
            Process.Start(@"C:\SOL.EXE");

            // Reset clock
            DateTime tCurrentYear = DateTime.Now.AddYears( + offset );
            st.FromDateTime(tCurrentYear);
            SetLocalTime(ref st);
        }
    }
}

Once this has been built, close down the project, and run the application from the Run menu, or via a shortcut which you will know how to construct. This will give you a better real time view of what is happening.

Two things remain to be done. Firstly, in the working example, Solitaire launches without the system clock being checked, and so it is quite safe to reset the clock immediately after the launch instruction is issued. Where the clock will be checked, however, as in the case of my Beta, it becomes necessary to introduce a delay before the clock is reset, to ensure the check is completed before the reset occurs. The following is all that is necessary to implement an arbitrary delay of 5 seconds:

C#
System.Threading.Thread.Sleep(5000);

Now, secondly, how do we get rid of the intrusive DOS screen? Once you are satisfied your clock manipulation and launch are working correctly, look at the Project | Properties page. Change the Output Type from Console Application to Windows Application, and rebuild. This tip I came across by chance on one of the forums but I didn't note the author's name.

There being no Form, the application will run as a Form-less Windows application. Copy the shortcut to the Taskbar, or put a dummy item on the Taskbar and rename its target to, in this example, "C:\SOL.EXE", and Solitaire (or anything else you have nominated) will launch normally.

It is instructive to look at the system clock while the launch is under way. Get the clock up on the screen and run the application. You will see the year immediately change to 2005 as Solitaire launches, and then, 5 seconds later, the year changes back to the current year.

If you are unhappy about the clock manipulation introducing a small error between the change and reset, then consider using an NTP server to keep your clock up to date.

Most of the work done for this project was done by others. The only credit I am entitled to claim is the bringing together of the several elements in to a very simple and versatile utility.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Australia Australia
An old assembly language programmer (8051 microcontroller) and a recent convert from Delphi. Retired ten years ago and rather enjoy writing C# code.

Comments and Discussions

 
GeneralApart from the technical view... Pin
mav.northwind5-Jul-06 20:33
mav.northwind5-Jul-06 20:33 
GeneralRe: Apart from the technical view... Pin
Maurice Tarrant5-Jul-06 23:55
Maurice Tarrant5-Jul-06 23:55 
GeneralRe: Apart from the technical view... Pin
Maurice Tarrant5-Jul-06 23:59
Maurice Tarrant5-Jul-06 23:59 
QuestionThis suffers from timing issues? Pin
Ennis Ray Lynch, Jr.5-Jul-06 11:48
Ennis Ray Lynch, Jr.5-Jul-06 11:48 
AnswerRe: This suffers from timing issues? [modified] Pin
Maurice Tarrant5-Jul-06 23:37
Maurice Tarrant5-Jul-06 23:37 
Thank you for the comment. I suppose I was focussed on the utility as a console application, where WaitForInputIdle, I think, is not appropriate. It was only when the DOS screen started to get to me that I investigated the Form-less Windows application as an alternative. Although there is no interface for a user to interact with, it might still be possible to utilise WaitForInputIdle. There is an excellent article dealing with this matter, with good example code, at http://www.akadia.com/services/dotnet_process_handling.html


-- modified at 6:01 Thursday 6th July, 2006

Maurice Tarrant

GeneralRe: This suffers from timing issues? [modified] Pin
85520-Aug-18 2:20
85520-Aug-18 2:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.