Archive for 2007

Determine which version of the .NET Compact Framework is in use

Monday, August 13th, 2007

Yesterday I outlined how an end user can determine which version(s) of the .NET Compact Framework are installed on a device. Sometimes it can be useful to query which specific version of the framework an application is currently running on. This could be used for instance, in automated bug report forms to provide your support staff with an accurate picture of the environment your application is being utilised within.

Within an application you can simply query the Envrionment.Version property to determine the version of the CLR your application is running on, for example:

MessageBox.Show(Envrionment.Version.ToString(), "CLR Version Number");

The version property is an instance of the System.Version class. To check if your application is running on a specific version of the .NET Compact Framework you can construct an instance of the Version class to represent the desired version number (see yesterday’s entry for a table) and perform a simple comparision, as the following example demonstrates:

Version targetVersion = new Version("2.0.7045.0");
if (Envrionment.Version == targetVersion)
     MessageBox.Show("You are running .NET CF 2.0 SP1", "Status");

Windows Mobile Tip: Determine which versions of the .NET Compact Framework are installed

Sunday, August 12th, 2007

Windows Mobile devices can come with different versions of the .NET Compact Framework installed in ROM. End users can also install various service pack releases etc. This blog entry outlines how in customer support scenarios you can determine which version(s) are currently installed on a particular device.

Overview
The .NET Compact Framework installs a utility called cgacutil.exe onto each device. This utility is primarily designed to allow the addition or removal of assemblies from the .NET Compact Framework’s GAC (see the section titled “The GAC” within Richard Grimes’s Fusion Workshop article for further details).

The utility however also has a handy feature which enables you to determine which version(s) of the .NET Compact Framework are currently installed.

How to run cgacutil.exe
On Pocket PC or Smartphone devices you can use the File Explorer application to navigate to the \Windows directory. Within this folder you will find the cgacutil.exe application which you can launch by tapping on it. As an alternative you could use the run dialog tip I mentioned earlier by typing “cgacutil” into the run dialog.

Once cgacutil is started a popup message box will appear which will list the version numbers of currently installed version(s) of the .NET Compact Framework.

Picture of message box displayed by cgacutil application showing which versions of the .NET Compact Framework are installed

If more than one version of the .NET Compact Framework is installed, these will be listed in a comma separated list.

Comparing .NET Compact Framework version numbers to releases
To convert the version numbers reported by cgacutil into the names of the co-responding .NET Compact Framework releases you can compare them to the following table:

Release Name Version Number
1.0 RTM 1.0.2268.0
1.0 SP1 1.0.3111.0
1.0 SP2 1.0.3316.0
1.0 SP3 1.0.4292.0
2.0 RTM 2.0.5238.0
2.0 SP1 2.0.6129.0
2.0 SP2 2.0.7045.0
3.5 RTM 3.5.xxxx.0

This table contains all current versions of the .NET Compact Framework. I however have not included any BETA or CTP (Community Technology Preview) releases as these are generally found only on devices owned by developers.

The .NET Compact Framework v3.5 has not been released to manufacture (RTMed) yet. Hence the exact version number is not known at this time. The entry in the table above is only for indicative purposes only, I do not know which digits will replace the xxxx part of the version number at this stage.

.NET Compact Framework presentation links

Wednesday, August 8th, 2007

A big thank you for all those that turned out for my presentation at the Christchurch branch of the New Zealand .NET User Group. There was quite a large turnout, and I hope that you all found some value in my presentation.

This was my first presentation of any form, and it was a very useful learning experience. I have defiantly learnt some things which will help improve future presentations I may present. I would be interested in hearing any feedback you may have on my presentation (good or bad), both in content and the way it was presented.

For those that could not make it (I know there were a few), I have uploaded the powerpoint presentation to www.slideshare.net. During the presentation I mentioned that I would provide a list of related website references for the various topics and products discussed, these have been attached to the bottom of this posting.

If anyone would like to discuss Windows Mobile development topics (native or managed), please feel free to get in contact with me. For development problems I would suggest trying the MSDN Forums website, as there are a number of active participants found there (including myself).

The Device Landscape

Development Environments

.NET CF – Platform Support

Screen Differences

Image Capture
Remember that these classes can be used in both .NET CF 1.0 and .NET CF 2.0 applications. They are however only present on Windows Mobile 5.0 or higher devices.

Network Communications
Disconnected Service Agent – a way to “cache” web service method calls when disconnected from the network and to automatically execute them when the connection comes back. See Smart Client Software Factory links below for the full documentation, or see the following post on MSDN forums for a brief overview.

Data Access

Development Tools

Getting Started

Diving Deeper

Where to get help

Reminder: Introductory Compact Framework Presentation

Monday, August 6th, 2007

Picture of a projectorJust a quick reminder that the presentation I mentioned previously is on this Wednesday night. The topic of my presentation is “Introductory Compact Framework Development”.

Further details can be found on the New Zealand .NET User Group website. Please register, as numbers are used to determine how much beer and pizza is required.

Presentation Summary

The internet has helped to shorten the distance between countries.

Likewise mobile computing has started to extend the reach of the office out into the field. The .NET Compact Framework is the .NET based platform for developing software for mobile workers utilising Windows Mobile based PDAs. This presentation will introduce the capabilities and history of the platform as well as providing lots of tips and tricks on how to develop your own applications.

Come along to find out what the difference between Windows Embedded CE and Windows Mobile is. Why the WinPad project failed, or simply to learn how to develop for this exciting platform.

About the presenter:
Christopher Fairbairn has spent the last 7 years specialising in software development in the mobile environment. He currently works for ARANZ Medical Limited in the Christchurch CBD. His current personal project is porting Google Gears to the Windows CE platform.

I hope to see some of you along at the Canterbury Innovation Incubator this Wednesday at 5:30pm.

Programmatically create and display Notifications

Thursday, August 2nd, 2007

Screenshot showing an example popup notification on a Windows Mobile 6 Professional deviceThe Windows Mobile operating system provides a Notifications feature which can be utilised to display prompts to the user in the form of toast or popup balloons (depending upon operating system version) even when your application is running in the background. These are ideal for when your application must inform the user that background tasks have completed, or that particular actions must be performed. This blog entry discusses how you can utilise notifications within your own applications.

Supported Platforms
Notifications are only supported on Windows Mobile Professional or Classic (i.e. Pocket PC) devices, they are not supported on Windows Mobile Standard (i.e. Smartphone) devices. If you develop a Compact Framework application which uses notifications, the application will compile when you target a Windows Mobile Standard device, but will cause a NotSupportedException when the application is ran on the device.

To utilise the Microsoft.WindowsCE.Forms.Notification class you must add a reference to the Microsoft.WindowsCE.Forms.dll assembly.

One of the easiest ways to obtain this reference, and to configure your notification is to drag a “Notification” component from the Toolbox within Visual Studio 2005 (it is located within the Device Components category). Doing this will automatically added the needed reference to your project, and allow you to configure the notification’s properties graphically via the Properties window.

Notification Properties
The notification class has a number of properties which control the look and feel of the notification balloon. These properties are as follows:

  • Caption – the text displayed in the caption bar at the top of the notification balloon.
  • Text – a string containing the HTML content to display in the main part of the notification popup. This enables you to use formatting, and different colours within your notifications.
  • Critical – a boolean flag, if set to true this indicates that the notification is of urgent importance. This has the effect of using a different colour border around the edge of the notification.
  • Icon – The icon to display on the nav bar for the notification. The user can tap on this icon to display a hidden notification, so it should be representative of the meaning of the notification.
  • InitialDuration – the number of seconds the notification should appear on the screen when initially made visible. After this duration has expired the notification will hide itself, and the user will have to tap on the icon on the nav bar to make it re-appear. If this value is set to zero the popup notification is not displayed, instead going straight to the icon on the nav bar.
  • Visible – setting the Visible property to true, will make the notification balloon appear on the screen.

Displaying a notification
To display a notification to the user is as simple as creating an instance of the Notification class, setting up the properties for the desired effect, and then finally setting the Visible property to true to make the notification visible to the user. This is demonstrated in the following sample:

using Microsoft.WindowsCE.Forms;
 
private Notification n = null;
 
private void button1_Click(object sender, EventArgs e)
{
  // Create an instance of the notification class and configure
  // its properties for the desired effect.
  n = new Notification();
  n.Caption = "Hello World!";
  n.Text = "<b>This</b> is a <u>sample</u> notification!";
  n.Critical = false;
  n.Icon = Properties.Resources.NotificationIcon;
 
  // Finally to make the notification appear on screen
  // set the Visible property to true.
  n.Visible = true;
}

One important thing to notice is that we have not used a local variable within the button1_Click method to hold the Notification we are displaying to the user. The reason for this has to do with the CLR and its Garbage Collection behavior. Although the code may work if you use a local variable, it is not guaranteed and will potentially lead to unpredictable behavior (more on this in a later section).

The only property which deserves further discussion is the Icon one. You can store an icon in a number of ways. Perhaps the easiest way to store an icon in your executable is to use the Resources.resx file the Visual Studio 2005 project wizard will have created for you. The following screenshot demonstrates where you can find this file within solution explorer. If you open the file you can add new icon(s) into it, and these icons will be accessible via strongly typed properties within the Properties.Resources class, as demonstrated by the code sample above.

Screenshot of Visual Studio 2005 demonstrating how to find the Resources.resx file to include the icon resource

Hiding a notification
There are two different ways you can remove a notification which is visible on the screen.

You can simply set the Visible property to false, as the following example demonstrates:

// Using this approach to hide a notification will allow you
// to re-display it by changing the Visible property back to true.
n.Visible = false;

This has the benefit that you can decide to re-display the notification, by simply resetting the Visible property back to true. You can change the Visible property as many times as you like.

The alternative approach is to call the Dispose method of the Notification class, as the following example demonstrates:

// Using this approach will hide the notification but won't
// allow you to re-display it without creating a new instance
// of the Notification class.
n.Dispose();

Once you have done this you will not be able to display the notification again, without creating a new instance of the Notification class.

Previously we mentioned that you should not use a local variable to reference your Notification object. This last code sample demonstrates the reason why. If you had stored your notification in a local variable within the button1_Click method, the garbage collector would detect your variable as potential garbage when the method completed. If a garbage collection occurred, and decided to collect this reference, the garbage collector would call the Dispose method on the notification, which would remove it from the screen. By keeping a reference to the notification “alive” for the life time of the form (by using a member variable to reference it) the garbage collector will not be able to dispose of it until the form is closed.

Detecting when the notification is hidden
The notification class has a BallonChanged event which fires whenever the notification balloon is made visible, or hidden.

The following example, demonstrates how you can listen to this event, in order to perform a task when the popup balloon is hidden:

Notification n = new Notification();
// configure the notification properties...
n.BallonChanged += new BallonChangedEventHandler(n_BallonChanged);
 
void n_BalloonChanged(object sender, BalloonChangedEventArgs e)
{
  // The Visible property indicates the current state of the
  // popup notification balloon
  if (e.Visible == false)
  {
    // If the balloon has now been hidden, display a message box
    // to the user.
    MessageBox.Show("The balloon has been closed", "Status");
  }
}

Sample Application
Screenshot of sample applicationA sample application is available for download, which demonstrates the use of the Notification class. It enables you to experiment with the various properties of the notification class, and see how they alter a notification.

There is one member of the Notification class which we have not discussed in this blog entry. This is the ResponseSubmitted event which can be used to process feedback provided by the user when they dismiss the popup notification. For example in the HTML text of a notification, you could create a couple of radio buttons, and a text field. By handling the ResponseSubmitted event you can determine what values the user has entered and use them to alter the behavior of your application. Covering how to utilise the ResponseSubmitted event to process HTML based forms will be the topic of a future blog entry.

Send and receive Win32 messages in managed code by using the MessageWindow class

Tuesday, July 31st, 2007

The System.Windows.Forms namespace is a wrapper around the native Win32 GUI functionality provided by the operating system. The .NET Framework does a pretty good job at hiding the specifics of the Win32 APIs from managed developers, providing them with a more object orientated programming model. However the managed wrappers do not provide access to all features present in the underlying OS. This is especially true of the .NET Compact Framework. One technique to access native functionality which is not supported by the .NET Compact Framework is to send window messages. This is the subject of this blog entry.

Requirements
This blog entry is specific to .NET Compact Framework v2.0 or higher. Although most of the concepts are usable in .NET Compact Framework v1.0, you will need to do some additional work, since some of the properties utilised in the samples are not directly available in the older version of the .NET Compact Framework.

To get the code samples within this blog entry to compile within your projects, you must:

  • Include a reference to the Microsoft.WindowsCE.Forms assembly
  • Include a “using Microsoft.WindowsCE.Forms” statement at the top of your source code file

What is a Window and what is a Message?
The Win32 GUI platform is built around the concept of “windows”. A window is a rectangular section of the screen. Any window can also have additional child windows, which are windows contained within the rectangular space allocated to their parent.

The concept of a window is an overloaded term. The Win32 Operating System APIs not only consider Forms to be windows, but also controls you commonly place on a form such as TextBoxes or Labels. What differentiates the behavior and look and feel of these different windows is their “window class”.

Within the Win32 GUI API windows communicate with each other via the concept of messages. Messages are sent to a specific window to inform them whenever events such as typing, or tapping on the screen occur. Other window messages are of a more house keeping nature and indicate that a window should repaint itself etc.

For the purposes of the Win32 GUI APIs a windows message has the following properties:

  • Message Type – used to differentiate between different types of messages
  • WParam – a value, the meaning of which depends upon the type of message
  • LParam – essentially the same as WParam, another message type dependent field

Within the .NET Compact Framework, a window message is represented by the Microsoft.WindowsCE.Forms.Message class.

Finding a Window Handle
In order to send a message to a window you must obtain it’s handle. A handle is simply a special value which uniquely identifies a particular window to the native Win32 GUI APIs.

In many cases you can easily obtain a window handle for a control within your application by querying the Handle property of the desired control. This property is available on all the GUI controls (including forms), because they all eventually derive from the Control base class.

The following example demonstrates how you may obtain the window handle of a textbox placed onto your form:

private void button1_Click(object sender, EventArgs e)
{
  // Obtain the window handle for a textbox control
  // called 'textBox1' which we have placed onto the form
  IntPtr hwnd = textBox1.Handle;
}

By convention window handles are typically referred to as HWNDs, this is Hungarian notation for “Handle to a Window” and can be traced back to the days when C developers prefixed their variables with a description of the variable’s data type.

Sometimes you need to send a message to a window created by another application. In this scenario you do not have a Control instance to query the Handle property. In this case you need to ask the operating system to search for the window given it’s name.

The .NET Compact Framework does not support this, so you will need to Platform Invoke a native Win32 API called FindWindow, as the following example demonstrates:

using System.Runtime.InteropServices;
 
[DllImport("coredll.dll")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
 
private void button1_Click(object sender, EventArgs e)
{
  // Find a window with the name "Test Application"
  IntPtr hwnd = FindWindow(null, "Test Application");
}

Fabien Decret mentions in his blog posting titled “Find a Window Handle” how you can use the Remote Spy utility to determine the name and window class of a particular window.

Sending a Message
To send a message to a window we simply create an instance of the Message class and configure it’s properties to the desired values. We then pass the message along to the MessageWindow.SendMessage static method to have it sent.

The following example demonstrates how to send a WM_CLOSE message to the File Explorer application, which will have the effect of closing it.

// Define the window message we want to send
const int WM_CLOSE = 0x10;
 
// Find the window we want to send the message to
IntPtr hWnd = FindWindow(null, "File Explorer");
 
// If the window was found, ask the application to close
if (hWnd != IntPtr.Zero)
{
  // Create a WM_CLOSE message (it doesn't use the lParam
  // and wParam fields so we set them to zero) and send the
  // message to the window
  Message msg = Message.Create(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
  MessageWindow.SendMessage(ref msg);
}

The documentation for the WM_CLOSE window message can be found on MSDN. This documentation explains the interpretation of the lParam and wParam parameters, as well as outlining at the bottom of the page, which header file we need to look in to obtain the value of WM_CLOSE (i.e. 0×10).

There is also a MessageWindow.PostMessage method, which is utilised the same way as SendMessage except that unlike SendMessage it does not wait for the message to be processed by the window it is sent to before returning.

Receiving a Message
On the desktop, the Control class provides a WndProc method which can be overridden to process any window message sent to the control. The Compact Framework however does not provide the WndProc method for us to override, so there is no (easy) way to see window messages sent to a control.

The .NET Compact Framework instead has a special class called MessageWindow which enables the creation of a hidden window that provides a virtual WndProc method which can be overridden to process any window messages sent to it.

To make use of this class applications must derive a class from MessageWindow and then override the WndProc method so that messages sent to the window can be processed.

The following code sample shows how to derive a class from the MessageWindow base class:

public class MyMessageWindow : MessageWindow
{
  // The window message type we want to process
  public static readonly int WM_USER = 0x400;
 
  // This method gets called for every window message this
  // window receives.
  protected override void WndProc (ref Message m)
  {
    // Check if it is a message we want to handle
    // based upon it's message type
    if (m.Msg == WM_USER)
    {
      // This is a message we recognise, so lets
      // process it. In this case we'll display a message
      // box
      MessageBox.Show("Hello - i received a window message");
    }
 
    base.WndProc (ref m);
    }
}

Because this is a managed application, there is no definitions available for the standard window messages such as WM_USER. A glance at the MSDN Documentation for WM_USER will confirm that the definition can be found within the C header file winuser.h, managed developers need to duplicate this definition in their own applications, as the code sample demonstrates. WM_USER is a good message number to utilise, since Microsoft defines this message number as the starting point for user defined messages.

Once we have defined our MessageWindow subclass we simply need to create an instance of the class to create the hidden window. The class has an Hwnd property which provides the window handle we need to send messages to in order for them to be processed by this window.

The following code sample demonstrates how to create an instance of the MyMessageWindow class, and then send a window message to it.

// Create the hidden window
MessageWindow msgWindow = new MyMessageWindow();
 
// Send a message to it
Message msg = Message.Create(msgWindow.Hwnd,
    MyMessageWindow.WM_USER, IntPtr.Zero, IntPtr.Zero);
MessageWindow.SendMessage(ref msg);

The previous code sample is not a typical use case of a message window. Typically the window will be created by one part of an application, and a message will be sent to the window from an unrelated part of the application (or even another application entirely). This leads to a problem, since the code which sends the window message will typically not have access to the window handle (Hwnd property value) to know where to send the message.

In this case you may like to set your MessageWindow’s Text property to something uniquely identifiable as your application. You can then use the FindWindow approach mentioned previously to find the window handle by passing in the same string.

Practical Uses
Sending window messages can be utilised for a number of purposes, but they are mainly utilised to interface to external applications. The following references are to real life situations where sending window messages is useful:

Sample Application
I have put together a small sample application to demonstrate some of these techniques. the easiest way to play with the demo is to open up the “SenderApplication” and “SecondApplication” projects into two instances of Visual Studio 2005. You will then be able to follow the “demo script” below:

  1. Start the “SecondApplication” in the debugger (press F5)
  2. Start the “SenderApplication” in the debugger (press F5 – also ensure you select the same emulator/device)
  3. Click the “Click another button” button and notice how the application behaves as if the “Show a Message Box” button was pressed. This is because a button click window message is being sent to the message box button whenever the first button is clicked.
  4. Click the “Display message in another app” button. Notice how the second application pops up and displays a message box stating the current state of the checkbox in the first application. This is because the “SenderApplication” has sent a window message to the MessageWindow created by the “SecondApplication”.
  5. Dismiss the message box and minimise the “SecondApplication” to return to the “SenderApplication”.
  6. Change the state of the checkbox and click the “Display message in another app” button a couple of times to see how the two applications are communicating the state of the checkbox.
  7. Press the “Close other app” button, and notice that the “SecondApplication” application shuts down (which will cause Visual Studio to stop debugging that project).

This blog entry neatly covers some of the background theory on something I have been working on quietly in the past few days, hopefully early next week I’ll have an interesting application to blog about….

Visual Introduction to .NET Micro Framework

Monday, July 30th, 2007

Confused about the .NET Micro Framework and what scenarios it enables? Or wondering how it compares to the .NET Compact Framework? Finding the documentation heavy going?

The following videos may help explain the differences, and give you some neat ideas for possible applications of the technology.

.NET Micro Framework resources

Sunday, July 29th, 2007

Over the weekend I have found some more .NET Micro Framework developer resources available on the Internet.

  • Kudzu World – “Programming is an art form that fights back”. This is the personal website of Chad Z. Hower, which has a .NET Micro Framework related section. It is essentially an index to blogs, development boards and other resources Chad has discovered.
  • .NET Micro Framework for Dummies – This is a promising new blog by an unknown developer (I could not find any contact details on the blog) who is in a similar situation to me. He has brought a Tahoe development board, and is blogging about his experiences learning to develop for the new platform.
  • Jens Kühner – “Geek stuff about the .NET, Compact and Micro Framework”, a reasonably new blog by Jens Kühner who is currently writing a book about the .NET Micro Framework. He promises to provide further tips and tricks as his book writing continues.

It will be interesting to see how these resources develop over time, many are at an earlier stage of their development (similiar to my own blog).

Another link of interest is a presentation titled “.NET Micro Framework – Brining .NET to smaller embedded devices” which appears to be developed by Microsoft. This is a worthwhile read, for those wanting to get a good overview of the platform. Sorry about the link (it points to a random PDF on someones website), but I discovered it via a Google search results page, and have not managed to find a better page to link to.

Simon Tatham’s Portable Puzzle Collection for Windows Mobile

Sunday, July 29th, 2007

Screenshot of Galaxies puzzle game running on a Windows Mobile deviceLast week I came across Simon Tatham’s website via a blog posting by Jon Skeet. One of the interesting finds on his website was his Portable Puzzle Collection. This is a series of approximately 27 puzzles which have been architected to be easily ported to new platforms. At present Mac OS X, Unix (using GTK as the GUI toolkit) and Windows builds are officially supported.

Dariusz Olszewski has contributed patches for the existing Windows build to target Windows Mobile (Pocket PC 2003 or higher). I recently submitted a small patch to improve the Windows Mobile port to cope with devices which can dynamically change screen orientation. I have also locally modified the build script to compile with Visual Studio 2005 rather than Embedded Visual C.

I particularly like the Galaxies puzzle, it’s very simple, but addictive at the same time. It also exercises the right side of the brain, as you try to determine if a particular shape will have rotational symmetry.

These games are well worth a look at, and I encourage any C developer with a little spare time to look into improving the Windows Mobile port (source code can be obtained from a SVN repository at svn://ixion.tartarus.org/main/puzzles). These puzzle games are an ideal way to fill in a few spare moments of time.

Windows Mobile Tip: Peeking inside CAB files

Saturday, July 28th, 2007

CAB files are the standard installation mechanism for Windows CE powered devices. Have you wondered what files have been installed by a given piece of software? Or what registry settings may have been overwritten during installation? If so, then this tip is for you.

CAB File Formats
A Microsoft CAB file is similar in nature to a common ZIP, or TAR file. They are a form of archive which contain one or more files. The individual files within a CAB file may have been compressed to reduce the overall size of the archive.

This archive file format has been re-purposed for application installation on Windows CE devices, by specifying a file with a special name that outlines the tasks required to install a given software package. This list of tasks will typically include decompressing and copying various files onto the PDA, but may also contain instructions to configure registry settings, or install shortcuts into the start menu etc.

Over the years the precise format of these files has changed. For a while the Windows Mobile Pocket PC and Smartphone platforms had incompatible CAB file formats. This has been resolved since the Windows Mobile 5.0 release which brought about a “unified” CAB file format for both platforms.

The older style CAB files had the list of setup instructions listed in a binary formatted file. The only information I am aware of on the structure of these CAB files is some reverse engineered documentation produced by the developers of the cabextract project.

The newer style CAB files have the list of setup instructions listed in an XML file called _setup.xml. It is this particular format that I will discuss here.

Extracting the contents of CAB files
On a desktop PC there are a number of ways you can extract the individual files within a CAB file. These include:

  • expand.exe – the Microsoft File Expansion Utility is a command line application present on all Windows machines. Specifying the name of a CAB file will cause the CAB file to be extracted into the current directory.
  • explorer.exe – by default most recent versions of Windows have an explorer shell extension which enables users to browse the contents of a CAB file by simply double clicking on it (as seen in the screenshot).
  • Winzip – many third party archive utilities will associate themselves with CAB files and enable you to extract their contents.

If you extract the _setup.xml file you can confirm that it’s main element is <wap-provisioningdoc>. This is a WAP provisioning document, as documented in MSDN in the Configuration Service Provider section.

The particular subset of this file format used by typical CAB files is fairly straight forward to follow, even without referring to the documentation. The _setup.xml file will enable you to determine the proper file names for the other files within a CAB file, and more importantly where they are installed to. One thing to be aware of is the use of macro Strings such as %CE2% to cope with internationalisation within file paths.

Possible uses of this tip
During development of an application, using this tip can be handy to verify that your CAB files are installing the desired files and settings. It is also useful when you have a CAB file which you have lost the original source code to, to determine what changes are made to the device.

The information would also be of use if you are developing an application to merge individual CAB files into one combined CAB file, such as the application discussed by Chris Tacke on his blog.

Random CAB fact of the day
Did you know that CAB files transfered via ActiveSync may be altered during the transfer process? If you have a CAB file which has been authenticode signed with a certificate, ActiveSync may strip off the certificate during the transfer process if it determines the connected device does not support signed cab files. This is something to be aware of, if you notice your CAB files won’t install if you download them across the network, but will if manually transfered via ActiveSync.