Friday, July 16, 2010

Sharing binaries between Surface and Windows 7

This post is part of a series about Blake.NUI, my open-source library for multi-touch natural user interface development with WPF 4 and Surface. In this post I discuss how to set up your projects to share 99% of your binaries between Surface and Windows 7. See my Blake.NUI announcement post for an overview of the project as well as a discount code for my book Multitouch on Windows, good until July 23.

In my last post, I showed how to use the SurfaceTouchDevice class to let WPF 4 Touch applications work on Microsoft Surface. In this post, I will discuss how to set up your project to allow you to reuse almost your entire WPF 4 code-base between a Surface SDK application and Win7 Surface Toolkit application. This approach will make your code binary compatible between the two platforms.

Note that as I discuss the technique, I am assuming that you are setting up your projects on a Windows 7 multi-touch machine with Visual Studio 2010 and both Surface SDK SP1 Workstation Edition and Surface Toolkit beta installed. Once the projects are setup, you can compile the solution on a Surface device as long as you create a solution configuration that does not build the projects that reference Surface Toolkit.

1. Project Structure

If you want to target both Win7 and Surface with the same code-base, you'll need to keep the Surface SDK-specific code separate from your reusable code. There are several possible approaches, but here is the one I have been using. Figure 1 shows the architecture of the solution.

Figure 1 Most of the controls and code is located in a common project that is consumed by a Surface project and a Win7 project.


I recommend creating a shell project for Surface and a shell project for Win7. Each of these projects has only a window. In the Surface project, add SurfaceTouchDevice.RegisterEvents(this) to the SurfaceWindow constructor. (I also add MouseTouchDevice.RegisterEvents(this) to both Surface and Win7 projects.) Then in a separate common library I put all of my MVVM code and added the same view user control to the window in each of the shell projects.

Note that the Surface project references the Surface SDK (v1.0) and the Win7 project references Surface Toolkit (v1.5). You will need to check the properties on the assembly references to ensure they are the correct version for each application. The Surface project probably is referencing v1.5 of Microsoft.Surface.Presentation.dll and Microsoft.Surface.Presentation.Generic.dll. Simply remove those reference and in the Add Reference dialog browse and add references to the 1.0 version of the assemblies.

Surface Toolkit contains a subset of controls from the full Surface SDK. This means that you can reference either version 1.0 or 1.5 of Microsoft.Surface.Presentation.dll in your common project and use any of the common controls that exist in both assemblies, such as SurfaceButton and ScatterView. As long as you stick to the subset of common controls, the same binary will work on both Surface and Win7. I would recommend using v1.0 in the common project so you can still compile the project on your Surface device without Surface Toolkit.


2. Loading the correct assemblies

Assuming that you do reference Microsoft.Surface.Presentation.dll v1.0 in the common project and Microsoft.Surface.Presentation.dll v1.5 in the Win7 project, you need to do one more thing to ensure that the application will load correctly. If you do not, then depending upon the order in which components load, you may get a runtime exception like the one shown in figure 2.

Figure 2. If you mix the assembly references, you may get an IOException: Cannot locate resource 'controls/touchvisualizations/touchvisualizationsresources/trailtop.png'. This exception occured on the first touch after the Win7 application loaded.

The solution to this is to add a versioning policy to redirect the v1.0 assembly to v1.5. This blog has a good overview of versioning policies. In the Win7 project, add this to the app.config within the configuration section:

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="Microsoft.Surface.Presentation"  
          publicKeyToken="31BF3856AD364E35" culture="neutral"/>
      <bindingRedirect oldVersion="0.0.0.0-1.5.0.0"  
          newVersion="1.5.0.0"/>
    </dependentAssembly>
  </assemblyBinding>
</runtime>

Just to be safe, you may want to also add the same thing to the Surface project's app.config, except change the newVersion to 1.0.0.0. This ensures that each project will always load the correct version of the assembly, provided it is installed.

I have committed a few updates to the Blake.NUI project, including TestApplication.Common, TestApplication.Surface, and TestApplication.Win7. These three projects illustrate the ideas discussed in this blog. Download the latest code from the Source Code tab on the CodePlex site.

3. Summary

We have learned how to structure a WPF 4 solution to target both Win7 and Surface while reusing almost all of our code in a common library. We also saw how to configure the projects to ensure they load the correct version of the Surface assemblies at runtime.

So far, we know that we can only reference the Surface controls that exist in both Surface SDK and Surface Toolkit. In the next post, I will discuss some techniques that can enable you to use the Surface SDK-specific controls such as TagVisualizer and ElementMenu while maximizing the code reuse.

4 comments:

  1. Finally read this after having the tab open for 3 days. Good stuff.

    ReplyDelete
  2. LOL thanks. I do that sometimes too. Last week I had a tab open for a week waiting for time to ready it.

    ReplyDelete
  3. Any hints on when the next post comes? I'm struggling to set this up since we have a pretty large surface app using many surface specific controls (tag visualizers among others). I'm not 100% clear how to separate the various parts and which machine I can use to build/run and debug which parts.

    By the way, I bought your book yesterday but haven't had time to read it all yet.. :) From the sample I read it looks very promising though!

    ReplyDelete
  4. Hi Isak,

    I have the next post partially written but need to finish it up. I'll see if I can knock that out this weekend. I also try to balance that with writing the book, too. :)

    In general, any of the controls in Surface Toolkit can be used in the common project for both Win7 and Surface. If you do not need to target Win7 then you can just use the Surface SDK and put whatever you need in any project.

    Thanks for buying the book! When you have a chance please fill out the reader survey here:
    http://www.manning-sandbox.com/thread.jspa?forumID=644&threadID=39051

    Thanks,
    Josh

    ReplyDelete