WiX overwrites config files during setup. How can I avoid this?

孤者浪人 提交于 2019-11-28 19:23:37

I sure someone will come up with a proper answer, but as a backup:

You could have the installer create a default configuration file, and then have your application copy the default file to the normal configuration file, if the normal configuration file is not present. This also provides an easy way to reset the application to factory default (just delete the configuration file).

Dave Andersen

The Component @NeverOverwrite="yes" attribute might be the solution to this problem.

From the WiX help documentation:

If this attribute is set to 'yes', the installer does not install or reinstall the component if a key path file or a key path registry entry for the component already exists. The application does register itself as a client of the component. Use this flag only for components that are being registered by the Registry table. Do not use this flag for components registered by the AppId, Class, Extension, ProgId, MIME, and Verb tables.

Component Element Documentation

Component/@NeverOverwrite="yes" will do this. Just remember to set File/@KeyPath="yes" on one or more of the files so it can detect whether it is already present.

If you're using heat.exe to harvest your file list automatically, you can use the following XSLT stylesheet to set this attribute on each Component containing a config file (and set each config File element as a key path).

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"
                exclude-result-prefixes="msxsl wix">
  <xsl:output method="xml" indent="yes" />

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="//*[local-name()='Component']">
    <wix:Component Id="{@Id}" Directory="{@Directory}" Guid="{@Guid}">
      <xsl:if test="contains(*[local-name()='File']/@Source, '.config')">
        <xsl:attribute name="NeverOverwrite">yes</xsl:attribute>
      </xsl:if>
      <xsl:apply-templates select="@* | node()"/>
    </wix:Component>
  </xsl:template>

  <xsl:template match="@KeyPath">
    <xsl:choose>
      <xsl:when test="contains(parent::node()/@Source, '.config')">
        <xsl:attribute name="KeyPath">
          <xsl:value-of select="'yes'"/>
        </xsl:attribute>
      </xsl:when>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

(Note: the XML namespace handling can probably be cleaned up, but it works.)

This really is an application bug, not a setup issue.

You shouldn't be "installing" data that is later editable by the user, Windows Installer records the size, modification date and hash value of files installed. That way if the file is later discovered to be "corrupt" it can be repaired.

We install a default config file that is copied to the user config when none is found, that way Windows Installer never even knows about the user editable config and so doesn't do any replacement.

You can change the default behavior with REINSTALLMODE property. It defaults to "Reinstall if the file is missing or is an older version", which is logically correct, as for me. But you can experiment with other values to find the behavior you need.

Hope this helps.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!