发布新日志

  • .Net 中的序列化与反序列化

    2008-12-06 00:07:07

    一、概述
       
    当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为对象。
        把对象转换为字节序列的过程称为
    对象的序列化。
        把字节序列恢复为对象的过程称为对象的反序列化。

        二、对象的序列化主要有两种用途:
      
      1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
       
    我们经常需要将对象的字段值保存到磁盘中,并在以后检索此数据。尽管不使用序列化也能完成这项工作,但这种方法通常很繁琐而且容易出错,并且在需要跟踪对象的层次结构时,会变得越来越复杂。可以想象一下编写包含大量对象的大型业务应用程序的情形,程序员不得不为每一个对象编写代码,以便将字段和属性保存至磁盘以及从磁 盘还原这些字段和属性。序列化提供了轻松实现这个目标的快捷方法。公共语言运行时 (CLR) 管理对象在内存中的分布,.NET 框架则通过使用反射提供自动的序列化机制。对象序列化后,类的名称、程序集以及类实例的所有数据成员均被写入存储媒体中。对象通常用成员变量来存储对其他实例的引用。类序列化后,序列化引擎将跟踪所有已序列化的引用对象,以确保同一对象不被序列化多次。.NET 框架所提供的序列化体系结构可以自动正确处理对象图表和循环引用。对对象图表的唯一要求是,由正在进行序列化的对象所引用的所有对象都必须标记为 Serializable(请参阅基 本序列化)。否则,当序列化程序试图序列化未标记的对象时将会出现异常。当反序列化已序列化的类时,将重新创建该类,并自动还原所有数据成员的值。
     
      2) 在网络上传送对象的字节序列。
       
    对象仅在创建对象的应用程序域中有效。除非对象是从MarshalByRefObject派生得到或标记为 Serializable,否则,任何将对象作为参数传递或将其作为结果返回的尝试都将失败。如果对象标记为 Serializable,则该对象将被自动序列化,并从一个应用程序域传输至另一个应用程序域,然后进行反序列化,从而在第二个应用程序域中产生出该对象的一个精确副本。此过程通常称为按值封送。如果对象是从MarshalByRefObject派生得到,则从一个应用程序域传递至另一个应用程序域的是对象引用,而不是对象本身。也可以将从MarshalByRefObject派生得到的对象标记为Serializable。远程使用此对象时,负责进行序列化并已预先配置为SurrogateSelector的格式化程序将控制序列化过程,并用一个代理替换所有从MarshalByRefObject派生得到的对象。如果没有预先配置为SurrogateSelector,序列化体系结构将遵从下面的标准序列化规则.

        三、.NET提供了三种序列化方式
        [1]、XML Serializer
        [2]、SOAP Serializer
        [3]、BinarySerializer

       
     四、基本序列化
       
    要使一个类可序列化,最简单的方法是使用 Serializable 属性对它进行标记,如下所示:
       
     [Serializable] 
        public class MyObject 
        { 
            public int n1 = 0; 
            public int n2 = 0; 
            public String str = null; 
        } 
      
     [BinarySerializer]
        将此类的一个实例序列化为一个文件:  

    MyObject obj = new MyObject(); 
    obj.n1 = 
    1
    obj.n2 = 
    24
    obj.str = 
    "一些字符串"
    IFormatter formatter = 
    new BinaryFormatter(); 
    Stream stream = 
    new FileStream("MyFile.bin", FileMode.Create, 
    FileAccess.Write, FileShare.None); 
    formatter.Serialize(stream, obj); 
    stream.Close(); 

        反序列化:

    IFormatter formatter = new BinaryFormatter(); 
    Stream stream = 
    new FileStream("MyFile.bin", FileMode.Open, 
    FileAccess.Read, FileShare.Read); 
    MyObject obj = (MyObject) formatter.Deserialize(fromStream); 
    stream.Close(); 

      [XMLSerializer]
        将此类的实例序列化成一个Xml文件.

    XmlSerializer ser = new XmlSerializer(obj.GetType());
    ser.Serialize(
    new FileStream(@"users.xml", FileMode.Create), obj);

        反序列化:

    XmlSerializer serializer = new XmlSerializer(Type.GetType("MyObject"));
    MyObject my=(MyObject)serializer.Deserialize(new FileStream(@
    "users.xml",FileMode.Open));

        说明:使用二进制格式化程序进行序列化。您只需创建一个要使用的流和格式化程序的实例,然后调用格式化程序的 Serialize 方法。流和要序列化的对象实例作为参数提供给此调用。类中的所有成员变量(甚至标记为 private 的变量)都将被序列化,但这一点在本例中未明确体现出来。在这一点上,二进制序列化不同于只序列化公共字段的 XML 序列化程序。将对象还原到它以前的状态也非常容易。首先,创建格式化程序和流以进行读取,然后让格式化程序对对象进行反序列化。    
        [SOAP Serializer]
        如果要求具有可移植性,请使用 SoapFormatter。所要做的更改只是将以上代码中的BinaryFormatter换 SoapFormatter,而 Serialize 和 Deserialize 调用不变。

  • 如何使用 Windows Installer XML 工具集

    2008-12-03 23:18:15

    From:http://msdn.microsoft.com/zh-cn/beginner/bb308771.aspx

    ------------------------------------------------------

    如何使用 Windows Installer XML 工具集
    创建应用程序安装程序


    在软件应用程序方面投入大量精力后,接下来还要花费大量时间来创建一个安装程序,才能与世界共享您的成果。创建可靠、功能强大且便于维护的安装程序包不仅令人生畏,而且相当耗时。因此,此项工作往往需要雇用许多软件开发人员来提供专业指导。幸运的是,非专业人员也拥有很多选择,不仅可以不费吹灰之力地创建简单的安装程序包,而且仍可充分利用 Microsoft Windows 提供的功能强大的安装服务。在本文中,我们将介绍 Windows Installer XML (WiX) 工具集,并尝试将其与其他可用安装程序技术配合使用。

    目录



    为工作选择合适的技术

    通常,可采用多种不同的安装方法在用户的计算机上安装软件。第一种方法只需将所需文件复制到计算机上,但这可能无法构成一个真正的安装程序。这种文件复制方法可以通过网络、CD 甚至是 Web 来执行。如果您拥有一个可以独立运行且不需要任何其他设置的应用程序,则可以使用这种方法 — 最简单的解决方案可能就是最佳的解决方法。

    另一种方法是使用 Microsoft 的 ClickOnce 技术,用户可以通过速成版中的发布向导访问该技术。ClickOnce 是用于托管应用程序的最佳选择,几乎无需自定义安装过程即可完成安装。但是,如果安装时需要执行任务(如创建虚拟 Web 目录、创建新用户帐户或添加注册表项),则需要考虑其他安装方法。

    您可以创建自己的自定义安装程序或为用户提供脚本和说明,但这种方法可能会由于种种原因导致其无法执行。创建自己的功能强大的安装程序非常困难并耗时,而且还会对那些已习惯使用更常见产品的用户造成困扰。从可用性和可维护性两方面来看,提供分布说明或脚本也不够理想。

    当前,Microsoft Windows Installer 技术的使用相当普遍。大多数 Windows 用户已非常熟悉通用界面,用户可在该界面上选择安装位置、选择功能、修复和卸载等。

    屏幕快照 1
    屏幕快照 1 — 安装过程中的通用用户界面屏幕

    Windows Installer 与操作系统紧密集成,因此可确保开发人员使用的通用平台能够在客户的计算机上使用。甚至某些最常用的第三方安装程序创建软件(如 InstallShield 和 Wise)在内部也使用 Windows Installer 技术。尽管许多简化 Windows Installer 使用的第三方工具都收取一定的费用,但有些社区项目成果仍值得看一下。在本文中,我们将介绍这样一个社区项目,名为 Windows Installer XML 工具集(简称 WiX)。

    Windows Installer 简介

    让我们简单介绍一下 Windows Installer,以便更好地了解用来构建 WiX 的平台。Windows Installer 随 Microsoft Windows 的各种版本一起分发,通常作为一种服务来实现高可用性。使用 MSI 扩展的安装文件包含 Windows Installer 安装软件应用程序必需的所有数据文件和结构。对于 Windows Installer,我们主要负责告诉安装程序服务需要安装“什么”,而不只是“如何安装”。

    使用 Windows Installer 的好处包括可以按需安装、失败时回滚、自我修复、修补和卸载等。有关 Windows Installer 的详细信息,请参阅本文最后的参考资料和资源部分。现在,我们来看一下 WiX 工具集能为我们提供哪些服务。预先掌握一些 XML 知识!

    WiX 工具集背景

    实际上,WiX 起初作为 Microsoft 的内部工具使用,至今仍在产品团队中广泛使用。Rob Mensching 的博客文章(发布于 2004 年 4 月 5 日)中将 WiX 工具集的发布称为一个开放源项目,而 Microsoft Office、SQL Server、BizTalk、Virtual PC 和 Instant Messenger 都属于使用 WiX 工具集进行打包的产品。这证明了非常重要的一点 — WiX 可帮助您完成安装要求所需的任何操作!

    WiX 工具集提供了可描述 Windows Installer 数据库文件(我们先前讨论的 MSI 文件)的架构,同时还提供了大量用于编译 WiX 源文件并将其链接到最终工作数据库的工具。从更高层次来看,确实也没有其他更重要的要求了。对于 WiX 和 Windows Installer 数据库,您需要了解大量相关详细信息,但对这些工具或提供的其他资源有一些基本了解后,则完全能够满足应用程序安装要求并将其转换为功能完备的安装程序。

    下载和安装 WiX 工具集

    目前,官方 WiX 项目由 SourceForge 托管,网址为 http://wix.sourceforge.net/。在此,您可以找到最新的新闻、文档和更新。出于本文的目的,请下载撰写本文时作为当前稳定版本列出的版本 2.0 二进制程序包。浏览 WiX 下载页面的版本 2.0 分支时,您会发现还提供了另外两个程序包,其中一个包含源代码,另一个包含名为 Votive 的项目,该项目可为 Visual Studio Standard 或更高版本增添集成的 WiX 支持功能。您只需下载二进制程序包,即可以使用 WiX 工具集。

    将 WiX 2.0 二进制程序包下载到开发系统,然后将二进制程序包的内容解压缩到所选位置。WiX 工具集的主要文件夹包括命令行工具,用来生成、编译 WiX 代码并将其链接到功能完备的 MSI 文件。此外,文档和示例均可从它们各自相应的目录中获得。WiX.chm 帮助文件包含所有可用的文档,是使用 WiX 工具集时可保持打开状态的重要参考工具。

    WiX 简介

    所有 WiX 源文件均以打开的根元素 < Wix/ > 开头,后面必须有一个 < Product/ > 或一个 < Module/ > 子元素,然后可有多个可选 < Fragment/ > 元素或根本不使用此元素。使用 < Product/ > 元素将生成一个 .msi(Windows Installer 数据库文件)。您还可以通过 < Module/ > 元素创建一个使用 .msm 扩展名的合并模块。合并模块是独立的程序包,可以合并到 .msi 产品中。最后,通过 < Fragment/ > 元素,您可以定义可从其他 WiX 代码中引用的 WiX 片段。安装规模扩大后,创建片段的功能就派上用场了。

    请看下面与 WiX 相关的结构都必须使用的代码:

    < ?xml version='1.0'? >
    < Wix xmlns='http://schemas.microsoft.com/wix/2003/01/wi' >
    < /Wix >

    创建 WiX 源文件框架后,安装程序的创建过程才真正开始。安装程序的典型任务包括部署文件、创建目录结构、向“添加/删除程序”注册、执行自定义操作以及添加用户帐户、SQL 数据库和 Web 应用程序。从 WiX 帮助文件的 WiX 架构中查看可用元素(位于 WiX 帮助 | 编写 | Wix 架构节点下)。您可以看到,共有 230 多个可用元素,因此创建安装程序可能有些复杂。不过,创建安装程序通常只需使用这些元素中的一小部分。

    以下 WiX 代码(可从 WiX 二进制程序包的“examples\first”目录中直接获取)显示了如何创建应用程序,该应用程序将在“Program Files”中创建一个目录、复制文本文件并向“添加/删除程序”注册。

    < Wix xmlns='http://schemas.microsoft.com/wix/2003/01/wi' >
      < Product Id='12345678-1234-1234-1234-123456789012' Name='Test Package'
        Language='1033' Version='1.0.0.0' Manufacturer='Microsoft Corporation' >
        < Package Id='12345678-1234-1234-1234-123456789012'
          Descrīption='My first Windows Installer package'
          Comments='This is my first attempt at creating a Windows Installer database'
          InstallerVersion='200' Compressed='yes' / >

        < Media Id='1' Cabinet='product.cab' EmbedCab='yes' / >

        < Directory Id='TARGETDIR' Name='SourceDir' >
          < Directory Id='ProgramFilesFolder' Name='PFiles' >
            < Directory Id='MyDir' Name='TestProg' LongName='Test Program' >
              < Component Id='MyComponent' Guid='12345678-1234-1234-1234-123456789012' >
                < File Id='readme' Name='readme.txt' DiskId='1' src='readme.txt' / >
              < /Component >
            < /Directory >
          < /Directory >
        < /Directory >

        < Feature Id='MyFeature' Title='My 1st Feature' Level='1' >
          < ComponentRef Id='MyComponent' / >
        < /Feature>
      < /Product >
    < /Wix >

    关于上述 WiX 示例,有必要说明一下其中显示的某些详细信息。您可以想到,< Wix\ > 元素仅包含一个子元素(< Product\ > 元素)。在 WiX 帮助文件的 WiX 架构部分中查看“Product 元素”页。如果向下滚动到“属性”部分,您可以看到为 Product 元素定义的属性,其中包括必需的属性。因此,可以证明 WiX 示例代码确实提供了 Product 元素需要的所有属性。

    表 1 — Product 元素属性(部分列表)

    名称

    类型

    说明

    必需

    Id

    Autogenuuid

    产品的产品代码 GUID。

    语言

    LocalizableInteger

    产品的十进制语言 ID (LCID)。

    制造商

    字符串

    产品制造商。

    名称

    字符串

    产品的描述性名称。

    版本

    字符串

    产品的版本字符串。

    < Package\ > 元素是 Product 元素和 Module 元素的必需子元素。该包介绍了作为部分 .msi 摘要流提供的属性,在资源管理器中将鼠标停留在 .msi 上方时就会看到这些属性。以下屏幕快照中显示了 Descrīption 和 Comments 属性。

    查看 WiX 帮助文件文档中 Package 元素的其他可用属性。请注意,我们可以指定安装程序版本、文件压缩,甚至安装权限(如果面向 Windows Vista)。

    表 2 — Package 元素属性(部分列表)

    名称

    类型

    说明

    必需

    Id

    Autogenuuid

    SKU 的程序包代码 GUID。

    AdminImage

    YesNoType

    如果源是管理映像,则设置为“是”。

     

    注释

    字符串

    可选注释(用于浏览)。

     

    压缩

    YesNoType

    如果设置为“是”,则源中可包含压缩文件。

     

    说明

    字符串

    产品的完整名称或说明。

     

    InstallerVersion

    整数

    最低安装程序版本(最大数*100 + 最小数)。

     

    InstallPrivileges

    枚举

    通过此属性指定在 Windows Vista 或更高版本上安装此程序包所需的权限。此属性的值应为下列值之一:

    受限

    设置为此值表明该程序包无需提升权限即可安装。

    提升

    设置为此值表明该程序包需要提升权限才能进行安装。此为默认值。

     

    制造商

    字符串

    发布此包的供应商。

     

    平台

    字符串

    此程序包支持的平台列表。

     

    对于许多安装程序(例如本示例),最好在 MSI 中将所有安装源文件打包在一起。通过 Media 元素,我们只需指定希望将文件存储到压缩和嵌入式 .cab 文件即可。但是,更大的安装程序可能需要跨多个磁盘。在这种情况下,您需要在 WiX 源文件中定义多个 Media 元素,并根据需要将资源分配到每个磁盘中。

    表 3 — Media 元素属性(部分列表)

    名称

    类型

    说明

    必需

    Id

    整数

    Media 表的磁盘标识符。此数值必须等于或大于 1。

    Cabinet

    字符串

    Cabinet 的名称(如果将存储在媒体上的部分文件或所有文件都压缩到了 Cabinet 文件中)。如果未使用任何 Cabinet,此属性必须为空。

     

    DiskPrompt

    字符串

    磁盘名称,通常是磁盘上印刷的可见文本。此文本可本地化,用于提示用户何时需要插入此磁盘。此值将用于 DiskPrompt 属性的“[1]”中。使用此属性需要定义 DiskPrompt 属性。

     

    EmbedCab

    YesNoType

    如果设置为“是”,则指示活页夹将 Cabinet 嵌入到产品中。此属性只能与 Cabinet 属性一起指定。

     

    VolumeLabel

    字符串

    该标签指示卷的属性。这是 GetVolumeInformation 函数返回的卷标。如果 SourceDir 属性指的是可移动(软盘或 CD-ROM)卷,则在尝试安装文件之前可通过此卷标验证驱动器中是否存在适当的磁盘。此列中的条目必须与物理媒体的卷标匹配。

     

    本示例的下一步介绍如何定义位置以及要安装的文件。即使以前没有用过 WiX 或 Windows Installer,您也可能猜到此步骤是要创建“\Program Files\Test Program”文件夹中 readme.txt 文件的副本。乍看起来,嵌套 Directory 元素系列可能有些混乱。因此,让我们更详细地介绍一下相关信息。

    < Directory Id='TARGETDIR' Name='SourceDir' >
      < Directory Id='ProgramFilesFolder' Name='PFiles' >
        < Directory Id='MyDir' Name='TestProg' LongName='Test Program' >

    MSI 数据库要求将单个根目标目录定义为 < Directory Id='TARGETDIR' Name='SourceDir' >。“TARGETDIR”和“SourceDir”属性都可被 Windows Installer 识别。如果“TARGETDIR”属性是通过命令行或用户界面定义的,则使用此属性解析目标路径。就我们的简单安装程序而言,不会对此进行定义,Windows Installer 将默认使用“ROOTDRIVE”属性,类似于“C:\”。“SourceDir”属性仅表示包含安装程序包的目录。

    下一个 Directory 元素是根目标目录的子目录,被定义为 < Directory Id='ProgramFilesFolder' Name='PFiles' >。“ProgramFilesFolder”是另一个 Windows Installer 属性,指示系统上预定义 Program Files 文件夹的完整路径。有关其他可用系统文件夹属性的示例,请参阅 MSDN 库中的系统文件夹属性。在此,我们可以查看“C:\Program Files\”的目标安装文件夹。

    最后,我们将最后一个 Directory 元素定义为 < Directory Id='MyDir' Name='TestProg' LongName='Test Program' >。这次,“MyDir”Id 属性并不是已定义的属性,因此将使用默认的 Name 属性或 LongName 属性。这就完成了本示例的目录结构,可能是“C:\Program Files\Test Program\”。

    表 4 — Directory 元素属性(部分列表)

    名称

    类型

    说明

    必需

    Id

    字符串

    此值是目录条目的唯一标识符。

    FileSource

    字符串

    用于为此目录的子元素设置文件系统源。

     

    LongName

    LongFileNameType

    将此值设置为该目录的非 8.3 名称。除非使用 Name 属性设置该目录的短名称,否则无法指定该属性。

     

    LongSource

    LongFileNameType

    在支持长名称的系统的源媒体上,将此值设置为该目录的非 8.3 名称。除非使用 SourceName 属性为此目录设置了源名称,否则无法指定该属性。

     

    名称

    字符串

    目录的 8.3 名称。如果此目录与父目录代表相同的目录,则不要指定此属性(或 LongName 属性)。有关“.”运算符的详细信息,请参阅 Windows Installer SDK 的 Directory 表主题。

     

    SourceName

    ShortFileNameType

    源媒体上目录的 8.3 名称。如果未指定此属性,则 Windows Installer 将使用默认的 Name 属性。

     

    设置好目录结构后,接下来我们便可以指定要安装的文件组件了。为方便起见,下面列出了示例中的相关代码段:

    < Component Id='MyComponent' Guid='12345678-1234-1234-1234-123456789012' >
      < File Id='readme' Name='readme.txt' DiskId='1' src='readme.txt' / >
    < /Component >

    由 GUID 唯一定义的组件可以表示资源,如文件、证书、环境变量、COM 注册、注册表项、服务、SQL 数据库和网站。在我们的示例中,我们只需安装文本文件,其中“src”属性指构建过程中 readme.txt 文件的位置。DiskId 属性指先前定义的媒体 Id 属性。

    表 5 — Component 元素属性(部分列表)

    名称

    类型

    说明

    必需

    Id

    字符串

    Component 标识符;这是标识组件的主键。

    Guid

    ComponentGuid

    此值应是一个 GUID,以便唯一标识此组件的内容、语言、平台和版本。此外,还可以将此值设置为空字符串以指定非托管组件。由于 Windows Installer 无法删除或修补非托管组件(实际上,它是不可修补的永久性组件),所以这些组件是一种安全漏洞。因此,对于包含将来可能需要修补的资源的任何组件,应始终为其指定 GUID。

    位置

    枚举

    此属性的值应为下列值之一:

    本地

    防止组件从源或网络运行(如果未设置此属性,则默认为此行为)。

    确保组件只能从源运行(无法从用户的计算机运行)。

    两者中的任意一个

    允许组件从源或从本地运行。

     

    永久

    YesNoType

    如果将此属性设置为“是”,则在卸载过程中安装程序不会删除该组件。安装程序将在 Windows Installer 注册表设置中为该组件注册额外的系统客户端(这一般意味着至少有一个产品经常引用此组件)。请注意,此选项与不设置 GUID 的行为不同,因为尽管该组件是永久性的,但仍可对其进行修补(因为 Windows Installer 仍然能够跟踪它),只是不可卸载。

     

    可传递

    YesNoType

    如果将此属性设置为“是”,安装程序将在重新安装时重新计算 Condition 语句中的值。如果此值先前为 False,但现已更改为 True,则安装程序将安装该组件。如果此值先前为 True,但现已更改为 False,则即使该组件拥有其他产品作为客户端,安装程序也会将其删除。

     

    请务必注意,Windows Installer 将添加到组件的所有资源视为原子单元,其中的所有内容都作为一个整体进行安装和卸载。因此,建议将各种资源置于其自己的组件中,有特殊需求则另当别论。例如,如果您希望添加指向桌面上文本文件的链接,则最好将其置于同一组件中。

    由于此安装程序中至少包括一个组件,因此,我们需要为它定义一个父 Feature 元素。此步骤目前看来可能是多余的,但这是因为我们的安装程序只有一个组件,并且没有 UI。当需要安装多个组件和逻辑应用程序段(其中一些是可选的)时,创建功能集就变得非常必要了。例如,通常安装程序会将应用程序的核心功能与可选帮助文件分开。

    提醒一下,我们的简单示例中的 Feature 元素类似以下内容:

    < Feature Id='MyFeature' Title='My 1st Feature' Level='1' >
      < ComponentRef Id='MyComponent' / >
    < /Feature >

    Feature 元素将“MyFeature”定义为包括先前定义的单个组件。同样,由于本示例中我们不为用户提供 UI,因此,此功能实际上是必需的。

    现在,让我们使用示例 WiX 源代码生成 Windows Installer 程序包,通过下列步骤应可将该程序包安装到几乎任何 Windows 计算机上:

    • 选择开始 | 所有程序 | 附件 | 命令提示符打开“命令提示符”窗口。
    • 在“命令提示符”窗口中导航到 WiX 二进制安装位置的“\examples\first”文件夹。
    • 通过发出命令,验证 product.wxs 包含我们先前讨论的示例代码
      >notepad product.wxs
    • 通过发出命令,将 WiX 工具集二进制文件夹添加到环境路径中(将 < WiXbinaries> 替换为您计算机上的安装位置):
      >path = %path%; < WiXbinaries>
    • 通过以下命令,使用 Candle.exe 编译器工具编译 product.wxs 源文件:
      >candle product.wxs
      编译步骤最后将生成名为 product.wixobj 的 WiX 对象文件。
    • 通过以下命令,使用 Light.exe 链接程序工具链接 product.wixobj 对象文件:
      >light product.wixobj
      链接步骤最后将生成名为 product.msi 的 Windows Installer 数据库文件。
    • 在“命令提示符”窗口中键入示例产品全名或通过资源管理器双击该产品来安装此产品。请注意,显示给我们的是部分进度 UI 信息,而整个过程完成时不会有进一步交互。
    • 通过导航到“Program Files”文件夹并查找包含 readme.txt 文件的“Test Program”文件夹,验证安装程序是否可正常运行。
    • 通过在添加/删除程序控制面板小程序中执行一些必要的步骤,验证卸载操作同样可正常运行。此外,您还可以在“命令提示符”窗口中发出以下命令:
      >msiexec /x product.msi

    在 Visual Studio Express IDE 中使用 WiX

    在结束 WiX 讨论之前,让我们花几分钟来自定义一下 Visual Studio 速成版环境,以便获得 WiX Intellisense 支持以及一些可用的 WiX 模板文件。Intellisense 是 Visual Studio 中的一项技术,使您能够通过键入某个词(如类名称或 XML 标记)的一部分,就可看到一列可能的匹配项和说明。稍后您将看到,此工具在手动编辑 WiX 代码时非常有用!

    为 WiX 添加 Intellisense 支持:

    • 导航到 WiX 安装的“Doc”文件夹
    • 将所有 XML 架构文件(XSD 扩展名)复制到 Visual Studio 安装位置中的“\XML\Schemas”文件夹(通常位于“\Program Files\Microsoft Visual Studio 8\”中)


    添加 WiX 模板文件:

    • 从 Word 文档所在的同一位置下载 WiX 模板 Zip 文件包 (WiXTemplates.zip)。
    • 将 WiX 模板 Zip 包的所有内容解压缩到“\My Documents\Visual Studio 2005\Templates\Item Templates”文件夹中。
    • 验证“WiX Merge Module.zip”“WiX Product.zip”均位于 ItemTemplates 文件夹中。

    如果使用 Windows Installer 数据库文件和扩展 WiX 源文件,则必须生成全局唯一标识符 (GUID)。GUID 可以使用多种格式表示,具体取决于它们的用途,但是我们将使用以下格式:

    “01234567-89AB-CDEF-0123-456789ABCDEF”

    或使用

    {“01234567-89AB-CDEF-0123-456789ABCDEF”}

    由于需要生成唯一的 GUID,因此,必须使用能够为我们完成此操作的工具。以下是一些建议:

    • 安装 Microsoft Visual C++ 2005 速成版,并使用 Guidgen.exe 实用程序(位于 \Program Files\Microsoft Visual Studio 8\Common7\Tools 中)。使用“注册表格式”选项以 WiX 兼容格式创建 GUID。
    • 创建自己的应用程序。可以使用 System.Guid 类及其静态的 NewGuid() 方法来生成新的 GUID。
    • 在线查找其他 GUID 生成工具。例如,尝试访问 http://www.guidgen.com


    配合使用

    在此部分中,我们将为一个简单的 Windows 应用程序创建安装程序,借此整理目前为止学到的所有内容。

    任务 1:创建 WiX 源。

    • 打开您所使用的 Visual Studio 速成版的一个实例。
    • 选择文件 | 新建项目创建一个新项目。同时,将加载“新建项目”窗口。
    • 选择Windows 应用程序项目模板,并添加一个便于以后记下的名称。
    • 确定按钮以生成新的 Windows 应用程序项目。
    • 在解决方案资源管理器中,右键单击该项目并从上下文菜单中选择添加 | 新项,将新的 WiX 源文件添加到该项目中。
    • 在“添加新项”窗口中,向下滚动我的模板部分。
    • 选择WiX 产品模板。
    • 添加按钮将新的 WiX 产品源文件添加到该项目中。
    • 选择文件 | 保存所有文件将该项目保存到磁盘。请记住该项目的名称,因为稍后该名称将非常重要。
    • 在“Program Files”文件夹中选择一个适当的安装位置,并将其分配到 Directory 元素的 LongName 属性,将其 ID 命名为“INSTALLATIONLOCATION”。
    • Component 元素 Id更改为更合适的名称,如“MyApp”。注意:此处不能使用空格。
    • 更改ComponentRef 元素 Id,使其与上一步骤中修改的 Component 元素 ID 匹配。
    • 使用以下代码为 Component 元素添加新的 File 子元素:
      < File Id="app" Name="MyApp.exe" DiskId="1" src="WiXInstallTest.exe" />
      请注意,File 元素的“src”属性应与生成的可执行文件的名称(默认为项目名称)匹配。
    • 使用以下代码为 File 元素添加新的 Shortcut 子元素:
      < Shortcut Id="desktopShortcut" 
         Name="WiXTest" LongName="WiX Test 1.0" 
         Directory="DesktopFolder" />

      请注意,务必确保 Shortcut 是 File 元素(而不是 Component 元素)的子元素。我们希望创建一个桌面快捷方式,直接指向该文件。“DesktopFolder”是 Windows Installer 可以识别的属性,用于表示用户桌面。
    • 在最后一个 Directory 元素结束标记前添加以下 Directory 元素:
      < Directory Id="DesktopFolder" Name="Desktop" />
      < /Directory>

      请注意,上文显示的 < /Directory> 结束标记并不是新的,它只是用来显示需要将新 Directory 元素置于何处的引用标记。
    • 生成新的 GUID,并将其分配到显示“PUT-GUID-HERE”Component Guid 属性中。
    • 生成新的 GUID,并将其分配到显示“PUT-GUID-HERE”ProductId 属性中。


    任务 2:修改该项目以执行生成后步骤。

    注意:该任务仅适用于 C#、J# 和 C++ 用户。如果您使用的是 VB,则需要自己编译和链接 WiX 代码。

    • 在解决方案资源管理器中,右键单击您的项目,然后从上下文菜单中选择属性
    • 选择生成事件选项卡(适用于 C# 和 J#)
      或者
      选择配置属性 | 生成事件 | 生成后事件节点(适用于 C++)。
    • “生成后事件命令行”文本框中,输入以下内容:
      "C:\wix 2.0.4820.0-binaries\candle.exe" "WiXProduct1.wxs"
      "C:\wix 2.0.4820.0-binaries\light.exe" "WiXProduct1.wixobj"
    • 在解决方案资源管理器中,选择WiX 源文件并查看属性窗口。
    • “复制到输出目录”属性更改“如果较新则复制”


    任务 3:生成和测试部署

    • 从主菜单中选择生成 | 生成解决方案
    • 导航\Build\Debug 文件夹,然后执行安装程序
    • 验证指向该应用程序的桌面链接可正常运行。
    • 通过控制面板中的添加/删除程序卸载该应用程序。


    概述

    在本文中,我们介绍了 Windows Installer XML 工具集,并简述了它可以执行哪些操作来满足您的安装要求。在开发计算机上安装 WiX 工具集并将其与生成环境集成后,创建新的安装程序就比较简单了,但在涉及的许多细节方面还是有点复杂。

    请务必注意,一定要根据安装要求权衡您的选择,从而确定是否真的有必要创建完整的 Windows Installer 数据库。例如,如果创建了独立的 Windows 窗体或 Windows Presentation Framework 应用程序,则使用 ClickOnce 技术可为开发人员和用户简化部署过程。

    请记住,我们仅泛泛地讨论了此主题,通过 WiX,您还可以执行自定义操作、定义用户界面、执行 COM 组件注册等。有关更多详细信息,请参阅 WiX 文档以及 WiX 官方站点(两者均可在下面的参考资料部分中找到)。

    参考资料和其他资源

    Windows Installer XML 工具集官方站点

    Rob Menching 博客文章(WiX 特约撰稿人)

    Justin Rockwood 博客(WiX 特约撰稿人)

    选择部署策略
    http://msdn2.microsoft.com/library/e2444w33(VS.80).aspx

    Windows Installer 部署

    Windows Installer 最佳实践

    Windows Installer Wikipedia 文章

  • strstr

    2008-11-04 23:45:58

    /* Check if string B includes string A */

    bool strstr(char* A, char*  B)
    {
     char* p1 = A;
     char* p2 = B;

     if(*p1 == '/0' || *p2 == '/0')
     return false;
     
     
     while(*p2 != '/0' && *p2 != *p1)
     {
      p2++;
     }
     
     if(*p2 == '/0')
     return false;
     
     while(*p1 == *p2)
     {
      p1++;
      p2++;
     }
     
     if(*p1 == '/0')
     {
      return true;
     }
     else
     {
      return strstr(A, p2)
     }
    }

数据统计

  • 访问量: 21415
  • 日志数: 14
  • 文件数: 1
  • 书签数: 8
  • 建立时间: 2008-11-01
  • 更新时间: 2009-02-25

RSS订阅

Open Toolbar