Monday, July 5, 2010

Keyboard and Mouse OS Level Hooks

Intercepting mouse and keyboard events anywhere in the operating system was easier than I thought. It can all be done in C# while using the User32 SetWindowsHookEx method.

Links to more information:
I have a half finished proof of concept of a keyboard and mouse hook for user presence detection as well as global hotkeys.  I'll post it when I get time.

See this December post for more on this topic.

Tuesday, June 29, 2010

Windows 7 Easter Egg

There is a GOD MODE easter egg in Windows 7.  Not quite as cool as it sounds but still very useful.


Create a folder on your desktop and rename it to: GodMode.{ED7BA470-8E54-465E-825C-99712043E01C}

This creates a folder that looks like this:


Opening this you get:

This gives you a window full of shortcuts to all the configuration features in Windows 7.  You can use the search box at the top of the window to quickly find the configuration icon you want! 

Cheers

Monday, June 28, 2010

Xaml Serialization and Blend Sample Data

Background
For a project I am currently working on, we are using specialised UI Designers and they are using Blend to import, draw and arrange the graphic assets.  One of the coolest features in Blend 4 is the very nice Sample Data features.  Our process involves delivering partially constructed MVVM controllers so the Designers can use Blend to generate random sample data.  This is all well and good, but it still means the application is totally blank when it runs, hence the generated sample data is called "Design-time Sample Data".  However, the sample data is actually a serialised format of instances of objects:

Blend's Design-time Sample Data
Blend offers 3 ways of creating sample data:
  1. From an XML file you have handcrafted yourself. 
  2. From a code class.
  3. Or manually creating it using a designer within Blend. (Not terribly useful in my opinion as the developers generally set the underlying class structure and names).
I have been using the code class option.
This generates a sample data item in the Data tab.
From this we can now be more specific on what kind of data each field is.  For example string fields can use the following templates to generate sample data:
Blend has created an xaml file to store in serialised form the object instances it has created.
Having sample data in the application makes the designer's job much easier as the see the data in the fields. It also means its easier to create custom templates for collection based items.

Xaml Serialised Data
The Xaml markup is actually just a form of XML serialisation. Here's an example of the file format generated by Blend:

<WpfApplication:MainWindowController 
    xmlns:WpfApplication="clr-namespace:WpfApplication" 
    State="Active">

    <WpfApplication:MainWindowController.CurrentForm>
        <WpfApplication:FormController State="Active">
            <WpfApplication:FormController.CurrentContact>
                <WpfApplication:Contact 
                    Company="A. Datum Corporation" 
                    Email="someone@example.com" 
                    FirstName="Aaberg, Jesper" 
                    MainLine="(111) 555-0100" 
                    Mobile="(111) 555-0100" 
                    State="Active" 
                    Surname="Aaberg, Jesper" />
            </WpfApplication:FormController.CurrentContact>
        </WpfApplication:FormController>
    </WpfApplication:MainWindowController.CurrentForm>

    <WpfApplication:MainWindowController.Dashboard>
        <WpfApplication:DashboardController 
            Capacity="33" 
            Online="True" 
            State="Invalid" 
            Status="Amet dictumst curae donec eleifend" 
            StatusEnum="Online" />
    </WpfApplication:MainWindowController.Dashboard>

</WpfApplication:MainWindowController>
This syntax is significantly better than standard Xml serialisation because the xml type elements are namespaced back to the assembly they are declared in.  Also it follows the same serialisation process as WCF Service contract serialisation in that it serialises all public properties. Standard Xml serialisation only serialises fields and those must be decorated with Xml Attributes! Way too much hassle.  Xaml serialisation is definitely the way of the future.

The Problem
Having design time data is a very tidy solution as it guarantees the design time data doesn't make it into your compiled executable.  The only drawback is that the designers can't run the application to do final visual testing.  One solution to this problem is to use the Xaml Serialisation classes to deserialise the Xaml back into objects and bind to those at runtime.

I feel like I need to come up with a safer more elegant solution so the design time cannot be accidentally left in the executable code, but for now I use a compilation switch #SAMPLEDATA. But hopefully the likelihood of someone releasing the product with the SAMPLEDATA switch intact is low.

public partial class App
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="App"/> class.
        /// </summary>
        public App()
        {
#if (SAMPLEDATA)
            // Sample data used at runtime.  Sometimes useful for visual testing in addition to design time testing in Blend.
            SampleData.SampleDataRepository.MainWindowController =
                SetUpSampleData<MainWindowController>(@".\..\..\SampleData\MainWindowControllerSampleData.xaml");
#endif
        }

#if (SAMPLEDATA)
        private static T SetUpSampleData<T>(string sampleDataFile) where T : class, new()
        {
            // Using Xaml
            if (File.Exists(sampleDataFile))
            {
                var deserialisedObject = XamlServices.Load(sampleDataFile);
                return deserialisedObject as T;
            }
            
            return null;
        }
#endif
    }

You can see I am using a static class with static properties to store the pre-made sample data controllers ready for use.  The sample controllers replace runtime controllers when the SAMPLEDATA switch is present.  .Net 4 includes a new class designed to simplify Xaml serialisation System.Xaml.XamlServices.

public partial class Sample {
        public Sample() {
            InitializeComponent();

#if (SAMPLEDATA)
            this.DataContext = SampleData.SampleDataRepository.MainWindowController;
#endif
        }
    }
Ordinarily when running in "Production" mode the DataContext is set in Xaml (my personal preference), or if it is set in code behind then it would need to be above the #if.

For more complicated scenarios the controllers might need to be interfaced if the are tightly bound to other data sources. This would allow the sample controllers to bypass any data service calls etc.

Serialisation
It doesn't apply to this scenario but it is equally as easy as deserialisation.

string serialised = XamlServices.Save(myObject);
No need to tell it the type or anything else. There are other overloads that take streams and writers and parameters.

For more information:

Saturday, June 26, 2010

WCF: Address Already In Use Exception

If you get this exception:

AddressAlreadyInUseException: Cannot listen on pipe name 'net.pipe://myservice/' because another pipe endpoint is already listening on that name.

Chances are you have one of the following issues:
  1. You have duplicate endpoints with exactly the same address. Double check your app.config endpoint declarations and/or code endpoint declarations.
  2. Ensure all ServiceContracts attributes have been uniquely namespaced.     [ServiceContract(Namespace = "http://services.rees.biz/myservice1")]
  3. Not sure how relevant this is, but I had an instance when this exception was resolved by changing my net.pipe endpoint url to net.pipe://localhost/servicename.  It was something like net.pipe://myservice/servicename.  Seems like a reasonable best-practice to always use localhost anyhow.
  4. Ensure the system tray Visual Studio WCF Host is not present in the system tray. Sometimes this thing can get confused at not restart correctly.
Yes you can have multiple processes all using net.pipe binding as long as they are using unique endpoint urls and unique service contract namespaces.

Hope that helps someone else.