使用Wix的技巧和提示有哪些?

  • 回答 (10)
  • 关注 (0)
  • 查看 (340)

我想知道在以下方面使用Wix的有效建议:

  • 设置Wix项目(布局、引用、文件模式)
  • 将Wix集成到解决方案中,并构建/发布过程
  • 为新安装和升级配置安装程序
  • 以及你想要分享的关于Wix的优点
liqoeiliqoei提问于
BlackKnight写一辈子代码,做一辈子好人回答于

Javascript CustomActions

JavaScript用于MSI自定义操作是错误的原因主要是:很难调试,并且不可靠。实际上,调试并不难,只是和C++不一样。在Javascript中编写CustomActions非常容易,比C++容易,快速,并且可靠。

但是有一个缺点:JavaScriptCustomActions可以通过Orca提取,而C/C++CA则需要reverse-engineering。

使用脚本,只需从某种结构开始。

CustomAction的JavaScript“样板”代码:

//
// CustomActions.js 
// 
// Template for WIX Custom Actions written in Javascript.
// 
// 
// Mon, 23 Nov 2009  10:54
// 
// ===================================================================


// http://msdn.microsoft.com/en-us/library/sfw6660x(VS.85).aspx
var Buttons = {
        OkOnly           : 0,
        OkCancel         : 1,
        AbortRetryIgnore : 2,
        YesNoCancel      : 3
};

var Icons = {
        Critical         : 16,
        Question         : 32,
        Exclamation      : 48,
        Information      : 64
};

var MsgKind = {
        Error            : 0x01000000,
        Warning          : 0x02000000,
        User             : 0x03000000,
        Log              : 0x04000000
};

// http://msdn.microsoft.com/en-us/library/aa371254(VS.85).aspx
var MsiActionStatus = {
        None             : 0,
        Ok               : 1, // success
        Cancel           : 2,
        Abort            : 3,
        Retry            : 4, // aka suspend?
        Ignore           : 5  // skip remaining actions; this is not an error.
};


function MyCustomActionInJavascript_CA() {
    try {
        LogMessage("Hello from MyCustomActionInJavascript");
        // ...do work here...
        LogMessage("Goodbye from MyCustomActionInJavascript");
    }
    catch (exc1) {
        Session.Property("CA_EXCEPTION") = exc1.message ;
        LogException(exc1);
        return MsiActionStatus.Abort;
    }
    return MsiActionStatus.Ok;
}

// Pop a message box.  also spool a message into the MSI log, if it is enabled. 
function LogException(exc) {
    var record = Session.Installer.CreateRecord(0);
    record.StringData(0) = "CustomAction: Exception: 0x" + decimalToHexString(exc.number) + " : " + exc.message;
    Session.Message(MsgKind.Error + Icons.Critical + Buttons.btnOkOnly, record);
}


// spool an informational message into the MSI log, if it is enabled. 
function LogMessage(msg) {
    var record = Session.Installer.CreateRecord(0);
    record.StringData(0) = "CustomAction:: " + msg;
    Session.Message(MsgKind.Log, record);
}


// http://msdn.microsoft.com/en-us/library/d5fk67ky(VS.85).aspx
var WindowStyle = {
    Hidden : 0,
    Minimized : 1,
    Maximized : 2
};

// http://msdn.microsoft.com/en-us/library/314cz14s(v=VS.85).aspx
var OpenMode = {
    ForReading : 1,
    ForWriting : 2,
    ForAppending : 8
};

// http://msdn.microsoft.com/en-us/library/a72y2t1c(v=VS.85).aspx
var SpecialFolders = {
    WindowsFolder : 0, 
    SystemFolder :  1, 
    TemporaryFolder : 2
};

// Run a command via cmd.exe from within the MSI
function RunCmd(command)
{
    var wshell = new ActiveXObject("WScript.Shell");
    var fso = new ActiveXObject("Scripting.FileSystemObject");
    var tmpdir = fso.GetSpecialFolder(SpecialFolders.TemporaryFolder);
    var tmpFileName = fso.BuildPath(tmpdir, fso.GetTempName());

    LogMessage("shell.Run("+command+")");

    // use cmd.exe to redirect the output
    var rc = wshell.Run("%comspec% /c " + command + "> " + tmpFileName, WindowStyle.Hidden, true);
    LogMessage("shell.Run rc = "  + rc);

    // here, optionally parse the output of the command 
    if (parseOutput) {
        var textStream = fso.OpenTextFile(tmpFileName, OpenMode.ForReading);
        while (!textStream.AtEndOfStream) {
            var oneLine = textStream.ReadLine();
            var line = ParseOneLine(oneLine);
                ...
        }
        textStream.Close();
    }

    if (deleteOutput) {
        fso.DeleteFile(tmpFileName);
    }

    return {
        rc : rc,
        outputfile : (deleteOutput) ? null : tmpFileName
    };
}

然后,使用以下内容注册自定义操作:

<Fragment>
  <Binary Id="IisScript_CA" SourceFile="CustomActions.js" />

  <CustomAction Id="CA.MyCustomAction"
              BinaryKey="IisScript_CA"
              JScriptCall="MyCustomActionInJavascript_CA"
              Execute="immediate"
              Return="check" />
</Fragmemt>

当然,您可以根据需要插入尽可能多的Javascript函数,以执行多个自定义操作。 举个例子:我用Javascript在IIS上做了一个WMI查询,以获得一个可以安装ISAPI过滤器的现有网站列表。 这个列表用来填充稍后在UI序列中显示的列表框。

在IIS 7上,IIS没有WMI提供程序,所以我使用了shell.Run()方法调用appcmd.exe来执行工作。

关于Javascript CustomActions

回答过的其他问题

如何通俗的了解kubernetes容器编排?

BlackKnight写一辈子代码,做一辈子好人

Kubernetes 是Google开源的容器集群管理系统,基于Docker构建一个容器的调度服务,提供资源调度、均衡容灾、服务注册、动态扩缩容等功能套件。很有用!

网页直播技术是如何实现的?以及如何实现简单的聊天室功能?

BlackKnight写一辈子代码,做一辈子好人

技术是一方面,另一方面是对于带宽的巨大需求

带宽扩容是个非常耗费金钱和人力的事儿。机房构建,带宽购买,服务器维护,这个问题当你的用户越多的时候所要的带宽和服务器就越多。

将Firestore数据显示到UIPicker Swift 4中

BlackKnight写一辈子代码,做一辈子好人
已采纳
在您的类中创建一个数组变量来保存有关您的程序的信息: var programsArray: [String] = [] 从Firebase读取数据时,而不是print(program)使用programsArray.append(program)。获得所有数据后,调用UIPic...... 展开详请

如何确保DOM元素在包含Flash对象时触发鼠标悬停

BlackKnight写一辈子代码,做一辈子好人
将object / embed标记的wmode参数更改为opaque。 您的代码应如下所示。 <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macro...... 展开详请

检查jQuery中是否可以选择下一个元素,如果是,请选择它

BlackKnight写一辈子代码,做一辈子好人
已采纳
我检查了该.selected课是否是:first-child或:last-child如果它是第一个隐藏前一个孩子,如果它是最后一个隐藏的孩子。这种方式可以防止使用下一个和上一个按钮发生任何错误。 这是我使用的一些代码。 // If prev element accessable...... 展开详请

阻止UI线程的方法

BlackKnight写一辈子代码,做一辈子好人

因为它与UI无关,所以您可以使用ConfigureAwait(false)。这将避免捕获当前同步上下文,并且任务将在TaskScheduler.Default线程池上下文上运行。

await callback().ConfigureAwait(false);

关于作者

BlackKnight

写一辈子代码,做一辈子好人

所属标签

扫码关注云+社区