INI disappear & NeverOverwrite="yes" - wix

I have following problem : a new version disappears after upgrade, although I set NeverOverwrite='yes'. Could anyone help me about this issue?
<Feature Id="CompRef03" Title="CompRef" Level="1">
<Component Id="INIWindowsFolder" Directory="WindowsFolder" Guid="d09921c0-1192-458f-8a3e-88889f56a013" KeyPath="yes" NeverOverwrite="yes" Permanent="yes">
<File Id="test.INI" Source="test\intest.INI"/>
</Component>
</Feature>

Problem: Not sure exactly what has happened here. You don't set REINSTALLMODE=amus, do you? Maybe you have changed the component GUID from version 1 of your package? (component GUIDs must remain stable between versions for reference counting to work correctly). Or else the file could be uninstalled and reinstalled (should not happend when you set a file permanent, but maybe you forgot that in your first package).
IniFile Element: Ini files are actually not supposed to be installed as files, but as "change items" of INI value pairs. In other words you define what entries inside the file should be added, changed, removed, etc... In Wix you use the IniFile Element to achieve this. All merge capabilities, rollback support and advanced ini file handling come along for free. All you need to do is to define what needs to be added or modified in the ini file during your installation. It will also be created if it is not there in the first place. Please find more details in this answer. And here is one more link to IniFile Element usage.

Related

Make Wix to not uninstall common dll

I have Wix project in which I need a common used dll library to be installed if it's absent.
If this dll exists I should not overwrite it.
So, when I set DefaultVersion="0.0.0.0" this dll is not overwritten if it exists, its ok. But when I delete app, the dll is beeing removed. How do I prevent removing dll in the case when it existed before installation?
I don't want to make it permanent because it should be removed if it didn't exist before installation.
<Component Id="myLib.dll" Permanent="no" Directory="Shared_Dir">
<File Name="myLib.dll" KeyPath="yes"
Source="mySource\myLib.dll"
DefaultVersion="0.0.0.0"
/>
Add reference to WixUtilExtension and xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" attribute to Wix element in your code.
Define <Property Id="Dll_Installed" Value="false"/> in Product element.
Add child <Condition>NOT Dll_Installed</Condition> to component myLib.dll.
Add that somewhere in your code:
<Fragment>
<util:FileSearch
Id="Dll_Installed"
Variable="Dll_Installed"
Path="[Shared_Dir]myLib.dll"
Result="exists"/>
</Fragment>
DefaultVersion attribute is not necessary.
The feature you are describing is reference counting. The Windows Installer reference counts with Components. Components are identified by their GUID.
So the normal way to address this requirement is to put the File in a Component and make sure the GUID of the Component is stable. The WiX Toolset should do exactly that automatically if if you do not specify the Component/#Guid attribute.
So the default behavior should just work for you.
The only other piece of the puzzle is the Windows Installer will install the latest version of a file. If the file version is the same or less the file will not be installed but will be reference counted.
Based on the details in the question it seems like you should be just fine with:
<Component Directory="Shared_Dir">
<File Source="mySource\myLib.dll" />
</Component>
One might ask why the Windows Installer use Components to reference count files. We'll, it allows you to group other resources, like registry keys, together and control their install as a unit. Much more important if you are installing COM servers than plain old files.

WiX NeverOverwrite flag deletes file

I have a data file that is installed with my application. When it is installed fresh, the data file gets installed properly. When it is upgrading, it was always overwriting the existing instance of the file, which was not wanted. I added the NeverOverwrite="yes" flag, and now for a new install is still the same, but for an existing install, it is deleting the existing file, and not installing the new file either. Have I used the flag incorrectly? This is the snippet in question:
<Component Id="cmp8553E6DDC92DBCDC568FB76CA13E7AF2" Guid="{C94263EB-56AF-4B19-942F-C92998252932}" NeverOverwrite="yes">
<File Id="fil7C9456E83E3FB4618684509DEEF67EBD" KeyPath="yes" Source="$(var.CDWrapper.ProjectDir)..\foo\bar" />
</Component>
Turns out I didn't have a full understanding of the NeverOverwrite flag and our usage of it. I will have to find a different method to preserve the existing file instead of always installing a new copy, but that's a whole different issue that should have reasonable answers elsewhere.

How to correctly add new files in WiX installation to create an uninstallable patch?

Good time,
I'm trying to create the uninstallable patch (msp file) which should contain the newly added files. The file is added in following maner:
<Directory Id="Some Dir">
<Directory Id="MYDIR" Name="Some Name">
<Component Id="Some Component" Guid="{GUID}" KeyPath="yes">
<File Id="README.txt" Name="README.txt" Source="to_install\README.txt" KeyPath="no"/>
<File Id="default.cfg" Name="default.cfg" Source="to_install\default.cfg" KeyPath="no"/>
... // some more files
</Component>
...
...
I've also tried using the DirectoryRef but got the same results.
The "MYDIR" directory is used in other places also and several other files are already installed there, but the patch is adding new files, and the installation log shows that the CreateDirectory table becomes modified and the uninstallation for patch becomes disabled.
What is a correct way to do it using WiX?
KeyPath :
This value points to a file or folder belonging to the component that the installer uses to detect the component.
It is creating entry in CreateFolder of MSI because of KeyPath is provide at component level that is taking installation folder as its key so your patch become not uninstallable.
Provide KeyPath at one of the file of component that is the most important for that component. So it does not make entry into CreatFolder table of MSI and your patch become uninstallable.
Whether a patch is uninstallable isn't really related to a piece of WiX source like that. One thing you definitely need for an uninstallable patch is a PatchMetadata table that says that the patch is uninstallable, as here:
http://wixtoolset.org/documentation/manual/v3/patching/patch_building.html
or here, see PatchMetadata table if you use a PCP file, AllowRemoval:
https://msdn.microsoft.com/en-us/library/aa370344(v=vs.85).aspx
So there are some things you need to do during patch creation to make the patch uninstallable that are nothing to do with your WiX source. It's not clear from your question how you are creating the patch correctly.
Even if you get the patch generation working, there are some rules that must be followed, described here:
https://msdn.microsoft.com/en-us/library/aa367850(v=vs.85).aspx
where it says (for example) that you can't change the component ids of any existing installed items. Create a verbose log when installing the patch and look for messages like SELMGR and entries saying removl of components is not supported, and if that has happened it means the patch will not apply correctly.

WiX: Make component upgradable, but not uninstallable

I am creating an installer using WiX (and I must say I really don't enjoy it, but that is less WiX's fault and more MSI's. And I absolutely applaud Rob Mensching's helpfulness here and elsewhere).
Is it possible to create a component such that it:
can be updated (via patches and major upgrades)
Files that have changed since install will not be uninstalled (it doesn't matter whether they're also not uninstalled if unchanged)
Ordinary file versioning rules apply when updating (that is, unversioned files that changed since install aren't updated, others are)
I am beginning to think this isn't possible. Marking a component as permanent means the component won't ever be uninstalled, which means it isn't updatable (at least not via major upgrade; how about patches?).
Marking a component NeverOverwrite won't prevent it from being uninstalled, even if the user has changed the unversioned keyFile (thus the user's work is deleted).
I appreaciate all definitive answers, even if they are negative.
I did not try it, but you probably can use a custom action to do this. See From MSI to WiX, Part 5 for an example. The Custom Action Type 38 example includes this:
<Directory Id="INSTALLDIR" Name="Minimal" LongName="MinimalInstallation">
<Component Id="Component1"
Guid="{A77C5B06-132D-4884-8E17-EA10A83C812D}">
<File Id="ReadMe" DiskId="1" Name="Readme.txt" Source="Readme.txt" Vital="yes" KeyPath="yes" />
<!--RemoveFile Id="RemoveCopy" Name="ReadMe2.txt" On="uninstall" /-->
</Component>
</Directory>
....
<CustomAction Id="CopyReadMe"
Script="vbscript">
<![CDATA[
Set fso = CreateObject("Scripting.FileSystemObject")
path = Session.Property("INSTALLDIR")
fso.CopyFile path & "ReadMe.txt", path & "ReadMe2.txt"
]]>
</CustomAction>
<InstallExecuteSequence>
<Custom Action="CopyReadMe" After="InstallFinalize">Not Installed</Custom>
</InstallExecuteSequence>
Here Readme.txt is installed, and using a vbscript custom action copied to ReadMe2.txt. If you do some version and/or modification date checking in vbscript, you can control yourself whether the ReadMe2.txt is overwritten or not. And without the RemoveFile, wix will not uninstall ReadMe2.txt, because it does not know the file exists.
For an upgrade it might be possibe to use a different custom action to copy ReadMe2.txt back to Readme.txt before installing. That way you can let wix handle the Ordinary file versioning rules to determine if Readme.txt can be updated. Then you don't have to add version handling to the vbscript.

Install a file regardless of version number with WiX

MyApp version 1.0 contained the file foo.dll. The version of this file was version 10.5.567. Now MyApp is version 2.0 and the version of foo.dll is 2.0.123. The version is LOWER than the old version. The vendor who wrote this dll decided to go backwards with the file version number. This is not a decision I can change.
How do I get WiX to always install this file?
The RemoveExistingProducts action is scheduled after the InstallFinalize action and also cannot be changed.
InstallShield had an 'always overwrite' flag but I don't think I can mimic this without changing the behavior of all files via a compiler switch. I do not want this. I just want to update THIS ONE file.
I have also tried
<RemoveFile Id="foo.dll" On="install" Name="foo.dll" />
But this did not work either. I end up getting 'Error 2753 The file foo.dll is not marked for installation' later.
It is really crazy this post is 10 years old and we also have this problem. The other approaches did not work for us.
How to solve it:
All files which should be copied regardless of their version, must be in their own component
Component element must have a unique Guid, not a *
Set KeyPath to no in the inner File element
Example:
<Component Id="cmpExample" Guid="{5ABE7229-C247-4CBA-B8DE-2C4968CD103E}" >
<File Id="fileExample" KeyPath="no" Source="$(var.TargetDir)\SomeExample.dll" />
</Component>
I would recommend to aggregate all those component elements in a component group. And furthermore you can use XML Transformation to get rid of those files if you use heat.exe to harvest all your files.
With this solution you can copy the file, even if the installed file version is higher. And it still works as expected when a higher file version will be installed with your upgrade.
This isn't easy because it is against the standard behaviour of MSI-packages. When compiling, you have to set supress-file-options with -sf in light.exe. Then there are no file-informations from your files read. You can set DefaultVersion this version will be used.
I have also used RemoveFile in a solution, but i can say that it works. I have add it in same componente where i add the file.
<Component>
<File DiskId="1" Id="fooDLL" Name="foo.dll" Vital="yes"
DefaultVersion="$(var.MAJORVERSION).$(var.MINORVERSION).$(var.BUILDVERSION)"
DefaultLanguage="0"></File>
<RemoveFile Id='RemoveOldDLL' On='install' Name='foo.dll'/>
</Componente>
This is not a clean way, but to remove an old version it works for me.
I answered a similar question a while back:
Forcing an upgrade of a file that is modified during its initial installation
I think I would use a companion file to solve this problem, but you might get validation errors since the file in question is a dll and hence considered an executable. I believe it would still work, and reliably so.
Annotation
Force always overwrite in Light.exe output with the "InstallShield trick":
XPath="/wixOutput/table[#name='File']/row/field[5]" InnerText=„65535.0.0.0“
One thing that could be worth trying is to set RemoveExistingProducts real early in the sequence. The MSI should then remove the old program first, then install the upgrade. This will solve your issue. e.g.
<InstallExecuteSequence>
<RemoveExistingProducts After="CostFinalize" />
</InstallExecuteSequence>