Introduction
We will consider the purposes of the Windows Cabinet files, the specific of software installation on Windows CE devices and the way to execute C++ code during the installation process. Also we will create a sample CAB installation in Visual Studio 2008.
The information provided below is based on the experience of the work with Hewlet-Packard Windows CE thin clients. In spite of the fact that the CAB installation procedure on Windows CE devices from different vendors has many common parts some aspects described in this article may differ on non-HP thin clients.
Table of Contents
Addons Installation Mechanism on Windows CE Thin Clients
Specific of the CAB Installation on Thin Clients
Additional Installation Actions and Setup.dll
Creating CAB Installation in MS Visual Studio
Summary
Bibliography.
Addons Installation Mechanism on Windows CE Thin Clients
To install additional applications on Windows CE based thin clients, it is convenient to use some kind of installer.
Most of the Windows CE distributions support the installations by means of the Windows Cabinet (.cab) files (http://msdn.microsoft.com/en-us/library/bb158712.aspx). Basically such Cabinet file contains the archived application binaries and the instructions on where to unpack archive contents; and also information about the changes that should be performed to the system registry.
During the .cab-installation on the thin client the corresponding record is created in the View or Remove Programs applet menu. Also the .unload script file is generated in the \Windows directory. It will be used during the uninstallation procedure.
Specific of the CAB Installation on Thin Clients
The typical Windows CE thin clients are equipped with the flash memory which is used both as RAM and the hard disk. The thin client file system is divided into the part stored in persistent memory and the part mounted on RAM. The former exists permanently and the latter is erased during each system reboot. This may be a little inconvenient as some important system folders are mounted on RAM. Of course their content is restored on each reboot using the information from persistent memory but if you have placed some important files to one of those folders you’ll have to take some precautions to not to lose them.
The persistent memory items are typically mounted in the \Hard Disk or similarly named folders in the root directory. The rest of items mounted under the root are the RAM items.
So it is preferable that you configure your .cab installation to unpack the binaries to one of the persistent folders inside the \Hard Disk directory. For example, \Hard Disk\Program Files\MyApplication would be a good option.
Then you will have to secure the .unload script file generated upon your installation. It will be created at the end of the installation process in the \Windows folder. This folder is mounted on RAM so its content will be erased on the next reboot and you won’t be able to uninstall your application with the View or Remove Programs applet afterwards.
To avoid this, you can use \Hard Disk\ramroot system folder. Its content is automatically copied to the root folder on each system start. So if you copy your .unload script to \Hard Disk\ramroot\Windows upon the installation, it will be automatically restored in the \Windows folder after each reboot. If some other binaries of your application must be installed to \Windows folder, you must make sure that you have placed their copies to \Hard Disk\ramroot\Windows as well.
Another important topic is your application registry settings.
During the CAB installation the corresponding registry keys are first created in the RAM registry and then copied to the so-called hive-based registry in the persistent memory.
The HP thin clients have the “Reset to Factory Defaults” option. During this operation the file system binaries stay intact but the hive-based registry in the persistent memory is erased and then rebuilt using the default OS image. If your application has stored some configuration data in the registry, you will lose it during this operation. Also you will lose the installation registry record.
To avoid this you can use the \Hard Disk\Defaults folder. When the OS determines, during boot, that the hive-based registry has been deleted, it will look in the \Hard Disk\Defaults folder for any registry data that it should add to the reconstruction.
The Defaults directory simply contains a collection of registry text files (*.reg). So you just have to create the .reg file containing your application registry data and copy it to the \Hard Disk\Defaults folder during the installation.
Additional Installation Actions and Setup.dll
The capabilities of the CAB installer are not very big. It allows you to unpack binaries to the destination folder, write some records to the registry, and create the shortcuts. But you are unable to display message boxes or manipulate the files, which are not included in the CAB-package.
For example, in the section above we have discussed the necessity of the .unload script file copying to the \Hard Disk\ramroot\Windows folder. But this file is not included in the CAB package - it is automatically generated only during installation process. So you won’t be able to copy it anywhere as easily as your application binaries.
You can create Setup.dll library to allow your CAB installer to do more complex tasks. It is the library of the specific format containing the implementation of four export functions to be launched on different installation stages: Install_Init
– at the beginning of the installation, Install_Exit
– at the end of the installation, Uninstall_Init
– at the beginning of the uninstallation, Uninstall_Exit
– at the end of the uninstallation. If the Setup.dll library is present in the CAB-distribution, these functions are called automatically at the corresponding events.
Though this library is included in the CAB file, it is never installed on the system.
The instructions on how to develop the Setup.dll library are given in the corresponding article on MSDN: http://msdn.microsoft.com/en-us/library/aa924308.aspx
Please note that defining such functions as Install_Init()
, Install_Exit()
, etc. exactly in the way described in MSDN article may cause problems with their external invoking. To avoid them use extern "C" (http://msdn.microsoft.com/en-us/library/0603949d%28VS.80%29.aspx ) keyword:
extern "C" BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
return TRUE;
}
extern "C" codeINSTALL_INIT Install_Init(HWND hwndParent, BOOL fFirstCall, BOOL fPreviouslyInstalled, LPCTSTR pszInstallDir)
{
return codeINSTALL_INIT_CONTINUE;
}
extern "C" codeINSTALL_EXIT Install_Exit(HWND hwndParent, LPCTSTR pszInstallDir, WORD cFailedDirs, WORD cFailedFiles,
WORD cFailedRegKeys, WORD cFailedRegVals, WORD cFailedShortcuts)
{
return codeINSTALL_EXIT_DONE;
}
extern "C" codeUNINSTALL_INIT Uninstall_Init(HWND hwndParent, LPCTSTR pszInstallDir)
{
return codeUNINSTALL_INIT_CONTINUE;
}
extern "C" codeUNINSTALL_EXIT Uninstall_Exit(HWND hwndParent)
{
return codeUNINSTALL_EXIT_DONE;
}
Also you will require the .def file (http://msdn.microsoft.com/en-us/library/28d6s79h%28VS.80%29.aspx ) with the following contents:
LIBRARY "Setup"
EXPORTS
Install_Init
Install_Exit
Uninstall_Init
Uninstall_Exit
Creating CAB Installation in MS Visual Studio
Now let’s create the sample CAB installer. It will perform the following:
- Extract the files foobar.exe, foobar.dll and EULA.txt to \Hard Disk\Program Files\Foobar folder;
- Create the Start Menu shortcut for foobar.exe;
- Add the registry key to HKLM\Software\Apps section.
Also we will create Setup.dll library, include it to our CAB installer. We will use this library to show the message box at the end of the installation and copy .unload script to the corresponding system directory in persistent memory.
Here are the steps for Visual Studio 2008.
- Install the Platform SDK for your target device.
- In Visual Studio, go to File > New > Project…
- The New Project dialog will appear. In Project types list select Other Project Types > Setup and Deployment. In Templates list select Smart Device CAB Project. Enter the project name and click OK.
- Open File System tab. You will see that the default item for Program Files folder already exists. Unfortunately, it represents the Program Files folder mounted to RAM and using it would not be the best idea. To use the Program Files folder from the persistent memory you will have to create it manually.
- Right-click File System on Target Machine item. Select Custom Folder. Name it “Hard Disk”.
- Now you should create the Program Files folder inside Hard Disk folder. You can enter the name “Program Files” explicitly or use the corresponding Windows CE string “%CE1%”. Complete list of the Windows CE strings for system folders is here: http://msdn.microsoft.com/en-us/library/ms934880.aspx
- Create the Foobar folder inside the newly created Program Files folder.
- Add foobar.exe, foobar.dll and EULA.txt files to the Foobar folder.
- Now let’s add the shortcut for the Start Menu. On the File System tab, right-click File System on Target Machine item. Select Start Menu Folder.
- Create the shortcut for the foobar.exe in the Start Menu Folder.
- Now let’s add sample registry key for our CAB installation. Open the Registry tab and create the Software key in the HKEY_LOCAL_MACHINE_KEY. Then create the Apps key in the Software key. Then create the Foobar key in the Apps key. Then create FoobarVersion string value in the Foobar key and set it to “1.0”.
- Now we should secure this registry setting from the “Reset to Factory Defaults” action. To achieve this, we will create the registry file Foobar.reg containing the registry information for our application:
[HKEY_LOCAL_MACHINE\Software\Apps\Foobar]
"FoobarVersion"="1.0"
Then we should create \Hard Disk\Defaults folder and put Foobar.reg into it:
- Now we should take the steps to secure the .unload file between system restarts. We couldn’t do it using the default CAB capabilities so we’ll have to create Setup.dll library with the required functionality.
First we should determine the name of the .unload file. The system combines it from the Manufacturer and ProductName properties of the CAB installation.
In the Solution Explorer select the Foobar CAB project and switch to the Properties tab.
In our example the Manufacturer property value is “The Company” and the ProductName is “Foobar”. So the .unload file name will be “The Company Foobar.unload”.
- Add new project to the solution.
- In the project types list, click Visual C++ and then Smart Device. In the template list, select Win32 Smart Device Project. Name it Setup and click OK.
- On the Platform page of the Wizard select the Platform SDK for your target device and click Next.
- On the Project Settings of the Wizard, select DLL application type and click Finish.
- Add ce_setup.h header file to the Setup project. It must contain the declaration for standard CAB installation functions. This header file is attached to the article.
- Open the Setup.cpp file and include ce_setup.h.
- Now it is time to add the definitions of the CAB installation functions. We will copy the .unload file to \Hard Disk\ramroot\Windows folder and display the message box at the end of the installation. The
Install_Exit
function is a good choice for that. Also we will need to manually remove the copy of the .unload file from the \Hard Disk\ramroot\Windows during the uninstallation process. This could be done during the execution of the Uninstall_Exit
function. The implementation of the rest of the installation functions we will leave empty. So the Setup.cpp file content will look as follows:
#include "stdafx.h"
#include "ce_setup.h"
#include <string>
const std::wstring UNLOAD_FILE_NAME = L"The Company Foobar.unload";
const std::wstring ORIGINAL_UNLOAD_FILE_PATH = L"\\Windows\\" + UNLOAD_FILE_NAME;
const std::wstring DESTINATION_UNLOAD_FILE_PATH = L"\\Hard Disk\\Ramroot\\Windows\\" + UNLOAD_FILE_NAME;
const std::wstring INSTALL_COMPLETE_CAPTION = L"Foobar";
const std::wstring INSTALL_COMPLETE_TEXT = L"Foobar application was successfully installed!";
extern "C" BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
return TRUE;
}
extern "C" codeINSTALL_INIT Install_Init(HWND hwndParent, BOOL fFirstCall, BOOL fPreviouslyInstalled, LPCTSTR pszInstallDir)
{
return codeINSTALL_INIT_CONTINUE;
}
extern "C" codeINSTALL_EXIT Install_Exit(HWND hwndParent, LPCTSTR pszInstallDir, WORD cFailedDirs, WORD cFailedFiles,
WORD cFailedRegKeys, WORD cFailedRegVals, WORD cFailedShortcuts)
{
BOOL result = ::CopyFile(ORIGINAL_UNLOAD_FILE_PATH.c_str(), DESTINATION_UNLOAD_FILE_PATH.c_str(), false);
MessageBox(0, INSTALL_COMPLETE_TEXT.c_str(), INSTALL_COMPLETE_CAPTION.c_str(), MB_OK);
return codeINSTALL_EXIT_DONE;
}
extern "C" codeUNINSTALL_INIT Uninstall_Init(HWND hwndParent, LPCTSTR pszInstallDir)
{
return codeUNINSTALL_INIT_CONTINUE;
}
extern "C" codeUNINSTALL_EXIT Uninstall_Exit(HWND hwndParent)
{
::DeleteFile(DESTINATION_UNLOAD_FILE_PATH.c_str());
return codeUNINSTALL_EXIT_DONE;
}
- Also we will need to add the .def file to the Setup project to make our installation functions export.
- The content of the Setup.def file will be:
LIBRARY "Setup"
EXPORTS
Install_Init
Install_Exit
Uninstall_Init
Uninstall_Exit
- There is one more thing left to do. We should connect our CAB project with the Setup.dll. Then the installation export functions will be invoked automatically during the setup process.
In the Solution Explorer, select the Foobar CAB project and switch to the Properties tab. Double click CE Setup DLL property.
- From the Look in drop-down list, select the Foobar folder.
- The Add Output button becomes active. Click it.
- The Add Project Output dialog will appear. Select the Setup project from the Project drop-down list and choose the Primary Output option. From the Configuration drop-down list, select the Setup project configuration for your target device and click OK.
- In the Solution Explorer, right-click the whole Foobar solution and select Build Solution. After the build process finishes, you will get your CAB installer.
Summary
The main purpose of this article was to make clear several non-obvious moments during the implementation of the CAB-installers for Windows CE devices. The author would be happy if this material proves to be useful :-)
Attached CAB_Installer_Sample.zip archive contains the complete sources of the sample installer described in the article.
Bibliography