After successful upgrade of the product, one file were not replaced for unknown reason (MSI log is missing). This is not a DLL file where the problem would probably be version. It is some custom binary file that (important note) during lifetime of older version was manually overwritten with newer file. Is there way to force file replacement?
This is how file node looks like:
<Component Win64="yes" Id="cmpSOMEFILE" Guid="*">
<File Id="filSOMEFILE" KeyPath="yes" Source="SOMEFILE.dll.sig" /></Component>
If you need the file to always be replaced, then how about using a <RemoveFile> in the same component to cleanup the file first.
The RemoveF0iles action should be scheduled before the InstallFiles and the file will be removed and replaced with the newer copy every time.
Refer this:
http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/Using-wix-how-to-always-overwrite-a-file-td6904118.html
Related
When uninstalling my application, I'd like to configure the Wix setup to NOT to remove few files that were added as part of the installation. It seems like the uninstaller removes all the files that were originally installed from the MSI file. How do I do that?
Here are my files which I wish to keep it forever
<Binary Id="RootCABinary" SourceFile="Assets\Certificates\RootCA.cer" />
<Binary Id="SubCABinary" SourceFile="Assets\Certificates\SubCA.cer" />
I have used WixIIsExtension.dll to install these certificates to the windows store.
Overwrite: Is it important that the file never gets overwritten? If so, add
"Never Overwrite" to your component. WiX attribute: NeverOverwrite="yes". Remember to test upgrade scenarios!
Permanent Component: As stated by Pavel, you can set a component permanent:
<Component Permanent="yes">
<File Source="License.rtf" />
</Component>
Blank GUID: Another way to do it is to set a blank component GUID. It essentially means "install and then leave alone". No repair or uninstall should be done (remember to add NeverOverwrite="yes" if the file should never be overwritten):
<Component Guid="" Feature="MainApplication">
<File Source="SubCA.cer" KeyPath="yes" />
</Component>
Read-Only Copy: I sometimes install files to a per-machine path (for example somewhere under program files) and then copy them to a per-user location (somewhere in the user-profile) on application launch, and then do operations on them that entail that the files should not be deleted. This is good in cases where you want to do something that change the files in question (they need to be writable). Then it is good to "untangle" them from deployment concerns (files will not be meddled with by installer operations at all - the installer has no knowledge of them). The original read-only copy installed to program files can be uninstalled though (no longer needed?).
Other approaches: You can also create such files using custom actions during installation (usually text files only), you can download the file in question from your web site on application launch (makes the file easy to manage and update / replace? Vulnerable to connection problems - firewalls, etc...) and the application can create the file using "internal defaults" in the main executable on launch. And there are no doubt further approaches that I can't recall.
Put your binaries in a separate WiX component and make it permanent. Have a look at this thread as well
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.
As the title says, I want to install an external file:
<Component>
<File Source="Application.exe.config" Compressed="no" />
</Component>
and–if the external file is not available–install the default, internal file:
<Component>
<File Source="Application.exe.default.config" Name="Application.exe.config" />
</Component>
So that is guaranteed, that there is always a file installed.
How can I achieve that?
To clarify: By external I do NOT mean a CopyFile-Element. Instead I am talking about a normal WiX-File (as seen in the first Snippet) that is simply not compressed into a cab.
Your code snippet shows the file in the MSI, not external, that's the confusion. If it's external it's not in the WiX or the MSI, you would copy it using a WiX CopyFile element.
I'd be tempted to use a file search to see if the file is present and store that resulting property with the WiX remember property pattern. Make your file component transitive and conditioned on "NOT FILEFOUND", for example, so it doesn't get installed if the external file is found. Then you just need the external file copied if FILEFOUND is set. For this, I would add another transitive component containing only a registry entry (it must contain something) with condition FILEFOUND. Put the WiX CopyFile in this component so it runs when FILEFOUND is set. I think that would do it without writing any code.
I'm in the process of upgrading an old Visual Studio setup project installer to a WiX installer.
I have a problem with the new installer though - it keeps removing a config file that was installed with the old installer.
The component in the .wxs file looks like this:
<Component Id="MyConfig" NeverOverwrite="yes" Permanent="yes">
<File Id="MyApp.exe.config" Name="MyApp.exe.config" />
</Component>
I tried setting the component Id and Guid to the same as they were in the old installer, but then it replaces the existing config file with the new one - which I don't want, as the config file may have been modified since the initial installation.
What I want, is if MyApp.exe.config is already installed it should not be removed or replaced.
Make sure your RemoveExistingProducts is scheduled after InstallExecute, eg: afterInstallExecute. GUID and Keypath of the component need to be the same as they were in your previous installer. MSI will only overwrite the old config file if it's modified date is equal to its create date. If the modified date is after the create date the config file was modified and MSI will not overwrite. You shouldn't need the Permanent attribute, that makes this file leaked on uninstall. Don't use NeverOverwrite either: per the docs this is only for registry.
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>