代码之家  ›  专栏  ›  技术社区  ›  Ryan

用于更改MSI中的操作序列记录的脚本

  •  6
  • Ryan  · 技术社区  · 15 年前

    解决问题 listed here 我必须更改MSI中的InstallExecuteSequence.RemoveExistingProducts记录。

    我想把它作为构建过程的一部分,而不是和奥卡混在一起

    3 回复  |  直到 7 年前
        1
  •  13
  •   Ryan    15 年前

    修改MSI_SetProperty.js脚本会

    // MSI_SetActionSequence.js <msi-file> <table> <action> <sequence>
    // Performs a post-build fixup of an msi to set the specified table/action/sequence
    
    // Constant values from Windows Installer SDK
    var msiOpenDatabaseModeTransact = 1;
    
    var msiViewModifyInsert         = 1;
    var msiViewModifyUpdate         = 2;
    var msiViewModifyAssign         = 3;
    var msiViewModifyReplace        = 4;
    var msiViewModifyDelete         = 6;
    
    if (WScript.Arguments.Length != 4)
    {
        WScript.StdErr.WriteLine("Usage: " + WScript.ScriptName + " file table action sequence");
        WScript.Quit(1);
    }
    
    var filespec = WScript.Arguments(0);
    var table = WScript.Arguments(1);
    var action = WScript.Arguments(2);
    var sequence = parseInt(WScript.Arguments(3));
    
    var installer = WScript.CreateObject("WindowsInstaller.Installer");
    var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);
    
    WScript.StdOut.WriteLine("Looking for action:" + action);
    
    try
    {   
        var sql = "SELECT Action, Sequence FROM " + table + " WHERE Action = '" + action + "'";
        var view = database.OpenView(sql);  
    
        view.Execute();     
        var record = view.Fetch();  
    
        if (record)
        {       
            while (record)
            {
                WScript.StdOut.Write("Found: " + record.StringData(0) + ", " + record.StringData(1) + ", " + record.StringData(2));
                if (record.IntegerData(2) != sequence)
                {
                    WScript.StdOut.WriteLine(" - changing to " + sequence);
                    record.IntegerData(2) = sequence;
                    view.Modify(msiViewModifyUpdate,record);
                }
                else
                    WScript.StdOut.WriteLine(" - OK");
    
                record = view.Fetch();
            }
    
            view.Close();
            database.Commit();
        }
        else
        {           
            view.Close();   
            throw("Warning - Could not find " + table + "." + action);
        }
    }
    catch(e)
    {
        WScript.StdErr.WriteLine(e);
        WScript.Quit(1);
    }
    

    要调用此脚本来执行对上述操作序列的更改,您需要将以下内容放入批处理文件中,并从生成后事件调用该文件,例如PostBuildEvent=$(ProjectDir)PostBuild.bat

    cscript.exe MSI_SetActionSequence.js YOURINSTALLER.MSI InstallExecuteSequence RemoveExistingProducts 1525
    
        2
  •  0
  •   Eric    14 年前

    一些笔记给其他人。我遇到了“错误1001。指定的服务已经存在”的问题,并尝试了上面的方法,但似乎不起作用。以下是我遇到的情况:

    我在GAC中安装了一些程序集。似乎当我移动RemoveExistingProducts序列时,这些文件已从GAC中删除,但未重新安装。为了解决这个问题,我在应用程序文件夹中安装了所有程序集。仅供参考,我正在使用VS2010。

    说了这么多,谢谢你发这个帖子!

        3
  •  0
  •   Markus2k    13 年前

    Ryan提供的解决方案解决了我面临的部分问题。它会执行完全卸载,然后执行安装。

    然而,我有另一个问题,在我的例子中,一些程序是在后台运行的。在安装程序运行之前,安装程序会抱怨某些文件正在使用中。并提供标准对话框,要求关闭应用程序或重新启动以完成更新。

    是否有一种方法(例如自定义操作或设置)可以终止后台运行的进程,从而使安装程序顺利进行?