Archives

Archives / 2011
  • Command Handling the Nancy Way

    minibuss_small_thumb1_thumb_thumb MiniBuss is a micro service bus framework over msmq which consists of less than 400 lines of code, sitting inside one single source file. The project is hosted over at http://minibuss.codeplex.com and the source code is maintained at https://github.com/johandanforth/MiniBuss

    I’ve been a fan of the Sinatra inspired web framework called Nancy, especially the neat way of setting up handlers for routes. The simplest sample on their site is this:

    public class Module : NancyModule
    {
        public Module()
        {
            Get["/greet/{name}"] = x => {
                return string.Concat("Hello ", x.name);
            };
        }
    }

    So, I shamelessly dug into the Nancy code and borrowed some 20-30 lines of code and came up with something like this for registering handlers for certain incoming commands on the minibus, what do you think?

    public class CommandHandler : MessageHandler
    {
        public CommandHandler()
        {
            WhenReceiving[typeof(SampleMessage1)] = x =>
            {
                Console.WriteLine("sample 1 message: " + x.Text);
            };
    
            WhenReceiving[typeof(SampleMessage2)] = x =>
            {
                Console.WriteLine("sample 2 message: " + x.Text);
            };
        }
    }

    It’s a bit more code but it helps/enforces you to move the handlers off to a certain module. Thoughts?

  • More MiniBuss Updates

    minibuss_small_thumb1_thumb MiniBuss is a micro service bus framework over msmq which consists of less than 400 lines of code, sitting inside one single source file. The project is hosted over at http://minibuss.codeplex.com

    Thanks to @CodingInsomnia for testing out the MiniBuss stuff a bit more than I did Winking smile For the samples, and for my initial testing code, I used a shared assembly with messages (events and commands), which shouldn’t be necessary. So I made a few simple changes and now you can choose to either share messages in an assembly between your sender/receiver and publisher/subscribers OR you can declare local message classes as long as those classes use the same class name and properties it should work.

    The NuGet package has been updated, and the new code is in package version 1.0.2.0.

  • MiniBuss Updates

    minibuss_small_thumb1 I made a small update to MiniBuss, the micro service bus framework. The messages you send, Commands and Events, are no longer dependent on IMessage. The messages sent on the bus can now be any .NET class which can be safely serialized.

    The MiniBuss package on NuGet has been updated (version 1.1.0.1).

    I’m looking for testers, reviewers and co-authors. Areas I want to look more at are multithreading/concurrency and the reply-feature (especially being able to reply to current message in multithreaded scenarios.

  • MiniBuss on Codeplex

    minibuss_small The micro service bus framework for msmq called MiniBuss is now open source on Codeplex at http://minibuss.codeplex.com

    There is also now a NuGet package available for easy install into projects:

    image

    If you’re interested in co-op on this project, please contact me via Codeplex! I’m looking for devs and tester who knows their c#, msmq and concurrency.

  • A One File .NET Micro Service Bus for MSMQ?

    This last year our company has invested quite some time in looking at CQRS, which led to looking at great looking service-buses like nServiceBus, Rhino Service Bus and Mass Transit, which led me to do some bus-coding on my own, mostly for fun and for learning MSMQ.

    Inspired by the service buses mentioned above, the result became a bare-bones-one-file “micro service bus” that I call MiniBuss which sits on top of MSMQ. The file itself is only some 400 lines of code and supports send, receive, reply, publish and subscribe/unsubscribe.

    Setting up a sender may look something like this:

    var bus = new MiniBuss.ServiceBus();

    bus.RegisterMessageEndpoint<HelloCommand>("minibuss_receiver1@johan-dell-ssd");

    bus.Start();

    bus.Send(new HelloCommand { Guid = Guid.NewGuid(), Message = "Hello" });

    Create the bus, register a message and tell it where messages of this type should go, start the bus and send the message.

    Setting up a receiver may look something like this:

    var bus = new ServiceBus { LocalEndpoint = "minibuss_receiver1" };

    bus.RegisterMessageHandler<HelloCommand>(command => Console.WriteLine(command.Message + " Guid: " + command.Guid));

    bus.Start();

    Create the bus and tell it which endpoint to listen to (which creates a local MSMQ queue if necessary) and tell it which message type to listen for and which delegate to kick off when such a message is received.

    Similarly, when doing a receive/reply, you would have to create the bus on the sender side with a local endpoint and register a message-handler for replies, like this:

    var bus = new MiniBuss.ServiceBus { LocalEndpoint = "minibuss_sender1" };

    bus.RegisterMessageEndpoint<HelloCommand>("minibuss_receiver1@johan-dell-ssd");

    bus.RegisterMessageHandler<HelloResponse>(reply => Console.WriteLine("Reply from receiver: " + reply.Message));

    bus.Start();

    Console.WriteLine("Sending command...");
    bus.Send(new HelloCommand { Guid = Guid.NewGuid(), Message = "Hello" });

    The receiver would do a bus.reply() like this:

    var bus = new ServiceBus { LocalEndpoint = "minibuss_receiver1" };

    bus.RegisterMessageHandler<HelloCommand>(command =>
    {
        Console.WriteLine(command.Message + " Guid: " + command.Guid);

        bus.Reply(new HelloResponse { Guid = Guid.NewGuid(), Message = "Hello back!" });
    });

    bus.Start();

    The MiniBus also supports publish to multiple subscribers. A simple publisher would create a bus with a local endpoint (to receive subscribe/unsubscribe commands), tell it to handle subscriptions for a certain event, then start publishing something every 5 seconds (as an example):

    var bus = new MiniBuss.ServiceBus { LocalEndpoint = "minibuss_publisher1" };

    bus.HandleSubscriptionsFor<SomethingHappenedEvent>();

    bus.Start();    

    Task.Factory.StartNew(() => PublishingThread(bus), TaskCreationOptions.LongRunning);

    Console.WriteLine("Done, press ENTER to exit");
    Console.ReadLine();
    private static void PublishingThread(MiniBuss.ServiceBus bus)
    {
        while (true)
        {
            Thread.Sleep(5000);
            var guid = Guid.NewGuid();
            Console.WriteLine("Publishing event with guid " + guid);
            bus.Publish(new SomethingHappenedEvent() { Guid = guid, Sent = DateTime.Now });
        }
    }

    Any clients interesting in subscribing to events from the publisher would create a bus with a local endpoint, start the bus and then send a subscribe command to the publisher, telling it you’re interested in subscribing to a certain type of event and which delegate to handle it:

    var bus = new MiniBuss.ServiceBus {LocalEndpoint = "minibuss_subscriber1"};

    bus.Start();

    bus.Subscribe<SomethingHappenedEvent>("minibuss_publisher1@localhost",
        @event => Console.WriteLine("something happened at {0}, event id {1}",
            @event.Sent, @event.Guid));

    Console.WriteLine("Waiting for events, press ENTER to exit");
    Console.ReadLine();

    bus.UnSubscribe<SomethingHappenedEvent>("minibuss_publisher1");

    Now, the question is, what do you think? I know there are issues with the code, like how to make message-handlers multi-threaded/concurrent without messing things up (it’s single threaded right now), and how to best handle exceptions, rollbacks and re-tries . Right now handling exceptions in send and receive works pretty well within a TransactionScope() together with ADO.NET, and if there’s an exception, the message is moved the an error-queue. No re-try or anything, only rollback and move to xxx_error. Also, the publisher doesn’t persist subscriptions, so if it is restarted subscribers wouldn’t know. You know, things like that.

    I’m a user of the micro-orm called Dapper and like it a lot, so I’m thinking that maybe I should release this micro-bus as open source and see where people may take it, if anywhere? Maybe just down the drain because they figure out this service bus is dangerous to use and risk loosing messages or something (which would be extremely good to know :)

    Or maybe this code is useless because you already got nServiceBus and Rhino out there and coders don’t need another service bus?

    What do you say?

  • Pomodoro Timer for the Windows 7 TaskBar

    EDIT:  The code is now open source on codeplex, on http://pomodorotaskbar.codeplex.com There's a new version available for download there too.

    If you’re into the Pomodoro technique and looking for a pretty simple out-of-the-way timer which sits in the Windows 7 taskbar and is controlled from the Win7 JumpList, this one might be worth trying out.

    NOTE: Icon overlays will NOT work if you're using small TaskBar icons!

    image

    That’s the timer looking like a tomato, with the remaining session minutes written out dynamically as icon overlay.

    image

    The timer has a couple of JumpList Tasks which you can use to control it. The program works well when “pinned” to the taskbar if you prefer it.

    image

    You can also control the timer from the main window with one large action-button (stop, start, stop ringing and restart session).

    image

    When the timer is stopped, you can just click on the remaining minutes-textbox and change the default session length to whatever you like. The value is stored.

    image

    When the session is ended, the window flashes, the tomato shakes and a ringing sound is played a few times to get your attention.

    Note, this is a very simple program which I’m planning to release as open source when I’ve received some feedback. I prefer to keep it simple, but may add session logging. The name as well as the looks may change. .NET 4.0 is required.

  • Create Tag-Cloud from RSS Feed in ASP.NET MVC

    Say you want to generate your own tag-cloud from a list of categories or tags you pull from an RSS-feed or similar. This is one way to do it. I’m using ASP.NET MVC for this sample which creates a simple tag-cloud in a Razor-view with HTML looking something like this:

    image

    The controller-code to start out with looks like this, where you read in the RSS-feed into a SyndicationFeed class, then pull out and flatten all the categories you have in that feed. Then group all those categories and count them to build up this simple view-model which is a Dictionary of category and percentage:

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            //get feed
            var feed = SyndicationFeed.Load(XmlReader.Create("http://blog.irm.se/blogs/MainFeed.aspx"));

            //get flat list of all categories/tags in the feed
            var categoriesList = feed.Items.SelectMany(item => item.Categories).Select(category => category.Name);

            var categoryGroups = categoriesList.GroupBy(category => category);

            decimal maxNrOfACategory = categoryGroups.Max(w => w.Count());

            //build a dictionary with category/percentage of all categories
            var tagCloudDictionary = new Dictionary<string, int>();
            foreach (var tag in categoryGroups)
            {
                var percent = (tag.Count() / maxNrOfACategory) * 100;
                tagCloudDictionary.Add(tag.Key, (int)percent);
            }

            return View(tagCloudDictionary);
        }
    }

     

    So now we got this view-model which is a Dictionary<string,int> and contains category/percentage data like this:

    image

    So all we need to do is create some kind of cloud in HTML or similar in the view. One way of doing it is this, which creates the output shown at the top:

    @model Dictionary<string, int>

    @{
        ViewBag.Title = "Index";
    }

    <h2>Tag cloud</h2>
    <div style="width: 400px; font-size: 25px;">
        @foreach (var tag in Model)
        {
            <span style="font-size: @(tag.Value / 2 + 50)%; ">
            @if (tag.Value > 10)
            {
                <span style=" font-weight: bold;">@tag.Key </span>
            }
            else
            {
                <span>@tag.Key </span>
            }
            </span>
        }
    </div>

     

    Obviously, to be able to click on a tag and so on you need to create a richer view-model, I just wanted to show how I grab and count the tags from the feed Smile

  • Never, never, never do Office interop on the server

    I’ve been telling people this for years and years, and still I stepped right into the mudhole a month ago. I blame stress, but still I shouldn’t have. It’s so easy to just add the interop assemblies and off you go… until you try running your stuff on the 2008 r2 server, hosted somewhere else, with just enough user rights. And even though I managed to get the !”#!¤¤”% working after a while, I got mem-leaks and follow-up probs due to the workarounds I had to do to get the interop working in the first place.

    Then I sat down and relaxed for a minute and realized I need to do this the right way, which is the OpenXML way.

    The thing is, OpenXML is – compared to Office-interop - not easy, and the Microsoft OpenXML SDK 2.0 is just lipstick on top of the XML and some things which were so easy to do with the interop assemblies gives you nightmares to do with OpenXML. Try fill in formsfields in a protected word document for example. I ditched the SDK and ended up doing it directly against the XML directly instead.

    I also had to fill out a few Excel spreadsheets with data, which was somewhat easier to handle than the Word-story above. But I ran into problems here too, because I wanted to do such a simple thing as setting text wrap on a few cells! I don’t know, but I’m sure Microsoft could have done something better for us poor developers that need to create docs on the server! Are we supposed to spend 40% of the coding time to just create a few simple docs, just because we go the OpenXML way? There are a quite a few pages on MSDN with samples, as well as code snippets to download, but as soon as you need to do something outside the “demo-path” you’re banging your head. Maybe I’m just stupid and doesn’t get it, or maybe I’m getting grumpy, because OpenXML is not a developer-friendly framework! There, feels much better now…

    Now, for Excel spreadsheets there’s good hope because you got more than a few decent packages out there to help you out, and the best one I’ve found so far is called ClosedXML on Codeplex. It’s free and it did everything I needed to do right out of the box! It took me 5 minutes to create the 2 different spreadsheets I needed for my project, including cell formatting, text wrapping and so on. Cheers to MDeLeon for doing this!

  • Refactored Dapper Extensions

    Making extensions for Dapper-dot-net was so fun and I needed a few more simple ones so I refactored a bit and made a few Update() and Delete() extensions as well. I’m also looking for Id-properties with the [Key] attribute on them. The class grew a bit, but it now supports the functions below. Note that this will only work for very simple objects and tables, but it might be helpful for some of you Smile

    I’m trying to follow the overall Dapper syntax as much as I can. If you done specify the table name with the input parameter, I’m using the name of the class/entity as table name, except where anonymous types are used.

    The object I’m using for testing

        public class Test
        {
            [Key]
            public int Id { get; set; }
            public string Name { get; set; }
            public int Age { get; set; }
        }
    

    Insert typed object

                    var entity = new Test() { Name = "Johan", Age = 44 };
                    connection.Insert(entity);
    

    Insert anonymous object

                    connection.Insert("insert into test", new { Name = "Johan", Age = 20 });
    

    Update typed object (where-clause built up from Id-properties)

                    var entity = new Test() { Id = 16, Name = "Johan", Age = 50 };
                    connection.Update(entity);
    

    Delete typed object (where-clause built up from Id-properties)

                    var entity = new Test() { Id = 4, Name = "Johan", Age = 44 };
                    var deletedCount = connection.Delete(entity);
    

    Delete anonymous object (where-clause built up from anonymous object)

                    var deletedCount = connection.Delete("delete from test", new { Name = "Johan" });
    

    The Code:

    public static class DapperExtensions
    {
        public static void Insert(this IDbConnection connection, object entityToInsert)
        {
            Insert(connection, null, entityToInsert);
        }
    
        public static void Insert(this IDbConnection connection, string sql, object entityToInsert)
        {
            var name = entityToInsert.GetType().Name;
            var sb = new StringBuilder(sql);
            if (sql == null)
                sb.AppendFormat("insert into {0}", name);
            sb.Append(" (");
            BuildInsertParameters(entityToInsert, sb);
            sb.Append(") values (");
            BuildInsertValues(entityToInsert, sb);
            sb.Append(")");
            connection.Execute(sb.ToString(), entityToInsert);
        }
    
        public static int Update(this IDbConnection connection, object entityToUpdate)
        {
            return Update(connection, null, entityToUpdate);
        }
    
        public static int Update(this IDbConnection connection, string sql, object entityToUpdate)
        {
            var idProps = GetIdProperties(entityToUpdate);
            if (idProps.Count() == 0)
                throw new ArgumentException("Entity must have at least one [Key] property");
    
            var name = entityToUpdate.GetType().Name;
    
            var sb = new StringBuilder(sql);
            if (sql == null)
                sb.AppendFormat("update {0}", name);
    
            sb.AppendFormat(" set ");
            BuildUpdateSet(entityToUpdate, sb);
            sb.Append(" where ");
            BuildWhere(sb, idProps.ToArray());
    
            return connection.Execute(sb.ToString(), entityToUpdate);
        }
    
        public static int Delete<T>(this IDbConnection connection, T entityToDelete)
        {
            return Delete(connection, null, entityToDelete);
        }
    
        public static int Delete<T>(this IDbConnection connection, string sql, T entityToDelete)
        {
            var idProps = typeof (T).IsAnonymousType() ? 
                GetAllProperties(entityToDelete) : 
                GetIdProperties(entityToDelete);
    
            if (idProps.Count() == 0)
                throw new ArgumentException("Entity must have at least one [Key] property");
    
            var name = entityToDelete.GetType().Name;
    
            var sb = new StringBuilder(sql);
            if (sql == null)
                sb.AppendFormat("delete from {0}", name);
    
            sb.Append(" where ");
            BuildWhere(sb, idProps);
    
            return connection.Execute(sb.ToString(), entityToDelete);
        }
    
        private static void BuildUpdateSet(object entityToUpdate, StringBuilder sb)
        {
            var nonIdProps = GetNonIdProperties(entityToUpdate).ToArray();
    
            for (var i = 0; i < nonIdProps.Length; i++)
            {
                var property = nonIdProps[i];
    
                sb.AppendFormat("{0} = @{1}", property.Name, property.Name);
                if (i < nonIdProps.Length - 1)
                    sb.AppendFormat(", ");
            }
        }
    
        private static void BuildWhere(StringBuilder sb, IEnumerable<PropertyInfo> idProps)
        {
            for (var i = 0; i < idProps.Count(); i++)
            {
                sb.AppendFormat("{0} = @{1}", idProps.ElementAt(i).Name, idProps.ElementAt(i).Name);
                if (i < idProps.Count() - 1)
                    sb.AppendFormat(" and ");
            }
        }
    
        private static void BuildInsertValues(object entityToInsert, StringBuilder sb)
        {
            var props = GetAllProperties(entityToInsert);
    
            for (var i = 0; i < props.Count(); i++)
            {
                var property = props.ElementAt(i);
                if (property.GetCustomAttributes(true).Where(a => a is KeyAttribute).Any()) continue;
                sb.AppendFormat("@{0}", property.Name);
                if (i < props.Count() - 1)
                    sb.Append(", ");
            }
        }
    
        private static void BuildInsertParameters(object entityToInsert, StringBuilder sb)
        {
            var props = GetAllProperties(entityToInsert);
    
            for (var i = 0; i < props.Count(); i++)
            {
                var property = props.ElementAt(i);
                if (property.GetCustomAttributes(true).Where(a => a is KeyAttribute).Any()) continue;
                sb.Append(property.Name);
                if (i < props.Count() - 1)
                    sb.Append(", ");
            }
        }
    
        private static IEnumerable<PropertyInfo> GetAllProperties(object entity)
        {
            return entity.GetType().GetProperties();
        }
    
        private static IEnumerable<PropertyInfo> GetNonIdProperties(object entity)
        {
            return GetAllProperties(entity).Where(p => p.GetCustomAttributes(true).Any(a => a is KeyAttribute) == false);
        }
    
        private static IEnumerable<PropertyInfo> GetIdProperties(object entity)
        {
            return GetAllProperties(entity).Where( p => p.GetCustomAttributes(true).Any(a => a is KeyAttribute));
        }
    }
    
    public static class TypeExtension
    {
        public static Boolean IsAnonymousType(this Type type)
        {
            if (type == null) return false;
    
            var hasCompilerGeneratedAttribute = type.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Count() > 0;
            var nameContainsAnonymousType = type.FullName.Contains("AnonymousType");
            var isAnonymousType = hasCompilerGeneratedAttribute && nameContainsAnonymousType;
    
            return isAnonymousType;
        }
    }
    
    Feel free to fork the code as much as you can, I’m too tired to stay up longer. Dapper is getting really useful Smile
     
  • Simple Insert Extension for Dapper

    Last week I started using Dapper (dapper-dot-net on Google Code) for a project I’m working on. Dapper is a micro ORM, which extends IDbConnection. It’s very fast and works very well for queries where you want to return both typed and dynamic lists of objects. Have a quick look at the webpage and you’ll see what I mean.

    Today I needed to do some inserting, which you can do with the Execute() extension, but you’d have to type out all the “insert into xxx (col1,col2) values (@val1, @val2)” stuff. Some guys suggested to create a dapper.contrib and adding extensions of insert, update, delete and so on but it’s not there yet (at time of writing).

    Anyway, the extensions in dapper are already so well written I thought it should be quite easy to just add a dead simple (or stupid if you prefer) Insert() extensions on top of the existing Execute(), and I ended up with this raw unrefactored code. All it does really is building up the SQL for the insert using some property reflection, dapper itself does the heavy lifting:

    public static class DapperExtensions
    {
        public static void Insert(this IDbConnection connection, 
    object entityToInsert, string sql = "insert into " ) { var name = entityToInsert.GetType().Name; if (sql == "insert into ") { sql = "insert into " + name + " "; } sql += " ("; for (var i = 0; i < entityToInsert.GetType().GetProperties().Length; i++) { var propertyInfo = entityToInsert.GetType().GetProperties()[i]; sql += propertyInfo.Name; if (i < entityToInsert.GetType().GetProperties().Length - 1) sql += ","; } sql += ") values ("; for (var i = 0; i < entityToInsert.GetType().GetProperties().Length; i++) { var propertyInfo = entityToInsert.GetType().GetProperties()[i]; sql += "@" + propertyInfo.Name; if (i < entityToInsert.GetType().GetProperties().Length - 1) sql += ","; } sql += ")"; connection.Execute(sql, entityToInsert); } }
    I’m using it like this with a type:
    using (var connection = new SqlConnection(connectionString))
    {
        connection.Open();
        var entity = new Test() { Name = "Johan", Age = 43 };
        connection.Insert(entity);
    }
    public class Test
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

    …or like this with an anonymous type:

    using (var connection = new SqlConnection(connectionString))
    {
        connection.Open();
        connection.Insert(new { Name = "Johan", Age = 43 }, "insert into test");
    }

    Works for me ™ Winking smile

  • Detecting Idle Time with Global Mouse and Keyboard Hooks in WPF

    Years and years ago I wrote this blog post about detecting if the user was idle or active at the keyboard (and mouse) using a global hook. Well that code was for .NET 2.0 and Windows Forms and for some reason I wanted to try the same in WPF and noticed that a few things around the keyboard and mouse hooks didn’t work as expected in the WPF environment. So I had to change a few things and here’s the code for it, working in .NET 4.

    I took the liberty and refactored a few things while at it and here’s the code now. I’m sure I will need it in the far future as well.

    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    
    namespace Irm.Tim.Snapper.Util
    {
        public class ClientIdleHandler : IDisposable
        {
            public bool IsActive { get; set; }
    
            int _hHookKbd;
            int _hHookMouse;
    
            public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
            public event HookProc MouseHookProcedure;
            public event HookProc KbdHookProcedure;
    
            //Use this function to install thread-specific hook.
            [DllImport("user32.dll", CharSet = CharSet.Auto,
                 CallingConvention = CallingConvention.StdCall)]
            public static extern int SetWindowsHookEx(int idHook, HookProc lpfn,
                IntPtr hInstance, int threadId);
    
            //Call this function to uninstall the hook.
            [DllImport("user32.dll", CharSet = CharSet.Auto,
                 CallingConvention = CallingConvention.StdCall)]
            public static extern bool UnhookWindowsHookEx(int idHook);
    
            //Use this function to pass the hook information to next hook procedure in chain.
            [DllImport("user32.dll", CharSet = CharSet.Auto,
                 CallingConvention = CallingConvention.StdCall)]
            public static extern int CallNextHookEx(int idHook, int nCode,
                IntPtr wParam, IntPtr lParam);
    
            //Use this hook to get the module handle, needed for WPF environment
            [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr GetModuleHandle(string lpModuleName);
    
            public enum HookType : int
            {
                GlobalKeyboard = 13,
                GlobalMouse = 14
            }
    
            public int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
            {
                //user is active, at least with the mouse
                IsActive = true;
                Debug.Print("Mouse active");
    
                //just return the next hook
                return CallNextHookEx(_hHookMouse, nCode, wParam, lParam);
            }
    
            public int KbdHookProc(int nCode, IntPtr wParam, IntPtr lParam)
            {
                //user is active, at least with the keyboard
                IsActive = true;
                Debug.Print("Keyboard active");
    
                //just return the next hook
                return CallNextHookEx(_hHookKbd, nCode, wParam, lParam);
            }
    
            public void Start()
            {
                using (var currentProcess = Process.GetCurrentProcess())
                using (var mainModule = currentProcess.MainModule)
                {
    
                    if (_hHookMouse == 0)
                    {
                        // Create an instance of HookProc.
                        MouseHookProcedure = new HookProc(MouseHookProc);
                        // Create an instance of HookProc.
                        KbdHookProcedure = new HookProc(KbdHookProc);
    
                        //register a global hook
                        _hHookMouse = SetWindowsHookEx((int)HookType.GlobalMouse,
                                                      MouseHookProcedure,
                                                      GetModuleHandle(mainModule.ModuleName),
                                                      0);
                        if (_hHookMouse == 0)
                        {
                            Close();
                            throw new ApplicationException("SetWindowsHookEx() failed for the mouse");
                        }
                    }
    
                    if (_hHookKbd == 0)
                    {
                        //register a global hook
                        _hHookKbd = SetWindowsHookEx((int)HookType.GlobalKeyboard,
                                                    KbdHookProcedure,
                                                    GetModuleHandle(mainModule.ModuleName),
                                                    0);
                        if (_hHookKbd == 0)
                        {
                            Close();
                            throw new ApplicationException("SetWindowsHookEx() failed for the keyboard");
                        }
                    }
                }
            }
    
            public void Close()
            {
                if (_hHookMouse != 0)
                {
                    bool ret = UnhookWindowsHookEx(_hHookMouse);
                    if (ret == false)
                    {
                        throw new ApplicationException("UnhookWindowsHookEx() failed for the mouse");
                    }
                    _hHookMouse = 0;
                }
    
                if (_hHookKbd != 0)
                {
                    bool ret = UnhookWindowsHookEx(_hHookKbd);
                    if (ret == false)
                    {
                        throw new ApplicationException("UnhookWindowsHookEx() failed for the keyboard");
                    }
                    _hHookKbd = 0;
                }
            }
    
            #region IDisposable Members
    
            public void Dispose()
            {
                if (_hHookMouse != 0 || _hHookKbd != 0)
                    Close();
            }
    
            #endregion
        }
    }

    The way you use it is quite simple, for example in a WPF application with a simple Window and a TextBlock:

    <Window x:Class="WpfApplication2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <TextBlock Name="IdleTextBox"/>
        </Grid>
    </Window>
    
    

    And in the code behind we wire up the ClientIdleHandler and a DispatcherTimer that ticks every second:

    public partial class MainWindow : Window
    {
        private DispatcherTimer _dispatcherTimer;
        private ClientIdleHandler _clientIdleHandler;
    
        public MainWindow()
        {
            InitializeComponent();
        }
    
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //start client idle hook
            _clientIdleHandler = new ClientIdleHandler();
            _clientIdleHandler.Start();
            
            //start timer
            _dispatcherTimer = new DispatcherTimer();
            _dispatcherTimer.Tick += TimerTick;
            _dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1);
            _dispatcherTimer.Start();
        }
    
        private void TimerTick(object sender, EventArgs e)
        {
            if (_clientIdleHandler.IsActive)
            {
                IdleTextBox.Text = "Active";
                //reset IsActive flag
                _clientIdleHandler.IsActive = false;    
            }
            else IdleTextBox.Text = "Idle";
        }
    }

    Remember to reset the ClientIdleHandle IsActive flag after a check.