Windows Mobile Deployment for Developers
If you are anything like me, I walk away from events like Tech-Ed with an overflow of information in my head… wondering when the event team and speakers will share out all their content so I can process it at my leisure. Notes are good, but I always miss something. So here you go… I told you I would post a summary of my session content to make it easier. The TLC sessions didn’t allow slides, so I’ll stick to summarizing key points and links where you can get more info.
I put together this session because it seemed to me that installation topics were all over the place between CE and Windows Mobile….CABs, INFs, Visual Studio, CeAppMgr, Custom Setup Components… I wanted to tie them all together from a developers perspective. To set some expectations, I’m not going to talk about management software. Management software like Systems Center Mobile Device Manager (and many other) can solve a range of deployment problems, but as a developer – you need to understand how it all works underneath management solutions. After all, you might be writing the management solution. =)
When it comes time to deploy your application, the basic unit used to package Windows Mobile files and applications is a CAB file.
CAB files are most easily built using Visual Studio… new Project->Other Project Types->Setup and Deployment->Smart Device CAB Project. Visual Studio exposes the basic support for building CABs-- adding project output, files, dependencies, and modifying registry keys during the install. You can also set compression options on the CAB, define OS minimum and maximum version requirements, and specify a custom setup component.
When you build a CAB file, Visual Studio simply builds a simple .INF (text) file with all your project information and then invokes the CABWIZ.EXE utility which does the work. CABWIZ.EXE is the tool that builds your CAB and it does so by following instructions in the INF file that was passed to it as a command line param. This INF file can contain many more options than Visual Studio exposes, so if you need more capabilities (e.g. – restrict the install based on platform type, etc.)… check out the docs on the CABWIZ utility and the INF file format. You can package CABs without Visual Studio… it’s just a little more work building the INF yourself.
A CAB file is made up of a provisioning file (_setup.xml), one special .000 data file that is automatically generated (don’t worry about this one), and then all the individual files you included in the CAB project (they get renamed with incremental extensions like .001, .002, etc.). You can examine the _setup.xml file to see exactly what it does. It’s just provisioning XML. This is really handy when you need to reverse engineer a CAB file to understand why something is failing (not that I would encourage that kind of thing). Hmmm…. wonder what this CAB is doing at install time or why it might be failing? Just crack apart the CAB and examine the provisioning XML. The CAB itself can be expanded using a number of tools, like WinZip.
You can deploy a CAB any number of ways: Over-the-air (OTA), SD Card, or through a cradled desktop connection via ActiveSync of Windows Mobile Device Center (WMDC). I think of deployment in two parts….
1) Getting the CAB to the device
2) What happens with the CAB once it’s on the device
Getting the CAB onto the device
Getting the CAB onto a device is often just about making an accessible path to the CAB file itself. There are many ways to do this using OTA notifications.
· Send an SMS or email message with an embedded HTML link to the download location on a local share or a web site (I demonstrated what this might look like using the cellular emulator and sent an SMS message). The user could click on the link and presto…the install begins.
· Send the CAB attached to an email message. User selects the CAB.
· Hook a special incoming message and auto-install the CAB. In practice, I hope your users know better than to install an update from an external web site based on random message with a link in it. You could automate the install with a custom SMS handler or EMAIL message handler to automatically intercept a special update message and kick off the install transparently. Intercepting SMS is a no-brainer and there several examples using managed and native code. Intercepting email is a bit more work through the IMapiAdviseSink interface. You’ll need your C++ skills here.
· Inserting an SD card into a Windows Mobile device will typically launch an application called AutoRun.exe if it’s placed in a special, processor specific directory. You can use this directory and application hook to install CAB files that are also placed on the SD Card. Marcus posted a good working example of what this might look like here. You can also see the AutoRun sample in the SDK sample as a place to start writing your own AutoRun CAB installer.
· Use a client utility to or auto-updating application to check for a new version through a network connection and update the device automatically. Alex Feinman wrote a paper on this topic for Windows Mobile. The original Compact Framework Core Reference talked about this as “trickle-feed” deployment. There are app updater blocks posted on MSDN to do this for desktop clients (could be easily adapted to mobile). The concept is the same. Write a little app that looks for updates, pulls them down, and then fires off the installation to transparently update the device.
Now that the CAB is on the device
.CAB files are associated with WCELOAD which is the device-side utility that unpacks all the files and uses the provisioning engine to perform actions on all the components (file copy, registry mods, shortcuts, etc.). When you select a CAB, you’re really just launching WCELOAD.EXE with the CAB as a command line param. As with many of these components, WCELOAD supports a number of command line params that you can use if you’re launching it programmatically. This comes in handy if you are trying to do things silently and want to suppress the user interface (for example – auto update of an application).
Custom Setup Actions
When you do need to do something that falls outside of the normal installation steps inside your CAB, it’s typically done by building a custom setup DLL. A custom setup DLL is C++ DLL that exports four hooks:
- Install_Init – Fires right before the installation occurs
- Install_Exit – Fires right after the installation completes
- Uninstall_Init – Fires right before the uninstall occurs
- Uninstall_Exit – Fires right after the uninstall occurs
You can plug your own code into any of these functions and add your own custom installation actions. You specify your setup.dll either in your Visual Studio project before you build the CAB or simply add it into your INF before you call CabWiz.
What about deploying multiple CABs?
Deploying one CAB is pretty simple. What about if you want to include newer version of the Compact Framework, SQLCE, or supporting CABs? As it turns out, you cab package CABs within CABs. We call the big CAB the “master” or “uber” CAB. Build a big CAB containing all the individual CABs you want to deploy, then you can use a custom setup DLL to start a little app on Install_Exit that iterates through a CAB list and manually installs each one. Check out the WM6 SDK sample called MultiCabInstall. It not only shows you how to make all this work, but also demonstrates how to build a custom setup dll. There is a whitepaper included in the SDK sample directory that goes into detail of how this little solution works.
CeAppMgr and the Desktop Installation
If you want to build a desktop installation using an MSI or other installation product, you need to check out CeAppMgr. I did a detailed post on this earlier in the year, but to recap, it’s a component of ActiveSync and Windows Mobile Device Center that knows how to talk to a connected Windows Mobile device. If you have ever used RAPI, it uses the same connectivity framework. The idea behind all these solutions is to build your MSI that adds everything to the desktop and then fires a custom action to launch CeAppMgr.EXE with little text file (INI) that lists your CABs. Here’s a sample from MSDN to show you how. CeAppMgr will push out the CAB and install it on the connected Windows Mobile Device. If it’s not currently connected, it will queue it up to be deployed on the next connection.
Developer Deployment FAQs
Can I get to the command line params passed to WCELOAD from my custom setup dll?
Sorry, WCELOAD actually spawns off some worker processes and the original command line params are not available.
Why does my CAB fail when I install it silently?
When you install silently, the platform will always choose default responses during install. If a security prompt comes up on unsigned code, it will choose not to install (e.g. – fail)
Why do I always get security prompts even though I signed my CAB?
The CAB and *all* executable content within the CAB must be properly signed. If you forget to sign a dll within the CAB, the security check will fail. See me post on “When good signatures go bad…”
My desktop install fails when I pass a privileged signed CAB to CeAppMgr, what gives?
I’m still investigating this one. There does seem to be a bug that affects privileged signed CABs on Vista right now when CeAppMgr is launched under the SYSTEM account during the install process.
How can I programmatically uninstall an application?
Use the Uninstall CSP
CeAppMgr isn’t doing what I expect it to…what’s up?
CeAppMgr is *very* picky about command line params. Be sure to provide the entire path when you launch the EXE as well as full path with the CAB param (enclose it in quotes). Use the /report param to see what CeAppMgr is actually parsing out if you still have problems.
How can I suppress the option to install on a storage card during install?
Either remove the InstallDir setting in the INF or use the /noaskdest param in WCELOAD.
Where do I start when a CAB fails to install?
After it fails, check the \Application Data\Volatile directory on the device. Installation creates a setup.log file there and very often, you can search for “error” in this file and discover the source of the failure.
How does CeAppMgr and my INI file know which CAB to deploy when I list multiple CAB files?
See my previous post here