打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Wix打包系列(三)自定义Action(Custom Action)
userphoto

2023.04.20 加拿大

关注

3.1 关于Action

我们已经知道如何生成具有标准安装界面的安装程序了,Windows Installer按照我们的界面设置使用标准的安装步骤进行安装,它的安装过程是由一系列标准的Action组成,通过这些Action来完成对计算机的安装配置;如果我们想自定义安装步骤或者在安装过程中执行自定义的操作,就需要使用自定义的Action。当然,使用Custom Action之前,我们应该先了解一下msi中这些标准的Action。

首先,我们通过Orca工具(参考Windows Installer SDK)打开Sample.msi文件,可以看到使用wix标准安装界面生成的安装程序包含哪些Action,如下图,我们可以看到这些Action的名称和安装顺序,关于Orca以及msi数据库的表和字段的含义,本文不做介绍,有兴趣可以查看msi sdk

这里我们主要关注InstallExecuteSequence 和InstallUISequence表,他们之间的区别是InstallUISequence只有在内置UI的等级是Full UI或者reduced UI时才会起作用,在basic UI 或者silent方式安装时不起作用;关于UI等级 在msi sdk中UILevel Property章节有详细说明。我们定义的Custom Action也可能会包含在这些   Action序列中,通过Sequence来确定执行顺序;当然也可能不包含在Action序列中,当这个Action是由按钮触发的时候。

3.2 Custom Action

    下面我们来看看怎么使用Custom Action,我们在代码中Product标签下加入如下代码:

  1. <Property Id='NOTEPAD' Value='Notepad.exe'/>
    <CustomAction Id='LaunchFile' Property='NOTEPAD' ExeCommand='[INSTALLDIR]Manual.pdf' Return='asyncNoWait' />
    <InstallExecuteSequence>
    <Custom Action='LaunchFile' After='InstallFinalize'>NOT Installed</Custom>
    </InstallExecuteSequence>
    添加以上代码的作用是安装结束后使用记事本打开安装目录下的Manual.pdf文件,代码很好理解CustomAction标记指示要执行的动作,而InstallExecuteSequence指示Action执行的顺序,在InstallFinalize之后执行,NOT Installed是安装的条件,指的是只有在首次安装的时候才会运行此Action,维护模式时不执行Action。
   wix中使用属性来区分Action的种类,对于不同种类的Action需要使用不同的属性组合;而msi中使用Type来区分,具体可参考http://msdn.microsoft.com/library/aa368062.aspx
   假如我们要安装后直接运行应用程序,CustomAction可以做如下调整:
  1. <CustomAction Id='LaunchFile' FileKey='filFoobarEXE' ExeCommand='' Return='asyncNoWait' />
3.3 Control Action
    3.2中的LaunchFile动作在InstallExecuteSequence序列中的InstallFinalize动作之后执行,即便InstallFinalize已经在InstallExecuteSequence的最后了,但是LaunchFile仍然会在完成界面弹出之前执行;一般我们都想在结束界面点击完成按钮之后执行LaunchFile动作,这时我们就需要用到按钮的事件了,把CustomAction动作绑定到按钮的事件中,这样点击结束按钮就可以执行LaunchFile了,操作步骤如下:
    首先,同样添加CustomAction:
  1. <CustomAction Id='LaunchFile' FileKey='filFoobarEXE' ExeCommand='' Return='asyncNoWait' />

然后,我们可以查到WixUI_Mondo模式的结束窗口是ExitDialog,需要给ExitDialog界面的完成按钮添加事件:

  1. <UI Id='MyWixUI_Mondo'>
    <UIRef Id='WixUI_Mondo' />
    <UIRef Id='WixUI_ErrorProgressText' />

    <Publish Dialog='ExitDialog' Control='Finish' Event='DoAction' Value='LaunchFile' Order='1'>1</Publish>
    </UI>
    Publish是用来定义按钮的事件,Control是按钮的标识;Event属性是事件类型,这里我们只介绍DoAction类型;Value的值就是CustomAction的标识;一个按钮可以定义多个Publish事件,Order的值是设置事件执行的顺序,ExitDialog本身没有定义其他事件,这里可以定义为1;如果不知道默认界面的按钮有哪些事件,可以用Orca工具打开msi文件,通过查看ControlEvent表可以知道所有按钮的事件和顺序。
    另外要注意的是:Publish标签必须定义在Control或者UI的下级,因此这里我们定义了一个自定义的UI标签MyWixUI_Mondo。
    关于不同Type的Action应用还有很多,感兴趣的可以看wix和msi sdk的文档,下面我们主要介绍如何编写托管的Custom Action。

3.4 编写托管的Custom Action

比如我们要在安装之前检查某个数据库连接是否存在,上面的CustomAction设置则不能满足我们的要求,这时我们就需要自己写一个Action 的DLL。这里我们只介绍如何使用c#生成Action ,对于使用VB和c++语言则不做介绍。

如果我们在安装wix之前安装了vs2005或者vs2008,我们就可以很方便的在vs开发环境下生成Action ,首先在解决方案资源管理器中右键解决方案名称,然后选择添加项目,在添加新项目对话框中项目类型选择wix,模板选择c# Custom Action Project,如图:

下面我们在SampleCustomAction类中添加一个连接数据库的方法,代码如下:

  1. using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.Deployment.WindowsInstaller;

    namespace SampleCustomAction
    {
    public class CustomActions
    {
    [CustomAction]
    public static ActionResult ConnectDataBase(Session session)
    {
    session.Log('Begin ConnectDataBase');

    // 数据库连接串
    string connectionStr = session['CONNECTIONSTRING'];

    // 连接数据库方法
    //if (DBUtil.ConnectDB(connectionStr))
    session['CONNECTSUCCESS'] = '1';
    //else
    session['CONNECTSUCCESS'] = '0';

    return ActionResult.Success;
    }
    }
    }

这里方法实现部分省去了,读者可以自己去实现,数据库连接串CONNECTIONSTRING是在wix源文件中定义的:

  1. <Property Id='CONNECTIONSTRING' Value='data source=(local);user=sa;password=123;initial catalog=master;Persist Security Info=;' />
    然后我们编译SampleCustomAction,在输出目录下会生成2个dll,要注意只有*.CA.dll才是我们需要的,也就是SampleCustomAction.CA.dll,将SampleCustomAction.CA.dll复制到wix源文件所在目录,在Sample.wxs文件中添加如下行:
  1. <Binary Id='ConnectDBClass' SourceFile='$(var.Version)/SampleCustomAction.CA.dll' />

    <CustomAction Id='ConnectDB' BinaryKey='ConnectDBClass' DllEntry='ConnectDataBase' />
    <CustomAction Id='ConnectError' Error='数据库连接失败' />

    <InstallExecuteSequence>
    <Custom Action='ConnectDB' After='CostFinalize' />
    <Custom Action='ConnectError' After='ConnectDB'><![CDATA[CONNECTSUCCESS <> '1' AND NOT Installed]]></Custom>
    </InstallExecuteSequence>
     第1行的Binary 就是我们编写的dll文件,第3行是CustomAction的入口,BinaryKey值是第1行定义的CustomAction的dll标识,DllEntry值是dll中CustomAction的入口函数,第4行是另外一种Type类型的CustomAction,它弹出错误对话框,然后终止安装程序;InstallExecuteSequence中定义Action的执行顺序和执行条件,第8行中条件表明只有CONNECTSUCCESS= '0' AND NOT Installed时此Action才会执行,也就是连接数据库失败并且首次安装时执行。
    注意到这里CustomAction的BinaryKey属性表明CustomAction文件被打包进安装文件中以二进制形式存在,不会被安装到目标计算机硬盘上;如果CustomAction文件是安装到目标计算机硬盘上的文件,则应使用FileKey属性,并添加相应的File标记。
    编译源文件,运行生成的安装包,安装过程中会弹出错误对话框“数据库连接失败”;托管的Action调试起来不方便,可以自己写一个辅助的程序调试,也可以通过session.Log方法记录安装日志,通过以下命令行方式运行安装程序可以生成安装日志:
  1. msiexec /i 1.0.0/Sample.msi /l*v Sample.msi.log

打开安装日志,我们可以看到Action执行的日志:

  1. ...
    ...
    操作结束 15:24:05: CostFinalize。返回值 1
    MSI (s) (E0:BC) [15:24:05:218]: Doing action: ConnectDB
    操作 15:24:05: ConnectDB
    操作开始 15:24:05: ConnectDB
    MSI (s) (E0:F4) [15:24:05:218]: Invoking remote custom action. DLL: C:/WINDOWS/Installer/MSI1A1.tmp, Entrypoint: ConnectDataBase
    MSI (s) (E0:04) [15:24:05:218]: Generating random cookie.
    MSI (s) (E0:04) [15:24:05:250]: Created Custom Action Server with PID 4108 (0x100C).
    MSI (s) (E0:24) [15:24:05:281]: Running as a service.
    MSI (s) (E0:24) [15:24:05:281]: Hello, I'm your 32bit Impersonated custom action server.
    SFXCA: Extracting custom action to temporary directory: C:/WINDOWS/Installer/MSI1A1.tmp-/
    SFXCA: Binding to CLR version v2.0.50727
    Calling custom action SampleCustomAction!SampleCustomAction.CustomActions.ConnectDataBase
    Begin ConnectDataBase
    MSI (s) (E0!F4) [15:24:05:687]: PROPERTY CHANGE: Adding CONNECTSUCCESS property. Its value is '1'.
    MSI (s) (E0!F4) [15:24:05:687]: PROPERTY CHANGE: Modifying CONNECTSUCCESS property. Its current value is '1'. Its new value: '0'.
    操作结束 15:24:05: ConnectDB。返回值 1。
    MSI (s) (E0:BC) [15:24:05:796]: Doing action: ConnectError
    操作 15:24:05: ConnectError。
    操作开始 15:24:05: ConnectError。
    数据库连接不存在
    MSI (s) (E0:BC) [15:24:06:703]: 产品: Foobar 1.0 -- 数据库连接不存在

    操作结束 15:24:06: ConnectError。返回值 3。
    操作结束 15:24:06: INSTALL。返回值 3。
    ...
    ...
    这里CONNECTSUCCESS 属性在wxs源文件中并没有定义,因此在执行到“session['CONNECTSUCCESS'] = '1';”时,会添加该属性,如果wxs源文件中已定义,该处就会修改该属性值。
    如果没有vs编译环境,也可以使用wix提供的MakeSfxCA工具编译生成dll,使用示例如下,具体可以参考wix文档和DTF文档:
  1. 1: csc.exe /target:library /reference:path/Microsoft.Deployment.WindowsInstaller.dll /out:CheckPID.dll CheckPID.cs
  1. 2: MakeSfxCA.exe path/CheckPIDPackage.dll path/sfxca.dll path/CheckPID.dll path/CustomAction.config path/Microsoft.Deployment.WindowsInstaller.dll

    到这里我们已经知道如何创建自定义的Action了,下一节我们将介绍如何自定义对话框,在安装程序标准UI的基础上定义我们自己的对话框和UI流程

Wix打包系列(三)自定义Action(Custom Action)的更多相关文章

  1. Wix打包系列(四) 自定义UI

    原文:Wix打包系列(四) 自定义UI 除了标准的安装界面,如果我们要在安装时需要提供一些额外的信息时,这时就需要自定义界面来显示和录入这些信息. 4.1  自定义对话框 如上一章中我们测试数据库的连 ...

  2. Wix打包系列(二)用户界面和本地化操作

    原文:Wix打包系列(二)用户界面和本地化操作 上一章节,我们已经大概知道如何对文件进行打包安装,不过我们也注意到,通过对Sample.wxs的编译链接,生成的msi安装包没有任何用户界面,只有一个安 ...

  3. Wix打包系列 (六)制作升级和补丁包

    原文:Wix打包系列 (六)制作升级和补丁包 前面我们已经知道怎么制作一个完整安装包了,但我们的软件往往不能一次性就满足客户的需要,当客户需要我们给软件进行升级的时候,我们应该怎么做呢? 在这之前,我 ...

  4. Wix打包系列(一)如何使用wix制作安装程序

    原文:Wix打包系列(一)如何使用wix制作安装程序 最近由于项目需要,需要给客户制作安装程序,一开始使用vs2005自带的打包工程来打包,但用了一段时间发现vs打包太死板,而且使用起来问题很多.收费 ...

  5. Wix打包系列(五) 部署数据库

    原文:Wix打包系列(五) 部署数据库 很多人在使用vs进行打包的时候,经常会为数据库部署的问题犯愁,即便是重写Installer类的方法,也不是很可靠方便,下面我们来看看在wix中如何部署数据库. ...

  6. Wix打包系列(七) 添加系统必备组件的安装程序

    原文:Wix打包系列(七) 添加系统必备组件的安装程序 我们知道在vs的打包工程中添加系统必备组件是一件很容易的事情,那么在wix中如何检测系统必备组件并在安装过程中安装这些组件.这里以.Net Fr ...

  7. WIX Custom Action (immediate, deffered, rollback)

    Following content is directly reprinted from From MSI to WiX, Part 19 - The Art of Custom Action, Pa ...

  8. Android高效率编码-第三方SDK详解系列(三)——JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送

    Android高效率编码-第三方SDK详解系列(三)--JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送 很久没有更新第三方SDK这个系列了,所以更新一下这几天工作中使用到的推送, ...

  9. Android 自定义title 之Action Bar

    Android 自定义title 之Action Bar 2014-06-29  飞鹰飞龙...  摘自 博客园  阅 10519  转 25 转藏到我的图书馆   微信分享:   Action Ba ...

随机推荐

  1. 讲解下for循环的用法,加深记忆

    引子 这是一段很简单的代码,但是即便是这么简单的东西,这里我们还是需要说一下. 关于for循环整个执行流程就是,先执行var i=10,然后到了第二个语句,判断10是否大于0,很明显为true,所以此 ...

  2. 升级版:深入浅出Hadoop实战开发(云存储、MapReduce、HBase实战微博、Hive应用、Storm应用)

          Hadoop是一个分布式系统基础架构,由Apache基金会开发.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力高速运算和存储.Hadoop实现了一个分布式文件系 ...

  3. jquery ajax局部加载方法介绍

    [导读] 在jquery中实现ajax加载的方法有很多种,不像以前的js的ajax只有那一种,下面我们介绍jquery ajax实现局部加载方法总结,有需要了解的朋友可参考.例 代码如下复制代码 $ ...

  4. 高斯消元法~get√

    高斯消元法,是线性代数中的一个算法,可用来求解线性方程组,并可以求出矩阵的秩,以及求出可逆方阵的逆矩阵.高斯消元法的原理是:若用初等行变换将增广矩阵 化为 ,则AX = B与CX = D是同解方程组. ...

  5. DBA日常管理——数据归档(Archiving-Data)

    原文出处:http://www.sqlnotes.cn/post/2013/09/05/DBA-Daily-Jobs-One%E2%80%94%E2%80%94-Archiving-Data 均为本人 ...

  6. hdu 4706

    注意一点 空的地方打空格而不是空字符,我因为这wa了一次... #include<cstdio> #include<cstring> #include<cstdlib&g ...

  7. “新浪UC”的后江湖时代------易名新浪SHOW重出江湖

        说到新浪UC,相信很多老网民应该并不陌生,当年QQ放号收费让新浪UC火爆了好一阵子,而随着QQ的崛起,UC也就渐渐退出了即时通信市场,不过,这并不意味着新浪UC退出了历史舞台,因为目前炙手可热 ...

  8. Java基础:泛型及其擦除性、不可协变性

    转载请注明出处:jiq·钦's technical Blog 1泛型语法: 泛型类: class ClassName<T>{} 泛型方法:public <T> void f(T ...

  9. Struts2 Action接收表单参数

    struts2 Action获取表单传值    1.通过属性驱动式    JSP:        <form action='sys/login.action' method ...

  10. Swift - 滚动视图(UIScrollView)的用法

    1,当图片尺寸超过屏幕时,使用UIScrollView可以实现滚动条视图,即手指触摸滚动屏幕方便浏览整个页面. 1 2 3 4 5 6 var scrollView=UIScrollView() sc ...

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Wix toolset 安装程序制作总结
showing custom menu on selection in UIWebView in iphone
解决windows installer服务不能访问的问题 - Windows Vista ...
使用WiX Toolset创建.NET程序发布Bootstrapper(安装策略管理)(二)
win7系统 无法访问 Windows installer服务。Windows Installer 没有正确安装时
SOLUTION:InstallShield打包时Basic MSI类型安装包升级之初探讨
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服