After developers master the art of building CABs and signing code, they often look to compliment their deployment story by providing a desktop based install package. 

There are a lot of reasons to have a desktop install for mobile apps.  Many end-users are simply used to (and more comfortable with) running desktop installs.  You might also build a desktop application that *extends* to a mobile device -- install the desktop piece first and then push out the right mobile CAB as the mobile client.  What if you ship multiple versions of your software for all the versions of our platform and want to simplify the user install experience (e.g. - WM2003 Pocket PC, WM2003 Smartphone, WM5 Smartphone, etc.) to the end user doesn't have to figure out which CAB is the right one.  My point is...many partners still have their reasons to ship multiple app versions and multiple CABs. 

What about the enterprise?  Some enterprise customers will use over-the-air (OTA) deployment products, but many still need to work with desktop based management software, so desktop installation is far from dead...we still need this scenario. 

So how do you build a desktop install for a CAB?
When you ask this question, developers commonly start talking RAPI and thinking of ways to write code that will interrogate a connected device and push out a CAB.  You could certainly write it yourself... but did you know that ActiveSync and WMDC already do this for you?  No major coding necessary.

Some CAB Basics
Before I go into more detail, let's first cover the basic concepts of what happens when you install a CAB on Windows Mobile.

If you look in the registry to see what a .CAB file is mapped to on the device, you will find it simply launches a program called WCELOAD.EXE.  WCELOAD is the device side application that is responsible for unpacking a CAB and directing the install sequence for the content.  It also supports a number of command line params to control exactly how it behaves (silent install, no uninstall option, etc.).  We won't get into all of that here, but if you are interested in those options, go check out MSDN here.

When I select a CAB on a Windows Mobile device, what I am really doing is simply launching WCELOAD and passing it the CAB as a command line param.  WCELOAD unpacks everything and handles the install details through a couple of worker processes it spins off.  This include calling any custom setup DLL you may have packaged in there and adding all the plumbing to use the UnInstall CSP to remove the app later.

That's what happens on the device... so to make it happen from the desktop, you just need to push out a CAB over ActiveSync and launch it right?

Introducing CeAppMgr
Installed as part of ActiveSync and WMDC, there is a desktop application called CeAppMgr.  You have probably seen it run and never realized what it was.  It's role in life is to push out and launch the install of a CAB on a device that may be connected to the desktop.  It already knows how to identify the device connected to your desktop-- platform, version, etc.  It follows a set of rules to make sure the CAB it is pushing out is valid for the connected device.  It will also queue up a CAB to install on the next connection if the device is temporarily disconnected.

CeAppMgr and it's workings are not well documented so I thought I would blog about a few things that have helped some partners get over hurdles using it.  Some details of CeAppMgr are outlined here, but to summarize -- it revolves around two primary pieces.  A CAB and an INI file.  The INI file consists of the application info, version, and a list of potential CABs. 

An example is worth a thousand words.  On XP, check out \program files\Microsoft ActiveSync.  On Vista, check out \windows\windowsmobile.  Look for application directories underneath these folders.  Typically, when an application is installed via CeAppMgr, you will find a directory containing the CABs and INI file here.  If you have installed mobile apps, you probably have some of these hanging around on your hard drive.  For example, I have a directory for Pocket Streets containing its CABs and INI file.  Let's look at that INI file:

[CEAppManager]
Version = 1.0
Component = PocketStreets

[PocketStreets]
Description = Microsoft Pocket Streets - View local maps and search for addresses, places and points of interest.
CabFiles = PocketStreets.PPCArm.cab,PocketStreets.PPCMips.cab,PocketStreets.PPCSh3.cab
Uninstall   = {AEFD48FE-2A76-11D3-928B-00C04FB90523}

To install an application from a desktop to a connected device, I just need to push over the appropriate CAB file and kick off WCELOAD.  This is exactly what CeAppMgr does.  It interrogates a connected device to understand what it's talking to and then picks a CAB from the list of potential CabFiles in your INI to find the best one.  For example, in the Pocket Streets sample above, there are three CAB files available-- PocketStreets.PPCArm.cab, PocketStreets.PPCMips.cab, and PocketStreets.PPCSh3.cab.  How does it know which one to push?

Depending on how you built your CAB (CabWiz.exe abstracted through Visual Studio or directly via the command line), you may remember specifying all kinds of options in the .inf file about version, cpu, and or/or platform.    Once the CAB is built, this information in embedded in the CAB and used by the install components like WCELOAD and CeAppMgr to determine what type of platform the it can be deployed on.

Let's look at what happens in the case of Pocket Streets if you cradle an emulator or device and fire off the following command line:
c:\windows\windowsmobile\ceappmgr.exe "c:\windows\windowsmobile\microsoft pocket streets for poc
ket pc\PocketStreets.PPC.ini"

CeAppMgr parses the [CabFiles] line in the INI and processes each CAB—left to right.  We grab the CAB and then try to match on CPU first.   Then we rule out unsupported platforms.  Next we try to match base version max/min info.  *If* platform info is available, it overrides version info.  Any CAB that matches CPU and platform automatically wins and the search stops there, otherwise we continue parsing the CABs for best match.  In summary it:

1)       Checks if the cab has specified a cpu type and if it does if it matches the current device
2)       Checks to see if the cab specifies any unsupported platform(s) and makes sure none of those matches the current device
3)       Checks to see if the cab specifies any supported version info.  If any platform info is provided (must have platform type and version numbers), it wins over basic version info

Although there are three CAB files supplied in the INI, CeAppMgr picks the right one and pushed out only the ARM version.  In this case, we have CABs build for different CPUs, but you could also use this technique to include CABs for different Windows Mobile platforms and versions. 

Can more than one CAB having matching criteria for a connected platform?  Yes -- that's why it's important to know how CeAppMgr prioritizes its selection to know which one (and in which order) it will pick.   It's also important to know what kind of criteria and CAB order you can use to ensure CABs don't match unintended platforms.

Cheers,
Reed