CLOG

A coder's BLOG from Todd S. Murchison

Recent posts

Disclaimer

The opinions expressed herein are my own and do not represent any other individual or organization.

© Copyright 2010

Windows Mobile 5 MSI Installers With CF2

I’ve recently jump through a number of hoops to put together an MSI install package for a Mobile 5 application that uses the Compact Framework 2.0. The goal was to provide a single file installation that includes the CF2 install CAB and the CAB for our application.

Microsoft actually provides a very helpful MSDN article on "Deploying .NET Compact Framework 2.0 Applications with .cab and .msi Files" ( http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetcomp/html/deploy_cf2_apps_cab_msi.asp). There are just a few things I’d like to add from my own experience.

1. Making your installer wait for ActiveSync to finish.

Part of the custom installation code you will be writing for the MSI is code to launch ActiveSync to have it deploy the various CAB files out to the connected device. The MSDN article provides good sample code for this. The only problem I see with the sample code is that it fires off ActiveSync and returns immediately. What this means is that your MSI desktop installer process will finish and say it’s done with the installation before ActiveSync has actually deployed to the device.

The fix for this is very simple. After launching ActiveSync simply wait for the process to exit. In C# this would look something like this:

System.Diagnostics.Process p = 
        System.Diagnostics.Process.Start({exe}, {args});
p.WaitForExit();

In C++ it takes a few more lines of code, but what you’d want to do is make a call to CreateProcess() filling in a PROCESS_INFORMATION structure. Then make a call to WaitForSingleObject(). As a note, I was unable to get CreateProcess() to work correctly until I gave it NULL for the exe and simply passed in the entire command line via the command line argument.

2. Getting the installer to correctly deploy CF2 and then your own CAB.

In the MSDN article we are told that the INI file used to register an application CAB with ActiveSync can contain multiple CAB files on the "CabFiles" line.

"Line 7 enumerates all of the .cab files that are used for this installation in a comma-separated list."

This may work for installations that do not require a reboot of the mobile device, but I was unable to get this to work for deploying CF2, rebooting, and the deploying our application CAB. The solution I found that works quite nicely is to actually launch the ActiveSync process once for each CAB to be installed. So, in my case I created two different INI files (one for each CAB) and then in my custom install code I simply sequentially launch ActiveSync twice (once for each INI file). So, my custom install code runs ActiveSync to deploy the CF2 CAB, waits for the process to finish, and the runs ActiveSync again to deploy our application CAB.

3. C#, C++, and desktop dependencies.

The last quark I had to muddle through involved making sure that our MSI installer did not create additional dependencies on the desktop computer. The MSDN article provides all sample code in C#. If you code your custom install actions DLL in C# you will be building a dependency on the .NET Framework into your installer. In order to run the installer the end user would be required to download all 20 some-odd megabytes of the .NET Framework first!

So, I coded my DLL in C++ using the C# sample code as a guide. Unfortunately, I built my C++ code using Visual Studio 2005. Why is this unfortunate, you ask? Because C++ built in VS 2K5 uses version 8 of the CRT. Most machines will not have version 8, so VS 2K5 auto-detects this as a dependency and auto-includes the CRT v8 DLLs in your installer. Cool... but wait.

The CRT v8 DLLs are considered "system components" and are installed into the Windows system directories. Well guess what, only administrators can do that. So, now, probably without even knowing it, you have an MSI installer that can only be run by administrators and can only be installed for "all users".

The solution is simple enough. Build your C++ DLL in an older IDE (Visual Studio 2003 or Visual Studio 6 would work). You can then take the already-built DLL and do the rest of the installer work in Visual Studio 2005.

Good luck with those MSIs!
-Todd

Currently rated 2.7 by 3 people

  • Currently 2.666667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by toddm on Saturday, October 28, 2006 6:13 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Related posts

Comments are closed