【问题标题】:Send Custom Action Data via Command Line for Visual Studio Installer通过命令行为 Visual Studio 安装程序发送自定义操作数据
【发布时间】:2012-10-24 13:18:02
【问题描述】:

我有一个 Visual Studio 安装程序,它有一个自定义 UI,其中一个文本框恢复设置为 QUEUEDIRECTORY 属性的值。然后我有一个自定义操作(一个 Installer 类),它使用这一行 /queuedir="[QUEUEDIRECTORY]" 传递该属性值 - 并且安装程序运行良好。

现在,我需要通过命令行发送该值,以便整个组织的系统管理员都可以运行此安装程序。因此,我尝试了以下命令行语句,但它不起作用。

msiexec /i Setup.msi QUEUEDIRECTORY="D:\temp"
Setup.msi QUEUEDIRECTORY="D:\temp"
Setup.msi queuedir="D:\temp"
msiexec /i Setup.msi queuedir="D:\temp"

此外,我似乎在网上找不到任何不觉得他们入侵它的东西,因为他们只是找不到解决方案。我的意思是我已经找到了一些解决方案,他们正在编辑 MSI 数据库和所有内容,但是这似乎不是 正确 解决方案 - 特别是因为我使用的是 Visual Studio 2010 - Microsoft自从首次发布此产品以来,肯定做出了一些改进。

这里是one of the articles,看起来可以工作,但仍然感觉像一个黑客。

无论如何,我希望你能帮助我!

【问题讨论】:

  • 链接到的黑客是真正解决这个问题的唯一方法。当您在 UI 中有一个文本框时,生成的 Visual Studio MSI 文件有一个无条件的自定义操作,将属性设置为空白,因此当您在命令行上指定它时,它会被内部自定义操作破坏。

标签: c# visual-studio-2010 command-line installation custom-action


【解决方案1】:

这是我在 Visual Studio 2010 中向我的 MSI 添加仅命令行属性值的方法。它类似于接受的答案,但不那么老套。在安装项目(.vdproj)目录下创建CommandLineSupport.js,代码如下:

//This script adds command-line support for MSI installer
var msiOpenDatabaseModeTransact = 1;

if (WScript.Arguments.Length != 1)
{
    WScript.StdErr.WriteLine(WScript.ScriptName + " file");
    WScript.Quit(1);
}

WScript.Echo(WScript.Arguments(0));
var filespec = WScript.Arguments(0);
var installer = WScript.CreateObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);

var sql
var view

try
{

    sql = "INSERT INTO `Property` (`Property`, `Value`) VALUES ('MYPROPERTY', 'MYPROPERTY=\"\"')";
    view = database.OpenView(sql);
    view.Execute();
    view.Close();

    database.Commit();
}
catch(e)
{
    WScript.StdErr.WriteLine(e);
    WScript.Quit(1);
}

然后在 Visual Studio 中单击您的部署项目以查看项目的属性,并将 PostBuildEvent 设置为:

cscript.exe "$(ProjectDir)CommandLineSupport.js" "$(BuiltOuputPath)"

然后使用自定义操作设置开发项目。单击主输出以进入自定义操作属性,并将CustomActionData 字段设置为/MYPROPERTY="[MYPROPERTY]"

然后您可以在自定义操作安装程序类中访问该属性,如下所示:

public override void Install(IDictionary stateSaver)
{
     base.Install(stateSaver);

     string the_commandline_property_value = Context.Parameters["MYPROPERTY"].ToString();
}

最后你可以运行cmd了。 C:\>Setup.msi MYPROPERTY=VALUE

这不需要在 Orca 中进行任何处理,也不需要像在接受的答案中那样使用任何自定义对话框控件。您也不必修改 PostBuildEvent 以具有正确的 .msi 名称。等等。也可以像这样添加任意数量的属性:

INSERT INTO `Property` (`Property`, `Value`) VALUES ('MYPROPERTY', 'MYPROPERTY=\"\"'),('MYPROPERTY2', 'MYPROPERTY2=\"\"', ('MYPROPERTY3', 'MYPROPERTY3=\"\"')) ";

玩得开心!

【讨论】:

    【解决方案2】:

    好的,所以我最终选择了我在问题中链接的解决方案。但是为了完整起见,让我把脚本放在这里。我需要做的第一件事是构建一个包含以下代码的 JS 文件(我将其命名为 CommandLineSupport.js)并将其放在 .vdproj 相同的目录中

    //This script adds command-line support for MSI build with Visual Studio 2008. 
    var msiOpenDatabaseModeTransact = 1;
    
    if (WScript.Arguments.Length != 1)
    {
        WScript.StdErr.WriteLine(WScript.ScriptName + " file");
        WScript.Quit(1);
    }
    
    WScript.Echo(WScript.Arguments(0));
    var filespec = WScript.Arguments(0);
    var installer = WScript.CreateObject("WindowsInstaller.Installer");
    var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);
    
    var sql
    var view
    
    try
    {
        //Update InstallUISequence to support command-line parameters in interactive mode.
        sql = "UPDATE InstallUISequence SET Condition = 'QUEUEDIRECTORY=\"\"' WHERE Action = 'CustomTextA_SetProperty_EDIT1'";
        view = database.OpenView(sql);
        view.Execute();
        view.Close();
    
        //Update InstallExecuteSequence to support command line in passive or quiet mode.
        sql = "UPDATE InstallExecuteSequence SET Condition = 'QUEUEDIRECTORY=\"\"' WHERE Action = 'CustomTextA_SetProperty_EDIT1'";
        view = database.OpenView(sql);
        view.Execute();
        view.Close();
    
        database.Commit();
    }
    catch(e)
    {
        WScript.StdErr.WriteLine(e);
        WScript.Quit(1);
    }
    

    您当然需要通过在 Orca 中打开 MSI 并将其与您创建的自定义对话框中的 Property 匹配来确保替换正确的 Action

    接下来,既然我的 JS 文件可以正常工作,我需要将 PostBuildEvent 添加到 .vdproj,您可以通过单击 Visual Studio 中的设置项目并点击 F4来实现>。然后找到PostBuildEvent 属性并单击省略号。在PostBuildEvent 中放置此代码:

    cscript "$(ProjectDir)CommandLineSupport.js" "$(BuildOutputPath)Setup.msi"
    

    确保将 Setup.msi 替换为您的 MSI 文件的名称。

    虽然我仍然觉得它是一个 hack……因为它是……它可以工作并且现在可以完成这项工作。这是一个足够小的项目,真的没什么大不了的。

    【讨论】:

      【解决方案3】:

      这是一个旧线程,但有一个更简单、有效的解决方案似乎仍然很难找到,因此我在这里发布它。

      在我的场景中,我们正在使用 VS2013(社区版)和 VS 2013 Installer Project 扩展。我们的安装程序项目有一个自定义 UI 步骤收集两个用户文本和一个绑定到接收这些文本的 Install\Start 步骤的自定义操作。

      我们可以通过 GUI 设置向导完成这项工作,但不能通过命令行完成。最后,在this workaround 之后,我们也能够使命令行工作,无需任何 MSI 文件 Orca 编辑

      事情的要点是直接从 Visual Studio 为所有需要的自定义对话框属性设置一个值,并且该值应采用 [YOUR_DIALOG_PROPERTY_NAME] 的形式。此外,似乎此类“公共”属性必须全部大写。

      这是最终设置:

      自定义对话框属性
      注意例如Edit1PropertyEdit1Value

      自定义操作属性
      注意,后面代码中用到的属性键可以用驼峰命名。

      自定义操作代码

      string companyId = Context.Parameters["companyId"];
      string companyApiKey = Context.Parameters["companyApiKey"];
      

      命令行

      > setup.exe COMPANYID="Some ID" COMPANYAPIKEY="Some KEY" /q /l mylog.txt
      

      HTH

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-29
        • 1970-01-01
        • 1970-01-01
        • 2013-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多