Thursday 20 October 2011

Retrieving the Operating System Idle Time, Uptime and Last Input Time

Download this project (Visual Studio 2005)


In this C# programming tutorial here at Geekpedia, we're venturing into unmanaged code again. It's the popular user32.dll that has the GetLastInputInfo() function which interests us in this tutorial. The application will work with Windows 2000, XP, Server 2003, Server 2008 and Vista.

Start by creating a form with 3 Labels: lblIdleTime, lblSystemUptime and lblLastInput. Also add a Timer tmrIdle. Set the Interval property to 1000 (1 second) and the Enabled property to True. Every time this timer ticks, we'll check the last input time and the system uptime. Thus setting the timer to tick every 1 second is a pretty good interval for checking this, accurate but not an overkill.


Now let's write some code. Since we're using an unmanaged library, first comes the additional using statement:



using System.Runtime.InteropServices;

Next comes the signature function and the definition of the struct that is passed to it:


// Unmanaged function from user32.dll
[DllImport("user32.dll")]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

// Struct we'll need to pass to the function
internal struct LASTINPUTINFO
{
    public uint cbSize;
    public uint dwTime;
}

Now it's time to double-click the tmrIdle Timer object so that we get to its Tick event. Here comes the main code, which is self-explanatory thanks to the comments:


private void tmrIdle_Tick(object sender, EventArgs e)
{
    // Get the system uptime
    int systemUptime = Environment.TickCount;
    // The tick at which the last input was recorded
    int LastInputTicks = 0;
    // The number of ticks that passed since last input
    int IdleTicks = 0;

    // Set the struct
    LASTINPUTINFO LastInputInfo = new LASTINPUTINFO();
    LastInputInfo.cbSize = (uint)Marshal.SizeOf(LastInputInfo);
    LastInputInfo.dwTime = 0;

    // If we have a value from the function
    if (GetLastInputInfo(ref LastInputInfo))
    {
        // Get the number of ticks at the point when the last activity was seen
        LastInputTicks = (int)LastInputInfo.dwTime;
        // Number of idle ticks = system uptime ticks - number of ticks at last input
        IdleTicks = systemUptime - LastInputTicks;
    }

    // Set the labels; divide by 1000 to transform the milliseconds to seconds
    lblSystemUptime.Text = Convert.ToString(systemUptime / 1000) + " seconds";
    lblIdleTime.Text = Convert.ToString(IdleTicks / 1000) + " seconds";
    lblLastInput.Text = "At second " + Convert.ToString(LastInputTicks / 1000);
}

Retrieving the operating system uptime is done through managed code (Environment.TickCount), however the last activity time is retrieved through the unmanaged GetLastInputInfo() function that we prepared earlier. From then on, calculating the last input ticks is simple math: subtract the last activity milliseconds from the system uptime and there you have it.

Speech Recognition in .Net using C#

Speech recognition is a much more difficult task than simply making the computer speak. So you would think that it would mean that there would be a good 100 to 200 lines of code required to get the task done. But with .Net it's more like 8.

   1: SpeechRecognitionEngine RecognitionEngine = new SpeechRecognitionEngine();
   2: RecognitionEngine.LoadGrammar(new DictationGrammar());
   3: RecognitionResult Result = RecognitionEngine.Recognize();
   4: StringBuilder Output = new StringBuilder();
   5: foreach (RecognizedWordUnit Word in Result.Words)
   6: {
   7:     Output.Append(Word.Text);
   8: }

The code above should be pretty obvious as to what is going on, with one exception. The LoadGrammar line might give you some pause. The system basically needs to know what to be looking for and has two modes. The first mode is dictation. This is what you would use for something like Word (and is what I show above). The second mode is command mode. In that case you have to build your own grammar (passing in text words, etc. for it to look for). The main reason to use this if you wanted to control an application with specific phrases. Other things to note is that the code above is synchronous. If you wanted to, you can do this async and have it notify you when it's done. We have other options as well, such as the ability to tie it to a wave file, etc. just like the text to speech bit of code.

Anyway, the SpeechRecognitionEngine is apart of the System.Speech.Recognition namespace. It's basically our gateway to the built in speech recognition software that Microsoft uses. Well, sort of anyway... Normally when Microsoft puts something in .Net, it means that it will work.

Speech recognition doesn't seem to want to on Windows Server 2008... I spent the better part of a day trying to get it to work with nothing to show for it. Anyway, on Vista and Windows 7, this code will give you speech recognition. With XP, you have to download and install the Speech SDK from Microsoft. Windows Server 2003 seems to also work with that download, but Windows Server 2008 seems busted at this point (and I'm guessing there is no rush to fix that).

There are claims out there that you can get it to work but none of them have worked for me thus far. Anyway, I hope this helps someone. Give it a try, leave feedback, and happy coding.