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.
Related
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.
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
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
I am trying to create a custom Wix Extension which copies a file with come preparations.
How can I achieve the similar procedure to File Element when all you need is specify file source and the file gets stored in the MSI tables?
<File Id="Some.dll"
Source="files\Some.dll"
KeyPath="yes" />
As a workaround I can use Binary Element, but I want to have the same elegant style as Wix Toolset.
You'll want to add your file to the Binary table of the MSI. This page here shows how to do this and then utilize it while installing.
The following doesn't compile, but how can I get the equivalent functionality of [MYDIR]?
<Component Id="MyComponent" Guid="MY_GUID" KeyPath="yes" Directory="[MYDIR]">
<File Source="MyFile.dll" Name="MyFile.dll"/>
</Component>
(I'm trying to put the file MyFile.dll into a directory whose path is determined when the installer is actually run.)
The Directory attribute must correspond to a <Directory> tag somewhere in your installer. You can set that directory to the value of a property that gets set at runtime. A good example of this is using the WixUI_InstallDir to ask the user where they want to install an application.
Here is an example of usage: https://wixtoolset.org//documentation/manual/v3/wixui/dialog_reference/wixui_installdir.html