Ralph Arvesen
Vertigo Software, Inc.
March 2003
Applies to:
Microsoft® .NET Compact Framework 1.0
Microsoft Visual Studio® .NET 2003
Summary: Learn how to create a single .msi file that is run from the desktop to install an application on different Pocket PC devices. The development process is automated so it's easy to build and package all of the necessary components into the .msi file. Sample code is provided for C# and VB.NET. (21 printed pages)
Download Deployment.msi.
Overview
Deployment
Uninstalling
Development
Automating the Development Process
The following are key points when developing and deploying Pocket PC applications:
The deployment process and uninstalling are discussed first, followed by development and automating the development process.
Users can install Pocket PC applications by copying and running the appropriate .cab file to their device, but a better solution installs the application on the device by running an .msi file on their desktop. This .msi file detects the type of device, copies the correct .cab file to the device, and installs the application by running the .cab file. All of this is transparent to the user; they run an .msi file on their desktop and the application is automatically installed on the Pocket PC.
The following are the steps involved in the msi-based deployment:
The diagram below shows the pieces involved in this process followed by information on each piece.
Figure 1. Pieces involved in the deployment process
The .msi file is the single file that installs your Pocket PC application from the desktop. The user runs the .msi file and it unpacks processor-specific .cab files, a customer installer component, and a setup.ini file.
Pocket PC applications are installed by running .cab files on the device. These are self-extracting files that contain installation instructions and all of the files required by the application. The files are processor-specific, so a separate .cab file is required for each processor type supported by the application.
This is a custom installer component that is executed during the installation process. It runs the WinCE Application Manager to copy and install the correct .cab file to the device.
This initialization file describes the application to the WinCE Application Manager and is required to install apps through the application manager.
The WinCE Application Manager (CeAppMgr.exe) resides on the user's desktop system and is used to install and uninstall applications on Pocket PC devices. The following shows the application manager prompting the user to install the sample application on the Pocket PC device.
Figure 2. Installing a Pocket PC application from the desktop
The .cab file stores information on the Pocket PC so the application can be uninstalled. Users can uninstall the application using the Pocket PC directly or from the desktop. To uninstall the application using the Pocket PC, users select Remove Programs from the Settings application as shown below.
Figure 3. Using Pocket PC to uninstall an application
Just like installing, users can also uninstall the application from their desktop. They select the application from the Control Panel application Add or Remove Programs and click the Remove button. This executes the custom installer component that runs the WinCE Application Manager in uninstall mode (does not specify a setup.ini file). The user unchecks the application and clicks OK to uninstall the application from the Pocket PC device.
Figure 4. Uninstalling a Pocket PC application from the desktop
The development goal is to generate the .msi file with the least amount of work (one click if possible). First let's see what pieces are involved in the development process:
The diagram below shows the pieces involved in this process followed by information on each piece.
Figure 5. Pieces involved in the development process
The BuildCab.bat file builds processor-specific .cab files by running the Cab Wizard tool. Visual Studio generates a template BuildCab.bat file when you select Build Cab Files from the Build menu. It's a good idea to let Microsoft® Visual Studio® generate this file, then copy it to a different location and make any changes. Most likely, the only change required is specifying a new path for the .cab and log files. The sample BuildCab.bat is shown below.
"C:\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\..\bin\..\bin\cabwiz.exe" "c:\program files\pocketpc deploy sample\Source\CS\PocketApp\BuildCabs\PocketApp_PPC.inf" /dest "c:\program files\pocketpc deploy sample\Source\CS\PocketApp\BuildCabs\Cabs" /err CabWiz.PPC.log /cpu ARMV4 ARM SH3 MIPS X86 WCE420X86
The Microsoft Windows® CE .NET .inf file specifies installation settings and application files to the Cab Wizard. Like the BuildCab.bat file, Visual Studio generates a template .inf file when Build Cab Files is selected. You should initially generate this file with Visual Studio and then copy it to another location to make any changes. The file usually requires minimal changes; usually just updating the Provider name.
Visual Studio generates an .inf file that contains references to vsd_setup.dll. This component is used for version checking and reports information if the Pocket PC device does not have the correct version of the .NET Compact Framework installed. It is a good idea to keep this in your application but it has been removed from the sample code for simplicity.
A sample file is shown below. You can visit Microsoft Windows CE .NET: Creating an .inf File for more information on .inf files.
[Version] Signature="$Windows NT$" Provider="Sample Company" CESignature="$Windows CE$" [CEStrings] AppName="PocketApp" InstallDir=%CE1%\%AppName% [CEDevice] VersionMin=3.00 VersionMax=4.99 [DefaultInstall] CEShortcuts=Shortcuts CopyFiles=Files.Common [SourceDisksNames] 1=,"Common1",,"C:\Code\Microsoft\Pocket PC Whitepapers\Deployment\Code\CS\PocketApp\obj\Release\" [SourceDisksFiles] PocketApp.exe=1 [DestinationDirs] Files.Common=0,%InstallDir% Shortcuts=0,%CE2%\Start Menu [Files.Common] PocketApp.exe,,,0 [Shortcuts] PocketApp,0,PocketApp.exe,%CE11%
The Cab wizard (cabwiz.exe) generates .cab files that can be installed on different Pocket PC devices. An .inf file is used to describe the application to the wizard and is passed as the first argument on the command line. Other optional arguments are the destination directory, error log file, and CPU types. You can visit Microsoft Windows CE .NET: CAB Wizard Syntax for more information on running the wizard.
The custom installer component automates the deployment process by handling the AfterInstall and AfterUninstall events and running the WinCE Application Manager. The path to the application manager is stored in the registry under the HKLM\software\Microsoft\Windows\CurrentVersion\App Paths\CEAppMgr.exe registry key. The code for the AfterInstall and AfterUninstall events is shown below.
C#
private void Installer_AfterInstall(object sender, System.Configuration.Install.InstallEventArgs e) { // get fullpath to .ini file string arg = Path.Combine( Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Setup.ini"); // run WinCE App Manager to install .cab file on device RunAppManager(arg); } private void Installer_AfterUninstall(object sender, System.Configuration.Install.InstallEventArgs e) { // run app manager in uninstall mode (without any arguments) RunAppManager(null); } private void RunAppManager(string arg) { // get path to the app manager const string RegPath = @"Software\Microsoft\Windows\" + @"CurrentVersion\App Paths\CEAppMgr.exe"; RegistryKey key = Registry.LocalMachine.OpenSubKey(RegPath); string appManager = key.GetValue("") as string; if (appManager != null) { // launch the app Process.Start( string.Format("\"{0}\"", appManager), (arg == null) ? "" : string.Format("\"{0}\"", arg)); } else { // could not locate app manager MessageBox.Show("Could not launch the WinCE Application Manager."); } }
VB.NET
Private Sub Installer_AfterInstall(ByVal sender As Object, _ ByVal e As System.Configuration.Install.InstallEventArgs) _ Handles MyBase.AfterInstall ' get fullpath to .ini file Dim arg As String = Path.Combine(Path.GetDirectoryName( _ System.Reflection.Assembly.GetExecutingAssembly().Location), _ "Setup.ini") ' run WinCE App Manager to install .cab file on device RunAppManager(arg) End Sub Private Sub Installer_AfterUninstall(ByVal sender As Object, _ ByVal e As System.Configuration.Install.InstallEventArgs) _ Handles MyBase.AfterUninstall ' run app manager in uninstall mode (without any arguments) RunAppManager(Nothing) End Sub Private Sub RunAppManager(ByVal arg As String) ' get path to the app manager Const RegPath As String = "Software\Microsoft\Windows\" & _ "CurrentVersion\App Paths\CEAppMgr.exe" Dim key As RegistryKey = Registry.LocalMachine.OpenSubKey(RegPath) Dim appManager As String = CStr(key.GetValue("")) If Not (appManager Is Nothing) Then If arg Is Nothing Then Process.Start(String.Format("""{0}""", appManager)) Else ' launch the app Process.Start( _ String.Format("""{0}""", appManager), _ String.Format("""{0}""", arg)) End If Else ' could not locate app manager MessageBox.Show("Could not find app manager") End If End Sub
The .ini file describes the Pocket PC application and is required when using the WinCE Application Manger to deploy applications to Pocket PC devices. The sample setup.ini file is shown below. You should set the Version, Description and CabFiles properties in your application. You can visit Microsoft Windows CE 3.0: Creating an .ini File for the Application Manager for more information on .ini files.
[CEAppManager] Version = 1.0 Component = App [App] Description = Sample Pocket PC application. CabFiles = PocketApp_PPC.X86.CAB,PocketApp_PPC.ARM.CAB,PocketApp_PPC.ARMV4.CAB, PocketApp_PPC.MIPS.CAB,PocketApp_PPC.SH3.CAB,PocketApp_PPC.WCE420X86.CAB
This is the file that is distributed to users. It contains everything necessary to deploy the Pocket PC application from the desktop to different Pocket PC devices.
Now that you are familiar with all of the pieces involved in the development process, let's see how the build can be automated. The key points are:
The following section discusses the C# and Microsoft Visual Basic® .NET sample solutions in more detail. The C# solution builds all projects (Pocket PC app, custom installer component and .msi file) with one click. Visual Basic.NET requires more steps since Microsoft Visual Studio® is missing these two features:
The VB.NET solution is still automated, just not as much as the C# version.
The C# solution contains three projects: PocketPC App, Custom Installer and Setup. The PocketApp project is a Smart Device application that contains the Pocket PC code. The CustomInstaller project is the customer installer component and the Setup project packages up everything into an .msi file. The C# solution is shown below.
Figure 6. C# solution that contains Pocket PC, installer component and setup projects
Two solutions are required for VB.NET. The first contains the Smart Device project called PocketApp. The second solution generates the .msi file and contains the projects CustomInstaller, Pre-Build and Setup. The CustomInstaller and Setup projects are equivalent to the C# projects and the Pre-Build project is a C++ Makefile project; it does not contain any C++ code and is only used to specify a pre-build event. The VB solutions are shown below.
Figure 7. VB.NET solutions that contain Pocket PC, installer component, pre-build and setup projects
The PocketApp project is a simple Smart Device, "hello world" application; a placeholder for your Pocket PC project. The BuildCab.bat and PocketApp_PPC.inf files are used to build the .cab files and the setup.ini file is used when deploying the application. The app.ico file is the application icon and appears in Programs group on the Pocket PC. Specifying the application icon is shown for the C# and VB.NET versions.
Figure 8. Specfying the application icon in C#
Figure 9. Specifying the application icon in VB.NET
Figure 10. Icon shows up in the Programs group on the Pocket PC
This is the component that runs the WinCE Application Manager to deploy .cab files to the Pocket PC device. The code for the C# and VB.NET versions is shown earlier in this paper.
The Setup project generates an .msi file that contains the processor-specific .cab files, installer component, and setup.ini file. The CustomerInstaller component is added as Install and Uninstall custom actions as shown below.
Figure 11. Adding the Install and Uninstall custom actions
You need to run the BuildCab.bat file to generate the .cab files after the PocketApp project is built. Visual Studio does not allow you to specify post-build events for C# Smart Device projects, so we do the next best thing and define a pre-build event for the CustomInstaller project.
Figure 12. Using a pre-build event to build the .cab files in C#
Visual Studio does not allow any build events for VB.NET projects so a C++ Makefile project is used to define the pre-build event as shown below.
Figure 13. Using a C++ pre-build event for the VB.NET solution
It's important to set the correct build order since the solution contains multiple projects. For C#, the build order is set to PocketApp, CustomInstaller and Setup as shown below.
Figure 14. Specifying the build order for the C# solution
The VB.NET version contains two solutions; the PocketApp solution should be built first, followed by the PocketPCSetup solution. The build order for the setup solution is shown below.
Figure 15. Specifying the build order for the VB.NET solution
Configuration Manager is used to build the Pocket PC project in debug mode and all projects in release mode. That way, you don't go through the entire build process just to debug the Pocket PC application. The C# version is shown below.
This is not necessary for the VB.NET version since it has one solution for the Pocket PC app and another solution to generate the .msi file.
Figure 16. Only build the Pocket PC project in debug mode
Figure 17. Build all projects in release mode
The following are notes on installing and building the sample solutions.