65.9K
CodeProject 正在变化。 阅读更多。
Home

自动将多个 CAB 文件安装到 Windows Mobile/Pocket PC 设备

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.71/5 (7投票s)

2010年3月13日

CPOL

9分钟阅读

viewsIcon

61632

downloadIcon

2650

一个使用多线程和 ActiveSync 自动将多个 CAB 文件安装到 Windows Mobile 或 Pocket PC 设备的解决方案

引言

本文旨在描述一种解决方案,该解决方案利用多线程和 ActiveSync 来自动化将多个 CAB 文件安装到 Windows Mobile 或 Pocket PC 设备的过程。

包含的示例安装项目是一个标准的 Windows MSI 安装文件,运行该文件将把两个 CAB 文件安装到 Windows Mobile 或 Pocket PC 设备。

项目包含的自定义操作负责将 CAB 文件安装到设备,它使用 ActiveSync 一次一个地连续安装每个 CAB 文件。每个安装都在一个单独的线程中运行,主进程在继续下一个安装之前会等待每个安装完成。

出于示例目的,我包含了两个 CAB 文件,但自定义操作可以轻松扩展以安装您想要的任意数量的 CAB 文件。包含的 CAB 文件将安装 .NET Compact Framework 3.5 和 SQL Mobile 2.0。

描述

自定义操作通过重写和扩展 `Installer` 类的默认功能来工作。安装程序类的被重写 `Commit` 方法首先调用基类的 `Commit` 方法,然后继续实现自定义功能。

大致而言,自定义功能的工作原理如下:

  1. 所有 CAB 文件都由安装程序复制到初始安装目标目录。MSI 会自动执行此操作。
  2. 自定义操作然后初始化一个 `InstallParams` 对象,该对象接受一个 `AutoResetEvent` 对象(用于在线程终止时发出信号)和一个标识要安装的 CAB 的初始化(*.ini*)文件的字符串。
  3. `RunInstallerTask` 方法和 `InstallParams` 对象用于通过调用 `ThreadPool.QueueUserWorkItem` 来启动一个新线程。
  4. 新线程启动一个进程,即执行一个程序,在本例中是 ActiveSync。如果安装了 ActiveSync,ActiveSync 的默认安装目录将从注册表项中检索:HKEY_LOCAL_MACHINE\Software\microsoft\windows\currentversion\app paths\ceappmgr.exe
  5. 在 ActiveSync 执行和安装目标 CAB 的同时,新(正在执行)的线程会等待,每隔 1000 毫秒间歇性地检查 `Process` 类的 `Process.HasExited` 属性。当进程退出时,它通过调用 `AutoResetEvent` 对象的 `Set()` 方法来向 `AutoResetEvent` 发出信号。这会向调用线程发出信号,该线程一直处于高效等待状态(通过调用 `AutoResetEvents` 的 `WaitOne` 方法),以继续执行。
  6. 从步骤 II 开始的过程会为将要安装的任何后续 CAB 文件重复执行。

实现

InstallParams 类

`InstallParams` 类很容易理解。如前所述,它只包含一个 `AutoResetEvent` 对象和一个包含 CAB 文件安装初始化文件(*.ini*)的字符串。`InstallParams` 对象作为第二个参数传递给 `ThreadPool.QueueUserWorkItem`。

此类作为嵌套的公共类实现,是 `CABFileInstaller` 类的一部分。

CABFileInstaller 类

此类派生自 `Installer` 类(声明为 partial,因此是标准库基类 `Installer` 类的派生扩展)。唯一重写 `Installer` 类的方法是 Commit 方法,该方法在实现任何自定义功能之前调用基类的 `Commit` 方法。

此类有一个私有的字符串成员(string appPath),用于存储 ActiveSync 可执行文件的路径。

此派生类还有一个名为 `RunInstallerTask` 的附加私有方法,该方法启动 ActiveSync 并基于 *.ini* 文件(下文所述)中的信息安装 CAB 文件。此方法依赖于作为其上下文一部分传递给安装过程的信息,以确定目标目录的路径。

`RunInstallerTask` 方法中的行 strIniFilePath = "\"" + Context.Parameters["targetdir"]... 从当前上下文中确定目标安装目录。为了实现这一点,必须将自定义操作的 `CustomActionData` 属性设置为 /targetdir="[TARGETDIR]\",如下面的演练中所述。

初始化文件(.ini)

对于要安装的每个 CAB 文件,必须创建一个格式化的 *.ini* 文件并将其安装到 MSI 目标目录。MSI 会自动将文件传输到安装文件夹,但您必须为每个 CAB 创建 ini 文件并将其添加到安装项目中的 ApplicationFolder 包含的文件中。

有关 *.ini* 文件内容及其格式的详细信息,请参阅 MSDN 上的此 URL:http://msdn.microsoft.com/en-us/library/bb158614.aspx

对于一个简单的 .ini 文件示例,用于安装 .NET Compact Framework CAB 文件(包含示例中的 NETCFv35.ini)的 .ini 文件如下所示:

[CEAppManager]
Version      = 1.0
Component    = NETCFv35.ppc.armv4
[NETCFv35.ppc.armv4]
Description  = RMS Stock Count Client
CabFiles     = NETCFv35.ppc.armv4.cab

前两行永远不变,即 `[CEAppManager]`,版本必须始终为 1.0。

`Component` 值必须与下一节的开头匹配,而最后一个(`CabFiles`)值应与正在安装的 CAB 文件的确切名称匹配。可以包括多个 CAB 文件在最后一行,用逗号分隔,以支持不同的体系结构。在本例中,包含的 .NET Compact Framework CAB 文件适用于 ARM 处理器。

项目设置 - 演练

我使用了 Visual Studio 2008,但这应该适用于 VS2005。

创建自定义操作

  1. 在 **文件** 菜单上,单击 **新建项目**。
  2. 在 **新建项目** 对话框中,在 **项目类型** 窗格中选择 **Visual C# 项目**,然后单击 **模板** 窗格中的 **类库**。在 **名称** 框中,键入 CABInstallCustomAction。

    项目已添加到 **解决方案资源管理器**。

  3. 在 **项目** 菜单上,单击 **添加类**,然后在 **添加新项** 对话框中,选择 **安装程序类**。键入名称为 CABFileInstaller.cs。单击 **添加**。
  4. 通过单击设计图面上的 **单击此处切换到代码视图**(或右键单击设计图面并单击 **查看代码**)切换到代码视图。
  5. 在代码编辑器中,将以下代码添加到 CABFileInstaller.cs 的类声明之后(也可以参阅本文附带的示例解决方案中的同一文件):

    声明 `InstallParams` 类

    public class InstallParams
    {
        private AutoResetEvent reset;
        private string strIniFile;
    
        public InstallParams(AutoResetEvent ev, string ini_file)
        {
            if (ev == null)
                throw new Exception("Null reset event");
            reset = ev;
            strIniFile = ini_file;
        }
    
        public AutoResetEvent Reset
        {
            get
            {
                return reset;
            }
        }
    
        public string IniFile
        {
            get
            {
                return strIniFile;
            }
        }
    }

    声明私有字符串 appPath

    private string appPath = null;

    创建 `RunInstallTask` 方法

    private void RunInstallerTask(Object iparam)
    {
        int time = 0;
        InstallParams iparams = iparam as InstallParams;
        AutoResetEvent are = (AutoResetEvent)iparams.Reset;
        // Get the target directory where the .ini file is installed.
        // This is sent from the Setup application
        string strIniFilePath = "\"" + Context.Parameters["targetdir"] + 
                                iparams.IniFile + "\"";
        // Now launch the Application Manager - ActiveSync
        System.Diagnostics.Process process = new System.Diagnostics.Process();
        process.StartInfo.FileName = appPath;
        process.StartInfo.Arguments = strIniFilePath;
        process.Start();
        while (!process.HasExited)
        {
            time = 1000;
            Thread.Sleep(time);
        }                
        are.Set();
    }

    创建重写的 `Commit` 方法

    public override void Commit(System.Collections.IDictionary savedState)
    {
        // Call the Commit method of the base class
        base.Commit(savedState);
    
        AutoResetEvent ev;
        InstallParams ip;
        Microsoft.Win32.RegistryKey key = null;
    
        // Open the registry key containing the path to the Application Manager
        key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(
               "Software\\microsoft\\windows\\currentversion\\app paths\\ceappmgr.exe");
    
        // If the key is not null, then ActiveSync
        // is installed on the user's desktop computer
        if (key != null)
        {
            // Get the path to the Application Manager from the registry value
            appPath = key.GetValue(null).ToString();
    
            if (appPath != null)
            {
                //.Net 3.5
                ev = new AutoResetEvent(false);
                ip = new InstallParams(ev, "NETCFv35.ini");
                ThreadPool.QueueUserWorkItem(new WaitCallback(RunInstallerTask), ip);
                ev.WaitOne();
                //SQL
                ev = new AutoResetEvent(false);
                ip = new InstallParams(ev, "sql.ini");
                ThreadPool.QueueUserWorkItem(new WaitCallback(RunInstallerTask), ip);
                ev.WaitOne();                    
            }
        }
        else
        {
            // No Active Sync - throw an error message
            throw new Exception("ActiveSync Not Installed");
        }
    }
  6. 在 **解决方案资源管理器** 中,右键单击 Class1.cs,然后单击 **删除**(因为它是不必要的)。

添加部署项目

  1. 在 **文件** 菜单上,指向 **添加**,然后单击 **新建项目**。
  2. 在 **添加新项目** 对话框的 **项目类型** 窗格中,展开 **其他项目类型** 节点,然后选择 **设置和部署项目**。在 **模板** 窗格中,单击 **设置项目**。在 **名称** 框中,键入 **MultipleCABFilesSetup**。

    项目已添加到 **解决方案资源管理器**,并且 **文件系统编辑器** 已显示。将 CAB 文件和相应的 *.ini* 文件复制到项目文件夹。

  3. 在 **文件系统编辑器** 中,在左侧窗格中选择 **应用程序文件夹**。在 **操作** 菜单上,指向 **添加**,然后单击 **文件**。以这种方式将所有 CAB 文件和相应的 *.ini* 文件添加到应用程序文件夹。
  4. 在 **文件系统编辑器** 中,在左侧窗格中选择 **应用程序文件夹**。在 **操作** 菜单上,指向 **添加**,然后单击 **项目输出**。
  5. 在 **添加项目输出组** 对话框中,将在 **项目** 列表中显示 **CABInstallCustomAction**。选择 **主要输出**。

    **CABINstallCustomAction 的主要输出(活动)** 出现在 **应用程序文件夹** 中。

添加自定义操作

  1. 在 **解决方案资源管理器** 中选择 **MultipleCABFilesSetup** 项目。在 **视图** 菜单上,指向 **编辑器**,然后单击 **自定义操作**。

    **自定义操作编辑器** 将显示。

  2. 在 **自定义操作编辑器** 中,选择 **安装** 节点。在 **操作** 菜单上,单击 **添加自定义操作**。

  3. 在 **在项目中选择项** 对话框中,双击 **应用程序文件夹**。选择 **CABInstallCustomAction 的主要输出**。

    **CABInstallCustomCation 的主要输出** 出现在 **自定义操作编辑器** 的 **安装** 节点下。

    在 **属性** 窗口中,将以下行添加到 **CustomActionData** 属性:/targetdir="[TARGETDIR]\"。此数据将传递给自定义操作,以便在目标安装目录中查找 ini 和 CAB 文件。请参阅自定义操作代码。

  4. 在 **属性** 窗口中,确保 **InstallerClass** 属性设置为 **True**(这是默认设置)。
  5. 在 **自定义操作编辑器** 中,选择 **提交** 节点。在 **操作** 菜单上,单击 **添加自定义操作**。
  6. 在 **在项目中选择项** 对话框中,双击 **应用程序文件夹**。选择 **CABInstallCustomAction 的主要输出**。

    **CABInstallCustomCation 的主要输出** 出现在 **自定义操作编辑器** 的 **提交** 节点下。

    在 **属性** 窗口中,将以下行添加到 **CustomActionData** 属性:/targetdir="[TARGETDIR]\"。此数据将传递给自定义操作,以便在目标安装目录中查找 ini 和 CAB 文件。请参阅自定义操作代码。

  7. 在 **属性** 窗口中,确保 **InstallerClass** 属性设置为 **True**(这是默认设置)。

  8. 在 **生成** 菜单上,单击 **生成自定义操作安装程序**。

在开发计算机上安装

  • 确保目标设备已连接,并且已使用 ActiveSync 设置了伙伴关系。然后,在 **解决方案资源管理器** 中选择 **MultipleCABFilesSetup** 项目。在 **项目** 菜单上,单击 **安装**。

这将运行安装程序并在您的开发计算机上安装 **MultipleCABFilesSetup**。安装结束时,您应该会看到 ActiveSync 启动并提示您安装 .NET Compact Framework,然后是 SQL Client。

您必须在计算机上拥有安装权限才能运行安装程序。

部署到另一台计算机

  1. 在 **Windows 资源管理器** 中,导航到您的项目目录并找到安装程序。默认路径将是 \Documents and Settings\<yourloginname>\My Documents\Visual Studio\Projects\MultipleCABFilesSetup\ MultipleCABFilesSetup \<project configuration>\ MultipleCABFilesSetup.msi。默认的 project configuration 是 **Debug**。
  2. 将自定义操作 Installer.msiSetup.exe 以及该目录中的所有其他文件和子目录复制到另一台计算机。
    要在一台未联网的计算机上安装,请将文件复制到 CD-ROM 等传统媒体。
  3. 在目标计算机上,确保已安装 ActiveSync,目标设备已连接,并且已使用 ActiveSync 设置了伙伴关系,然后双击 Setup.exe 运行安装程序。

    安装结束时,ActiveSync 应该会启动,并提示您安装设置项目中包含的两个 CAB 文件。

    您必须在计算机上拥有安装权限才能运行安装程序。

卸载应用程序

  1. 在 **控制面板** 中,双击 **添加或删除程序**。
  2. 在 **添加或删除程序** 对话框中,选择 **MultipleCABFileSetup** 并单击 **删除**。
    要从您的开发计算机卸载,请在 **解决方案资源管理器** 中打开并选择 **MultipleCABFileSetup** 项目,然后从 **项目** 菜单中单击 **卸载**。
© . All rights reserved.