1

我创建了 WiX 安装程序项目,用于在客户机器上部署我的 .net winform 应用程序。该应用程序仅扫描文档并将图像保存到服务器上的数据库中。扫描仪非常具体,公司中只有一台,但大约有。偶尔可以使用它的四个用户 => 应用程序将仅安装在一个专门用于扫描的工作站上 - 大多数情况下它将是免费的,这些用户中的任何一个都可以来,扫描文档并继续他的工作。

=> 我正在进行每台机器的安装:ALLUSERS 被硬编码为 1。

因为生产中的数据库服务器不受我控制,而且我真的不知道数据库将存储在哪里,所以我无法将正确的 ConnectionStrings.config 文件打包到 MSI 存档中。而不是它,安装程序会根据用户在安装期间提供的参数值修改此配置。为了更新连接字符串,我使用 util:XmlFile 元素。connectionstrings.config 文件与应用程序二进制文件一起存储在安装目录中。

一切似乎都运行良好,直到我使用这个每台机器安装模拟了两个用户。我已经在自己的帐户下执行了我的 wix 设置项目,XML 配置文件已正确更新,然后我启动了应用程序并测试了连接字符串是否正常。一切都很好。

然后我切换到另一个用户帐户。快捷方式已经出现在程序菜单中 - 正如我所期望的那样,因为安装是每台机器的。所以我点击了快捷方式,然后(对我来说出乎意料)一个进度条窗口“等到产品 XY 的配置完成”。出现了。(请注意,我的机器语言环境不是英语,在英语语言环境工作站上的消息可能会略有不同)。几秒钟后,窗口消失了,我的应用程序启动了。不幸的是,它无法连接到数据库,因为 connectionStrings.config 文件已被重写 - 连接字符串已使用默认(=不正确)属性值进行了更新。

我一直在研究为什么每当新的用户帐户尝试使用它时设置会再次启动。这是因为快捷方式元素(快捷方式被放置到“ProgramMenuFolder”。有一个卸载操作的请求,AFAIK 需要一个父组件,这个组件需要一个 KeyPath,它必须是 HKCU 下的注册表项。)。当我从 WXS 中删除所有 Program-Menu-Shortcut-stuff 时,切换用户上下文后不会再次启动 MSI。

结果是我有安装程序,它能够根据输入参数配置与数据库的连接。但是以后任何尝试从第二个用户帐户使用该应用程序只会将此配置发送到厕所。在生产环境中,这意味着每次新用户尝试使用该应用程序时,管理员必须来手动更改连接字符串,这当然是不可接受的行为。

这是我的 WiX 源代码的简化版本:

    <?define ProductID = "11111111-1111-1111-1111-111111111111" ?>
    <?define ProductName = "MyProduct" ?>
    <?define ProductLocalName = "MyLocalLanguageProductName" ?>

    <!-- application's root registry path, where it stores its settings -->
    <?define ApplicationRootRegistryKey = "Software\MyCompany\MyProject\MyBuildConfiguration" ?>

    <Product Id="$(var.ProductID)" UpgradeCode="{11111111-1111-1111-1111-111111111112}"
             Name="$(var.ProductName)" Version="1.10.1103" 
             Manufacturer="MyCompany"Language="1029" Codepage="1250">

    <Package Id="*" InstallerVersion="200" Compressed="yes"
             Description="$(var.ProductName) Installer" Languages="1029" 
             SummaryCodepage="1250" />

        <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />

        <!-- always install the app for all users -->
        <Property Id="ALLUSERS" Value="1"/>

        <!-- initialize properties used for adjusting connection strings.
             The user will provide valid property values through command-line -->
        <Property Id="DB_SERVER_NAME" Value="please-specify-db-server-name"/>
        <Property Id="DB_NAME" Value="please-specify-db-name"/>

        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="ProgramFilesFolder" Name="PFiles">
                <Directory Id="CompanyProgramFilesFolder" Name="CompanyName" >
                    <Directory Id="INSTALLDIR" Name="ProjectName">
                        <Directory Id="InstallDirApp" Name="Bin" />
                    </Directory>
                </Directory>
            </Directory>
            <Directory Id="ProgramMenuFolder" Name="Programs">
                <Directory Id="AppProgramMenuDir" Name="$(var.ProductLocalName)">
                    <Component Id="ProgramMenuDir" Guid="*">
                        <RemoveFolder Id='AppProgramMenuDir' On='uninstall'/>
                        <RegistryValue Root='HKCU' Key='$(var.ApplicationRootRegistryKey)' Type='string' Value='' KeyPath='yes' />
                    </Component>
                </Directory>
            </Directory>
        </Directory>

        <DirectoryRef Id="InstallDirApp">
            <Component Id="Executable" Guid="*">
                <File KeyPath="yes" Source="$(var.MyProject.TargetPath)">
                    <Shortcut Id="ProgramMenuShortcut" Name="$(var.ProductLocalName)"
                              Directory="AppProgramMenuDir" Advertise="yes"
                              WorkingDirectory="InstallDirApp" Icon="AppIcon.ico" IconIndex="0"/>
                </File>
            </Component>

            <!-- ConnectionStrings config file deployment and settings adjustment -->
            <Component Id="ConnectionStrings.config" Guid="*">
                <File KeyPath="yes" Source="$(var.Csob.ChequesScanning.SmartShell.TargetDir)ConnectionStrings.config" />
            <!--</Component>

            <Component Id="xml01" Guid="*">-->
                <!--<Condition><![CDATA[NOT Installed]]></Condition>-->

                <!-- this sets the connection strings according to provided parameters -->
                <util:XmlFile Id="SetConnectionString" Action="bulkSetValue"
                              File="[#ConnectionStrings.config]"
                              ElementPath="//add" Name="connectionString"
                              Value="Data Source=[DB_SERVER_NAME];Initial Catalog=[DB_NAME];Integrated Security=True;Pooling=True"
                              Permanent="yes" />
            </Component>
        </DirectoryRef>

        <Icon Id="AppIcon.ico" SourceFile="$(var.MyProject.ProjectDir)Resources\AppIcon.ico" />


        <Feature Id="ProductFeature" Title="MyProjectName" Level="1">
            <ComponentRef Id="Executable" />
            <ComponentRef Id="ConnectionStrings.config"/>
            <ComponentRef Id="ProgramMenuDir" />
        </Feature>

    </Product>
</Wix>

我已经尝试了这些步骤来解决问题,但没有任何帮助:
1)我已经分离了独立组件。
2)我尝试在这些组件下添加未安装。
3) 我尝试在安装过程中向 HKLM 写入注册表值。我为该注册表值添加了 RegistrySearch 和属性,然后将该值用作条件(实际上只是替换了之前的“未安装”)

有人能帮忙吗?我究竟做错了什么?

谢谢指教

马立克

4

1 回答 1

0

根目录下的注册表项HKMU请参阅参考资料)。这将根据 ALLUSERS 属性的值正确地将您的注册表项植根于 HKLM 或 HKCU。

于 2010-11-08T13:01:36.717 回答