Archive for December, 2007

2008 Summer Road Trip – Book your seat now!

Sunday, December 16th, 2007

summer-road-trip.png2008 heralds the release of the next wave of technology in the main pilliars of the Microsoft development platform i.e., Windows Server 2008, SQL Server 2008 and Visual Studio 2008.

The New Zealand .NET User Group is organising a national road trip to help spread the word and showcase the latest features and advantages of these products.

Chris Auld and Jeremy Boyd (New Zealand’s two Microsoft Regional Directors) will co-present with a local presenter in each region, a presentation that builds a live enterprise level web application utilising Windows Server 2008, ASP.NET, SQL Server 2008, WCF, .NET Framework 3.5 and Live mapping in under 2 hours, right in front of your eyes!

This event is traveling to the following locations:

I’m very excited about this event as I am honoured to be the local presenter for the Christchurch leg of this event. It should be a valuable and exciting experience to present along side Chris and Jeremy (thanks Dan for getting me involved).

Darryl has been able to organise some very cool spot prizes and give-aways for the event. Also by registering and filling out an eval form on the day you can go into the draw to win 1 of 3 Windows Home Servers available nationally. To register for the road trip click the link above for your region to obtain venue and registration details. When you register you will notice that you can also nominate friends to invite along. If you invite a friend and they attend you will get another entry into the draw. This works like a multi level marketing scheme, if your friends then go on to invite further friends, you will also receive additional entries in the competition and so on.

So help spread the word, register and make sure your friends and work colleagues come along!

Sharing Platform Invoke code between the Desktop and Compact Framework

Saturday, December 15th, 2007

Previously we discussed techniques for backwards compatibility when accessing new APIs within native applications. This blog posting discusses how similar techniques can be used by .NET Compact Framework developers utilising Platform Invoke functionality.

.NET Compact Framework developers inherently have a head start, as utilising Platform Invoke functionality means they are always implicitly dynamically linking to native APIs.

Building Assemblies that work on Desktop and PDA
Screenshot of sample .NET Compact Framework application running on a Desktop PC running Microsoft VistaIf you build your application as a Smart Device project you will find that you can get your executable to also run on the full .NET Framework without modification.

The magic that allows this to happen is a new feature Microsoft introduced with .NET Framework v2.0 called retargetable assemblies. An assembly which is marked as retargetable can be substituted with a compatible assembly from a different publisher.

The .NET Compact Framework base class libraries (such as System.Data.dll) are retargetable. This allows the desktop assembly loader (fusion) to substitute them for the desktop versions of these assemblies when the executable is ran on a Desktop PC.

The reverse is not possible. I.e. an assembly built against the desktop assemblies will fail to run when placed on a device running the .NET Compact Framework.

You have to be careful while using this feature. If you manage to use a feature only present in the .NET Compact Framework version of an assembly, a TypeLoadException will occur when your application attempts to run on a desktop PC,.

Dealing with non existant APIs
Sometimes you may need to access an API which is only available on a particular platform or device and it is important to handle the error cases which may occur when the application runs on a platform that does not support the API.

Internally the Platform Invoke functionality calls the LoadLibrary and GetProcAddress system APIs discussed when we talked about native platform compatibility. If either of these APIs return failure codes the .NET Compact Framework Platform Invoke functionality will cause an exception to be thrown. We will again use the SndPlaySync API to demonstrate this.

// Declare the SndPlaySync API as being a native function present
// within the aygshell.dll file
[DllImport("aygshell.dll")]
private static extern int SndPlaySync(string pszSoundFile, UInt32 dwFlags);
 
...
 
try
{
  // Attempt to call the SndPlaySync function
  SndPlaySync(@"\Windows\Alarm2.wav", 0);
}
catch (DllNotFoundException ex)
{
  // deal with the DLL not being present
  // at all
}
catch (MissingMethodException ex)
{
  // deal with the method not being found
  // within the dll
}

If we ran this application on a desktop PC we would expect to receive a DllNotFoundException, this is because the aygshell.dll file does not exist on a desktop PC.

If we ran this application on a PDA running Windows Mobile 5.0 or lower we would expect a MissingMethodException, since these platforms have an aygshell.dll, but it does not provide the SndPlaySync API.

In a real application we may like to handle these exceptions by attempting to use an alternative, or less capable technique to implement the same functionality. For example we may fall back to using an older API with less features, or disable some element of our user interface.

Dealing with APIs that exist in different locations
Windows CE (the operating system Windows Mobile is based upon) aims to have a Win32 API implementation which is fairly compatible with the implementation found in desktop versions of the Microsoft Windows operating system. However for a number of technical and historical reasons the APIs are commonly exposed by different DLLs. This leads to a potential issue since the DLLImport attribute utilised to Platform Invoke a function requires hard coding the DLL’s name into your application as shown below.

// MessageBox is found within coredll.dll
[DllImport("coredll.dll")]
private static extern int MessageBox(IntPtr hWnd, String lpText,
  String lpCaption, uint uType);

We can work around this problem by having more than one Platform Invoke declaration for our desired function. We can have one declaration for each platform we target, with the only difference being the DLL specified. For example:

// MessageBox is found in coredll.dll on Windows Mobile
[DllImport("coredll.dll")]
private static extern int MessageBox(IntPtr hWnd, String lpText,
  String lpCaption, uint uType);
 
// MessageBox is found in user32.dll on Desktop PCs 
[DllImport("user32.dll")]
private static extern int MessageBox(IntPtr hWnd, String lpText,
  String lpCaption, uint uType);

However if we attempt to compile this the compiler would tell us that we have duplicate definitions for the MessageBox function. We can get around this by giving them different names and using the optional EntryPoint field of the DllImport attribute to define the actual name of the function within the DLL.

[DllImport("coredll.dll", EntryPoint="MessageBox")]
private static extern int MessageBox_WCE(IntPtr hWnd, String lpText,
  String lpCaption, uint uType);
 
[DllImport("user32.dll", EntryPoint="MessageBox")]
private static extern int MessageBox_WIN(IntPtr hWnd, String lpText,
  String lpCaption, uint uType);

Having these two definitions gives two uniquely named functions as far as the C# compiler is concerned, but both attempt to access a function called MessageBox in their respective DLLs.

We can then produce a small wrapper function which hides this difference and automatically calls the correct method based upon the current platform the application is running on.

int MessageBox(IntPtr hWnd, String lpText,
  String lpCaption, uint uType)
{
  if (Environment.OSVersion.Platform == PlatformID.WinCE)
    // call the Windows CE version of this function
    MessageBox_WCE(hWnd, lpText, lpCaption, uType);
  else
    // call the desktop version of this function
    MessageBox_WIN(hWnd, lpText, lpCaption, uType);
}

Sample Application

[Download CrossPlatformTest.zip - 9.9KB]

A small sample application is available to demonstrate these two techniques. Once the application is built you should be able to run it on both the Windows Mobile 5.0, and 6 Device Emulators, as well as your Desktop PC (for this navigate to the executable on your hard-drive and double click it).

The first button should display a message box (similar in functionality to the built in System.Windows.Forms.MessageBox class). If you step through the code you should see that different DllImport statements are used to take care of the different DLLs this API lives in on Windows Mobile devices and Desktop PCs.

The second button attempts to play a sound via the SndPlaySync API which is present on Windows Mobile 6 and above. If you run this example on any other platform you should get a message box indicating an error. The message displayed demonstrates the different type of exceptions which may be thrown when the API is not present on a given platform.

Windows Mobile Tip: Creating managed control panel applets

Friday, December 14th, 2007

aaTo create a dialog that appears within the Settings application (accessible via the Windows Start menu) you could utilise the Control Panel Applet API. However this API doesn’t lend itself to writing an applet in C# or VB.NET.

As an alternative you can create a standard .NET Compact Framework Device Application. Once you have deployed your application you can place a shortcut to it within the \Windows\Start Menu\Settings folder. This will cause your application to appear within the System tab of the Settings application (as demonstrated by the “Earth” icon shown in the screenshot).

By configuring the properties of your application’s form you can get your application to appear the same way a standard control panel applet does (i.e. a title row of bold text and a 1 pixel high divider line).

When creating a settings shortcut you may need to soft reset your device to have your new option appear. One disadvantage of using this tip is the fact that you can not control which tab your application will appear on.

There is nothing stopping you from creating a shortcut to a third party application. I like moving shortcuts to system utilities such as registry editors and backup utilities into the Settings application instead of the main Programs list.

World’s Greatest NERD?

Wednesday, December 12th, 2007

Photo of World's Greatest NERD medalI’m defiantly not the world’s greatest nerd, but today I found out that I passed the last paper needed to complete my Computer Science degree. I got an A+ for the Declarative Programming paper I did extramurally via Massey University.

All going according to plan, this should mean I can finally graduate from Canterbury University early next year.

To celebrate completing my degree my partner bestowed the following medal on me. Below the medal is the description:

“World’s Greatest Nerd – How does someone with biceps like knots on cotton, 3 inch thick glasses, 14 pencils in their pocket, and a laugh that could curdle like milk, become so popular? Perhaps it’s because you’re the only one who can fix all our computer problems.”

It’s good to finally have this degree completed. Having stopped a couple of years ago to pursue full time employment I really underestimated how long it would take me before I took the initiative and completed those last couple of points…

Capturing photos without using the CameraCaptureDialog class

Wednesday, December 12th, 2007

A couple of days ago I received an email from Stefan Plattner asking how to integrate photo capture into an application without using the standard camera user interface. Since I’ve heard this question a couple of times I thought I would respond to his email via a blog posting.

His question was:

I read some posts on your excellent weblog (http://www.christec.co.nz/blog/). Maybe you can give me some answers regarding “camera programming” for Windows Mobile.

I’m starting to develop an application for the Compact Framework 2.0 (PocketPC) and wanted to show the real-time camera image in a frame (directly in the application, not through “CameraCaptureDialog()”). In a second step it would be nice to capture the current image on a button click. Do you know if there is some sample code (managed or unmanaged) out there? Do you have any experience with this topic?

I apologize, if I bother you with this email, but I couldn’t find useful information anywhere on the net.

I don’t have a code sample that does exactly what Stefan wants, but can give a couple of pointers to code samples that may be modifiable to suit his needs.

Prior to Windows Mobile 5.0 there was no standardised camera API, meaning it’s difficult to provide an answer for Windows Mobile 2003 or prior. However with Windows Mobile 5.0 and above there are three standardised APIs that can be used to work with the camera at various levels of abstraction.

Unfortunately the two APIs that are easily accessible from managed code both require user input in order to capture an image and don’t allow much flexibility in the user interface presented during image capture. The third API for accessing the camera functionality is called DirectShow. This is a COM based API that is significantly more complex to utilise due to it’s implementation technology and the low level nature of the API.

Some code samples that you may find a useful starting point include:

  • CameraCapture code sample – The Windows Mobile 5.0 / 6 SDKs include a code sample written in native C++ to demonstrate how to setup a DirectShow filter graph in order to capture video or still images at a press of a button.
  • Marcus Perryman’s Timed Camera Capture blog posting discusses how to modify the CameraCapture code sample to become a small DLL that can be called from a C# application to automatically take photos at a timed interval.
  • As an alternative MSDN Forums contains a thread titled “SendKeys” which discusses automating the existing CameraCaptureDialog (I actively discourage this approach due to the brittle nature of the code which could stop working with a new ROM update etc).

The main problem with the existing CameraCapture code sample is that it does not provide a live preview of the video or still image being captured. However by altering the DirectShow “filter graph” and some of the surrounding application logic, it should be possible to add a live preview stream that renders to a specified region of the screen.

If you have access to the MEDC 2007 conference CD it would be helpful to view the “ECE310 – The Windows® Embedded CE 6.0 MDD/PDD Camera Driver Model” presentation. Although it discusses a newer camera device model not yet available on the Windows Mobile platform, I found the presentation useful in learning how the existing version works, since the presentation discussed the benefits of the new driver model by comparing it to the older one.

A couple of things to be aware of while investigating the use of DirectShow capture graphs:

  • It could be significantly more complex than using the CameraCaptureDialog or SHCaptureDialog APIs depending upon your experience with COM based APIs.
  • Across a range of devices you may have slightly inconsistent behaviour. For example some devices return images that are upside down and need to be manually flipped to be viewed correctly on the LCD. The Windows Mobile Test Kit tested if a device had implemented the API correctly, but didn’t test the “correctness” of the images it generated. Apparently this issue has been improved so that newer Windows Mobile devices should more consistantly implement this API.

Hopefully this provides you with some guidance Stefan and thanks for contacting me. One of the reasons I started this blog was to connect with the development community, so it was great to hear from you.

How much interest is there for a custom control that could be used within a .NET Compact Framework application to perform the kind of tasks Stefan is after with a few lines of managed code?

How to determine where an application is installed

Monday, December 10th, 2007

Screenshot showing a messagebox describing where the application is installed on the filesystemMost Windows Mobile software is installed via the use of a CAB file. On recent versions of the Windows Mobile operating system CAB Files offer the user the choice of where to install the application. However numerious system APIs and features require the full path to the application’s executable to be specified.

This blog entry discusses how a .NET Compact Framework application can determine its installation location for use in such APIs.

How to determine the full path to the executable

using System.Reflection;
 
private string GetApplicationExe()
{
  // Determine the full path to the application executable
  return Assembly.GetExecutingAssembly().GetName().CodeBase;
}

The GetExecutingAssembly method returns an Assembly object that represents the Assembly that contains the code which called the GetExecutingAssembly method. Hence if this call is placed within code contained within the main executable it will return the path to the main executable.

An example return value may be “\program files\foobar\foobar.exe”. This value is useful to have for APIs such as SystemState.EnableApplicationLauncher which expect the full path to our executable to be specified. By not hard coding the path within our application we allow the end user to move the application around on their device without breaking the application’s functionality.

How to determine the directory containing the application
It is common for an application to install a number of configuration or data files required by the application. Since Windows CE does not have the concepts of a current working directory or relative paths full paths need to be specified when attempting to access these files.

By using the Path.GetDirectoryName static method we can extract the directory component of the path obtained above, so that we do not need to hard code the location of our support files.

using System.IO;
 
private string GetApplicationPath()
{
  // Return the full path to the directory our
  // application is installed within.
  string codebase = GetApplicationExe();
  return path.GetDirectoryName(codebase);
}

A nice helper method to include within an application is one which takes a name of a file (or subdirectory) which should be located within our application directory and returns a full path to that file.

string GetPathToApplicationFile(string filename)
{
  string path = GetApplicationPath();
  return Path.Combine(path, filename);
}

For example GetPathToApplicationFile(@”config\foo.txt”); would return a string similiar to “\Program Files\TestApp\config\foo.txt” where \Program Files\TestApp is the directory the application is currently installed in.

Sample Project

[Download DetectApplicationDirectory.zip - 11.8KB]

A small sample project is available for download. When the application is started it displays a Message box that displays the location of the executable. Notice that the application correctly determines if the CAB file has been installed on to a storage card or the main memory of the device. It will also cope with the application files manually being moved to a different location.

The CAB file also installs two text files within the application directory. By using the main menu you can load one of these files and display its contents within the window.

Making use of new APIs within older applications

Tuesday, December 4th, 2007

Each new release of the Windows Mobile platform tends to introduce a couple of new APIs. This blog post discusses a technique that Native developers can use to allow conditional access to these APIs while still allowing the application to run on older devices.

Introduction
Typically a developer creating a C or C++ application within Visual Studio would choose a device SDK that matches their target device. For example when creating a project for a Windows Mobile 6 Professional device the developer would typically select the “Windows Mobile 6 Professional” SDK within the New Project wizard. Compiling with a particular Device SDK “marks” the executable in such a way that it requires as a minimum that particular version of Windows Mobile in order to run.

Since the Windows Mobile platform strives for backwards compatibility this should also mean that the application would work on any newer version of the OS (but it would be constrained to accessing the subset of functionality exposed by the selected SDK).

Visual Studio includes a tool called Dependency Walker. Opening an exe or dll file within this application allows you to determine which version of the Windows Mobile OS an executable is designed for. This tool can typically be found within the C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin directory. The “Subsystem Ver” field as indicated in the above screen-shot shows the minimum version of the Windows CE kernel required for the selected program to run (see “What device is my application running on?” for a table of Windows CE kernel versions and their associated Windows Mobile releases). Trying to run an executable compiled for a newer version of the OS on an older version will result in an error message similar to the following:

Dependency Walker (as it’s name suggests) also allows us to determine which DLLs an executable depends upon and hence must be present on the device in order for the application to run. For example in the following screenshot the application has dependencies on aygshell.dll, phone.dll, and coredll.dll. If any of these DLLs are not present on a device, the OS will fail to start the application with the same error message shown above.

Accessing APIs from newer versions of the OS
Some times it is necessary to compile against an older device SDK while still allowing access to new APIs whenever the application is running on a newer device.

As an example, a previous project I worked on was compiled against the Pocket PC 2002 SDK, and there were a couple of hundred Pocket PC 2002 devices out in the field. When Windows Mobile 2003 Second Edition devices started showing up (which support dynamic screen orientation changes), it was desirable to access a new API to ensure the application always ran in Portrait mode, without switching the project over to the Pocket PC 2003 SDK (since that would mean needing to compile two versions of the app, or loosing support for the existing Pocket PC 2002 devices).

As an easy to follow example we will use the SndPlaySync API introduced in Windows Mobile 6, and discuss how to access this while building our application against the Pocket PC 2003 SDK.

When targeting the Windows Mobile 6 Professional SDK we could make use of this API as follows:

// Play the Alarm2.wav sound effect
#include <soundfile.h>
SndPlaySync(_T("\\Windows\\Alarm2.wav"), 0);

However attempting to run this executable on a Pocket PC 2003 device will fail because:

  1. The executable is marked as requiring Windows CE OS version 5.02 or higher.
  2. The executable indicates it depends upon a function called SndPlaySync being present within a dll called aygshell.dll. Although aygshell.dll exists on a Pocket PC 2003 device, it does not export a function called SndPlaySync.

Both of these facts can be confirmed via the use of the Dependency Walker utility as discussed above.

If we change our project to target the Pocket PC 2003 Device SDK we will notice that the project fails to compile. This makes sense, since changing the SDK changes the version of the Windows header files our project compiles against. The Pocket PC 2003 version of the Windows header files are clearly highlighting the fact that the SndPlaySync function does not exist on this version of the platform.

One solution to this problem is to dynamically link to this API. In other words when our application runs we manually load aygshell.dll and attempt to find the SndPlaySync function within it. If we find it we can make use of it, otherwise we can fail gracefully and provide some kind of fallback.

Within the Win32 programming environment we do this by making use of a function pointer typedef and the LoadLibrary and GetProcAddress APIs.

By looking at the MSDN documentation for SndPlaySync we can typically determine which DLL the API lives within, and determine a function prototype that is suitable for converting into a function pointer typedef. Depending upon the API in question, we may also need to copy any structs or #define’s utilised by the function that are not present in the older Windows Mobile header files.

An example of this technique is shown below:

// A typedef that defines a function pointer called SND_PLAY_SYNC that
// is capable of pointing to any function that has the same
// prototype as SndPlaySync
typedef HRESULT (* SND_PLAY_SYNC)(LPCTSTR pszSoundFile, DWORD dwFlags);
 
// Attemp to load aygshell.dll
HMODULE hLib = LoadLibrary(_T("aygshell.dll"));
if (hLib)
{
  // If we manage to load it attempt to get the address
  // of the SndPlaySync API located within it.
  SND_PLAY_SYNC pfnSndPlaySync =
    (SND_PLAY_SYNC)GetProcAddress(hLib, _T("SndPlaySync"));
 
  // If SndPlaySync is found then invoke it. Otherwise
  // provide a simple fallback, in this case a simple
  // message box. A more complete example may
  // have used an alternative sound playing API.
  if (pfnSndPlaySync)
    pfnSndPlaySync(_T("\\Windows\\Alarm2.wav"), 0);
  else
    MessageBox(GetForegroundWindow(),
      _T("Sorry we can not play a sound"),
      _T("Status"), MB_OK);
 
  CloseHandle(hLib);
}

This solution doesn’t magically make the API available on older devices. The key thing is it delays the check for the SndPlaySync API being present from launch time (by the OS) until runtime (by our code). If you use the Dependency Walker utility you will notice that there is no hard-coded dependency on the SndPlaySync API within this version of the application.

Sample Application

[Download BinaryCompatabilityExample.zip - 16KB]

A small sample application is available for download. It contains two projects. The first called “BadApp” targets the Windows Mobile 6 SDK and will fail to run on devices using an older version of the OS. The second called “GoodApp” targets the Pocket PC 2003 SDK and shows how to modify the source code of “BadApp” in order to make the application also run on older devices. As an added bonus the sample demonstrates how this solution can also resolve issues with devices using the same OS version but having different hardware capabilities. This issue has been discussed by Mel Sampat in regards to accessing phone functionality (some PDAs still come without any cellular capabilities).

A future blog posting will discuss how similar techniques can be implemented for .NET Compact Framework applications which use Platform Invoke (DllImport) functionality. This can be particularly handy for getting an application that makes use of PInvokes to work on both the desktop and PDA devices without the need of conditional compilation and multiple versions of the executable.

Using $exception within Visual Studio’s Debugger

Tuesday, December 4th, 2007

Here is a little tip that I discovered today. Quite often you will develop exception handling code that looks like the following:

try {
  // do something here which may fail
}
catch (FileNotFoundException) {
  // do some error handling here which
  // doesn't refer to the exception object
  // that has been thrown
}
catch (Exception) {
  // do some more generic error handling here
}

Since our exception handling code makes no use of the exception object that has been thrown, we do not need to declare a variable to reference it (i.e. the traditional “ex”). However this leads to an issue while debugging. Without a variable there is nothing to mouse over in order to display the exception’s contents once the initial popup has been dismissed.

Up until today I would typically modify the code to look like the following:

try {
  // ...
}
catch (FileNotFoundException ex)
{
  // ...
}

This allows me to mouse over the variable ‘ex’ in order to view the contents of the exception. However this meant that I needed to modify the source code and restart the debugging session (hoping I could re-create the error condition). It also meant that a compile time warning (”CS0168: The variable ‘ex’ is declared but never used.”) was produced, since the compiler correctly points out that I am not using this variable.

What I learnt today was that instead of doing this you can add the special variable $exception to the debugger’s Watch Window, or query it via the Immediate Window. This variable references the currently thrown exception when located within a catch block.

Screenshot of Visual Studio 2005 IDE showing the Watch Window display the value of the $exception variable

Now for the bad news, unfortunately this tip only seems to work for applications targeting the full Desktop framework, when developing a Smart Device or .NET Micro Framework project the watch window reports “The name ‘$exception’ does not exist in the current context”.