WinCE 瘦客户端的 CAB 安装





5.00/5 (1投票)
本文介绍了为瘦客户端的 Windows CE 5.0/6.0 应用程序创建 CAB 安装程序的方法。
引言
我们将探讨 Windows Cabinet 文件的用途、Windows CE 设备上软件安装的特殊性以及在安装过程中执行 C++ 代码的方法。此外,我们将在 Visual Studio 2008 中创建一个示例 CAB 安装。
以下信息基于与惠普 Windows CE 瘦客户端的工作经验。尽管来自不同供应商的 Windows CE 设备上的 CAB 安装过程有许多共同之处,但本文中描述的某些方面可能在非惠普瘦客户端上有所不同。
目录
Windows CE 瘦客户端上的附加组件安装机制
瘦客户端上 CAB 安装的特殊性
附加安装操作和 Setup.dll
在 MS Visual Studio 中创建 CAB 安装
摘要
参考书目。
Windows CE 瘦客户端上的附加组件安装机制
要在基于 Windows CE 的瘦客户端上安装附加应用程序,使用某种安装程序会很方便。
大多数 Windows CE 发行版都支持通过 Windows Cabinet (.cab) 文件进行安装(http://msdn.microsoft.com/en-us/library/bb158712.aspx)。基本上,这种 Cabinet 文件包含已归档的应用程序二进制文件和解压缩归档内容的说明;以及有关应执行的系统注册表更改的信息。
在瘦客户端上进行 .cab 安装时,会在“查看或删除程序”小程序菜单中创建相应的记录。此外,会在 \Windows 目录中生成 .unload 脚本文件。它将在卸载过程中使用。
瘦客户端上 CAB 安装的特殊性
典型的 Windows CE 瘦客户端配备有闪存,既用作 RAM 又用作硬盘。瘦客户端文件系统分为存储在永久内存中的部分和安装在 RAM 中的部分。前者永久存在,后者在每次系统重启时都会被擦除。这可能有些不便,因为一些重要的系统文件夹安装在 RAM 上。当然,它们的内容会在每次重启时使用永久内存中的信息进行恢复,但如果您将一些重要文件放在这些文件夹中的一个中,您将不得不采取一些预防措施以避免丢失它们。
永久内存项通常安装在根目录中的 \Hard Disk 或类似名称的文件夹中。安装在根目录下的其余项都是 RAM 项。
因此,最好将 .cab 安装配置为将二进制文件解压到 \Hard Disk 目录中的一个永久文件夹中。例如,\Hard Disk\Program Files\MyApplication 将是一个不错的选择。
然后您必须保护您的安装生成的 .unload 脚本文件。它将在安装过程结束时在 \Windows 文件夹中创建。此文件夹安装在 RAM 上,因此其内容将在下次重启时被擦除,之后您将无法使用“查看或删除程序”小程序卸载您的应用程序。
为避免这种情况,您可以使用 \Hard Disk\ramroot 系统文件夹。其内容会在每次系统启动时自动复制到根文件夹。因此,如果您在安装时将 .unload 脚本复制到 \Hard Disk\ramroot\Windows,它将在每次重启后自动恢复到 \Windows 文件夹中。如果您的应用程序的其他二进制文件必须安装到 \Windows 文件夹中,您必须确保也将其副本放置在 \Hard Disk\ramroot\Windows 中。
另一个重要主题是您的应用程序注册表设置。
在 CAB 安装期间,相应的注册表项首先在 RAM 注册表中创建,然后复制到永久内存中所谓的基于 Hive 的注册表中。
HP 瘦客户端具有“恢复出厂设置”选项。在此操作期间,文件系统二进制文件保持不变,但永久内存中基于 Hive 的注册表会被擦除,然后使用默认操作系统映像重建。如果您的应用程序在注册表中存储了一些配置数据,您将在此操作期间丢失它。您还将丢失安装注册表记录。
为了避免这种情况,您可以使用 \Hard Disk\Defaults 文件夹。当操作系统在引导期间确定基于 Hive 的注册表已被删除时,它将查看 \Hard Disk\Defaults 文件夹中是否有任何应该添加到重建中的注册表数据。
Defaults 目录只包含一组注册表文本文件 (*.reg)。因此,您只需创建包含应用程序注册表数据的 .reg 文件,并在安装过程中将其复制到 \Hard Disk\Defaults 文件夹中。
附加安装操作和 Setup.dll
CAB 安装程序的功能并不多。它允许您将二进制文件解压到目标文件夹,向注册表写入一些记录,并创建快捷方式。但是您无法显示消息框或操作未包含在 CAB 包中的文件。
例如,在上一节中,我们讨论了将 .unload 脚本文件复制到 \Hard Disk\ramroot\Windows 文件夹的必要性。但是这个文件不包含在 CAB 包中——它只在安装过程中自动生成。因此,您无法像复制应用程序二进制文件一样轻松地将其复制到任何地方。
您可以创建 Setup.dll 库,使您的 CAB 安装程序能够执行更复杂的任务。它是一个特定格式的库,包含在不同安装阶段启动的四个导出函数的实现:Install_Init
– 在安装开始时,Install_Exit
– 在安装结束时,Uninstall_Init
– 在卸载开始时,Uninstall_Exit
– 在卸载结束时。如果 CAB 分发中存在 Setup.dll 库,这些函数将在相应的事件时自动调用。
虽然此库包含在 CAB 文件中,但它从未安装到系统上。
有关如何开发 Setup.dll 库的说明可在 MSDN 的相应文章中找到:http://msdn.microsoft.com/en-us/library/aa924308.aspx
请注意,以 MSDN 文章中描述的方式精确定义 Install_Init()
、Install_Exit()
等函数可能会导致其外部调用出现问题。为了避免这些问题,请使用 extern "C" (http://msdn.microsoft.com/en-us/library/0603949d%28VS.80%29.aspx ) 关键字
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; }
您还需要一个内容如下的 .def 文件 (http://msdn.microsoft.com/en-us/library/28d6s79h%28VS.80%29.aspx )
LIBRARY "Setup" EXPORTS Install_Init Install_Exit Uninstall_Init Uninstall_Exit
在 MS Visual Studio 中创建 CAB 安装
现在让我们创建一个示例 CAB 安装程序。它将执行以下操作:
- 将文件 foobar.exe、foobar.dll 和 EULA.txt 解压到 \Hard Disk\Program Files\Foobar 文件夹;
- 为 foobar.exe 创建“开始”菜单快捷方式;
- 将注册表项添加到 HKLM\Software\Apps 部分。
我们还将创建 Setup.dll 库,并将其包含在我们的 CAB 安装程序中。我们将使用此库在安装结束时显示消息框,并将 .unload 脚本复制到永久内存中相应的系统目录。
以下是 Visual Studio 2008 的步骤。
- 安装目标设备的 Platform SDK。
- 在 Visual Studio 中,转到“文件”>“新建”>“项目…”
- 将出现“新建项目”对话框。在“项目类型”列表中选择“其他项目类型”>“安装和部署”。在“模板”列表中选择“智能设备 CAB 项目”。输入项目名称并单击“确定”。
- 打开“文件系统”选项卡。您将看到“程序文件”文件夹的默认项目已经存在。不幸的是,它表示安装到 RAM 的“程序文件”文件夹,使用它不是最好的主意。要使用永久内存中的“程序文件”文件夹,您必须手动创建它。
- 右键单击“目标计算机上的文件系统”项。选择“自定义文件夹”。将其命名为“Hard Disk”。
- 现在您应该在“Hard Disk”文件夹中创建“Program Files”文件夹。您可以明确输入名称“Program Files”或使用相应的 Windows CE 字符串“%CE1%”。系统文件夹的 Windows CE 字符串的完整列表在这里:http://msdn.microsoft.com/en-us/library/ms934880.aspx
- 在新创建的 Program Files 文件夹中创建 Foobar 文件夹。
- 将 foobar.exe、foobar.dll 和 EULA.txt 文件添加到 Foobar 文件夹。
- 现在让我们为“开始”菜单添加快捷方式。在“文件系统”选项卡上,右键单击“目标计算机上的文件系统”项。选择“开始菜单”文件夹。
- 在“开始菜单”文件夹中为 foobar.exe 创建快捷方式。
- 现在让我们为 CAB 安装添加示例注册表项。打开“注册表”选项卡并在 HKEY_LOCAL_MACHINE_KEY 中创建 Software 项。然后在 Software 项中创建 Apps 项。然后在 Apps 项中创建 Foobar 项。然后在 Foobar 项中创建 FoobarVersion 字符串值并将其设置为“1.0”。
- 现在我们应该保护此注册表设置免受“恢复出厂设置”操作的影响。为此,我们将创建一个包含应用程序注册表信息的注册表文件 Foobar.reg
[HKEY_LOCAL_MACHINE\Software\Apps\Foobar] "FoobarVersion"="1.0"
然后我们应该创建 \Hard Disk\Defaults 文件夹并将 Foobar.reg 放入其中
- 现在我们应该采取措施确保 .unload 文件在系统重启之间是安全的。我们无法使用默认的 CAB 功能完成此操作,因此我们必须创建一个具有所需功能的 Setup.dll 库。
首先,我们应该确定 .unload 文件的名称。系统会根据 CAB 安装的制造商和产品名称属性将其组合起来。
在“解决方案资源管理器”中选择 Foobar CAB 项目并切换到“属性”选项卡。
在我们的示例中,Manufacturer 属性值为“The Company”,ProductName 为“Foobar”。因此,.unload 文件名将是“The Company Foobar.unload”。
- 向解决方案添加新项目。
- 在项目类型列表中,单击“Visual C++”,然后单击“智能设备”。在模板列表中,选择“Win32 智能设备项目”。将其命名为 Setup 并单击“确定”。
- 在向导的“平台”页面上,选择目标设备的 Platform SDK,然后单击“下一步”。
- 在向导的“项目设置”中,选择“DLL”应用程序类型,然后单击“完成”。
- 将 ce_setup.h 头文件添加到 Setup 项目。它必须包含标准 CAB 安装函数的声明。此头文件已附加到文章中。
- 打开 Setup.cpp 文件并包含 ce_setup.h。
- 现在是时候添加 CAB 安装函数的定义了。我们将在安装结束时将 .unload 文件复制到 \Hard Disk\ramroot\Windows 文件夹并显示消息框。
Install_Exit
函数是一个不错的选择。此外,我们还需要在卸载过程中手动从 \Hard Disk\ramroot\Windows 中删除 .unload 文件的副本。这可以在执行Uninstall_Exit
函数时完成。我们将保留其余安装函数的实现为空。因此,Setup.cpp 文件的内容将如下所示
#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; }
- 我们还需要将 .def 文件添加到 Setup 项目中,以导出我们的安装函数。
- Setup.def 文件的内容将是
LIBRARY "Setup" EXPORTS Install_Init Install_Exit Uninstall_Init Uninstall_Exit
- 还有一件事要做。我们应该将我们的 CAB 项目与 Setup.dll 连接起来。然后,安装导出函数将在安装过程中自动调用。
在“解决方案资源管理器”中,选择 Foobar CAB 项目并切换到“属性”选项卡。双击 CE Setup DLL 属性。
- 从“查找位置”下拉列表中,选择 Foobar 文件夹。
- “添加输出”按钮变为活动状态。单击它。
- “添加项目输出”对话框将出现。从“项目”下拉列表中选择 Setup 项目,然后选择“主要输出”选项。从“配置”下拉列表中,选择目标设备的 Setup 项目配置,然后单击“确定”。
- 在“解决方案资源管理器”中,右键单击整个 Foobar 解决方案,然后选择“生成解决方案”。生成过程完成后,您将获得 CAB 安装程序。
总结
本文的主要目的是阐明在为 Windows CE 设备实现 CAB 安装程序时一些不明显的方面。如果这份材料能有所帮助,作者将感到高兴 :-)
附加的 CAB_Installer_Sample.zip 存档包含文章中描述的示例安装程序的完整源代码。
参考书目
- http://msdn.microsoft.com/en-us/library/bb158712.aspx - 用于交付 Windows Mobile 应用程序的 CAB 文件
- http://msdn.microsoft.com/en-us/library/zcebx8f8%28VS.90%29.aspx - 演练:打包智能设备解决方案以进行部署
- http://msdn.microsoft.com/en-us/library/aa924308.aspx - 用于安装的可选 Setup.dll 文件
- http://hpeb.lithium.com/t5/Workstations-Thin-Clients/how-to-build-an-addon-on-T5520/m-p/773517 - 如何为 HP 基于 CE 的瘦客户端安装自定义软件