Setting permissions for folder and all sub folders in Wix - permissions

All of the relevant links seem to assume that I am using DirectoryRefs and CreateFolder within these. When I run heat I get a .wxs file that consists of <Directory> tags and <Component> tags but not DirectoryRefs. I'd rather not rewrite the whole 5000 line file by hand. Is there a way to edit folder permissions for these tags?

You don't have to rewrite the heat auto-generated fragment. You can reference the directories defined there with the DirectoryRef elements in another fragment.
Most likely you'd like to do the following:
First, change the ID of the root directory in a heat-generated fragment. This can be done by a -dr <DirectoryName> command line switch of heat.exe. Choose a name for the DirectoryName, e.g. MY_ROOT_FOLDER. This is necessary for a convenient reference to that directory in a DirectoryRef element
Next, author a special component (in a different fragment), which is to contain the permissions functionality only. Something like this:
<DirectoryRef Id="MY_ROOT_FOLDER">
<Component DiskId="1" Id="Permissions" Guid="GUID-GOES-HERE">
<Condition>...</Condition>
<CreateFolder>
<util:PermissionEx GenericAll="yes" User="[LOGON_ACCOUNT]" Domain="[LOGON_DOMAIN]" />
</CreateFolder>
</Component>
</DirectoryRef>
Finally, don't forget to include this component to a feature of your choice.
Note, that by default the <util:PermissionEx> element appends permissions to the folder in question and all its descendants.

Related

SourceProperty as Nested Directory in CopyFile

I want to copy two file from existing location to new location using WIX Installer.
INSTALLDIR and Destination Directory are already defined. And In SourceProperty for first I want to use INSTALLDIR\P\X\Y and In second I want to use INSTALLDIR\Q\X\Y
<ComponentGroup Id="aYML" Directory="INSTALLDIR">
<Component Id="CopyaYML" Guid="" Transitive="yes">
<CopyFile Id ="aYMLcopy" SourceProperty="INSTALLDIR\P\X\Y" SourceName="A.yml" DestinationProperty="Destination"/>
<CreateFolder/>
</Component>
</ComponentGroup>
<ComponentGroup Id="bYML" Directory="INSTALLDIR">
<Component Id="CopybYML" Guid="" Transitive="yes">
<CopyFile Id ="bYMLcopy" SourceProperty="INSTALLDIR\Q\X\Y" SourceName="B.yml" DestinationProperty="Destination"/>
<CreateFolder/>
</Component>
</ComponentGroup>
As \ is not allowed in WIX how to achieve this?
It has to be a property name, which has a limited character set of letters, numbers, and underscores. You could use a SetProperty custom action (type 19) to format a value using the directory ID and the file name, or even the [#fileId] property format, though that's not reliable in older versions of Windows Installer.
Before InstallFiles but after CostFinalize, you could do something like this:
<SetProperty Id="AYMLPATH" Before="InstallFiles" Sequence="execute" value="[ParentDirectoryId]A.yml" />
Though, it may be easier to just use the SourceDirectory attribute and specify the directory ID.
Copying files, though, can cause issues for some servicing scenarios. For example, if you copy files in a patch, the changes can't be rolled back. If the files are small, just duplicate the files. There are even tricks to duplicating the file records, but keeping a single file blob in a CAB, but is outside the scope of this answer.

WiX: Component, Directory and CreateFolder tags, how to write Components

i'm attempting to follow tutorials and guides to learn WiX and i'm not really understanding how all of these basic elements come together. i'm attempting to package just a folder containing JRE6. i'm generating the WiX XML with a little parser, but i'm not sure how this is actually supposed to look.
the goal is basically to package the entire JRE6 in the installation as a single Component. i can't figure out the proper structure. when i try this:
<Directory Id="jre6_dir" Name="jre6">
<Directory Id="dir_jre_jre6bin" Name="bin">
<File Id="binawt.dll" Name="awt.dll" />
<File Id="binaxbridge.dll" Name="axbridge.dll" />
<Directory Id="dir_jre_binclient" Name="client">
<File Id="clientclasses.jsa" Name="classes.jsa" />
<File Id="clientjvm.dll" Name="jvm.dll" />
<File Id="clientXusage.txt" Name="Xusage.txt" />
</Directory>
etc...
the compiler tells me that i can't place a File tag within a Directory tag.
so i have tried:
placing File tags inside Directory tags.
placing File tags inside CreateFolder tags.
placing Directory tags inside the Component tag.
none of this works. i'm just not understanding the very basics of how WiX works and how i should create a component like this. i just want to be able to call the contents of the JRE6 directory its own Component in the installation. how do i do this?

Remove a folder if registry entry is not present

I need to remove a folder if a certain folder path in registry doesn't exist. I wrote the below code but it doesn't work. The folder is not deleted and nothing about a condition check in the logs as well.
<Property Id="UPDATERSERVICEFOLDER">
<RegistrySearch Key="SYSTEM\CurrentControlSet\Services\UpdaterService\Parameters" Root="HKLM" Type="raw" Id="UpdateDirectoryRegistrySearch" Name="UpdaterServicePath" />
</Property>
<Component Id="RemoveFolder" Directory="MyProgramDir" Guid="*" >
<RemoveFolder Id="MosquittoInstallDir" On="uninstall"/>
<Condition><![CDATA[UPDATERSERVICEFOLDER]]></Condition>
</Component>
What am I doing wrong here? Any help would be much appreciated.
RemoveFolder won't remove the folder if there is anything in the folder when the component is processed. The issue you probably have is that this component gets processed before all the other components that represent something in that folder are processed or there are files that are not part of your install in this folder.
I don't know if there is a way to force a component to be processed last. An alternative you can try is Util:RemoveFolderEx. It is very important to note the remark at the bottom of this page. What this is basically saying is that you can't use a directory property to define the path to remove; you can't use [MyProgramDir] as the Property. The suggested way to implement the Property for this Util:RemoveFolderEx is to use a registry search to get the correct path then use that property set by the registry search.

Install component conditionally in Wix

We have a Wix project for our Installer. Is it possible to check if a file exists?
Basically, for some of our config files, we want to pass in the path of the file that is actually not present in our installer script but pass in the path of the file to a public property on command line.
In this case we want the config file component to use this passed in config file during the installation instead of the default config file.
Is this possible?
I have tried something like this:
<?if FileExist([PORTALCONFIGPATH])?>
<File Id='webConfig' Name='web.config' DiskId='1' Source='[PORTALCONFIGPATH]' KeyPath='yes'/>
<?else?>
<File Id='webConfig' Name='web.config' DiskId='1' Source='web.config' KeyPath='yes'/>
<?endif?>
Someway to check that the passed in file name exists then install the passed in file otherwise use the default file.
The WiX FileSearch, DirectorySearch, Condition, and CopyFile elements are what you are looking to use. Create a property, when executing the msi if the property is set then the DirectorySearch and FileSearch elements will look in the path for that property, setting another property (MYFILEEXISTS for example) then if MYFILEEXISTS CopyFile will run with the path.

Using Wix how can I deploy one of several web.config files while installing an ASP.net web application

I'm using Wix 3.6 beta from the command line, not as VS projects. I have a web application that is harvested with heat as a directory. This works. I'm using web.config transforms to manage each of the target environment web.config files. These are output with msbuild, this works and keeps things visible in Visual Studio and source control.
I've hit a problem deploying one of the several web.config files which I am manually including in product.wxs as components with conditions. I was expecting to include all components as deployable features and let the conditions select just one as active. For example:
<DirectoryRef Id="wwwroot">
<Component Id="setup_a" Guid="some_guid" >
<File Source="$(var.ConfigSourceDir)\setup_a\web.config" />
<Condition>ENVIRON = setup_a</Condition>
</Component>
<Component Id="setup_b" Guid="some_guid" >
<File Source="$(var.ConfigSourceDir)\setup_b\web.config" />
<Condition>ENVIRON = setup_b</Condition>
</Component>
This didn't create any file renaming, moving or deleting issues, but has the very fundamental problem that multiple web.config files are mapped to the same destination and this gives me a light error of "Product.wxs(xxx) : error LGHT0091 : Duplicate symbol 'File:web.config' found. This typically means that an Id is duplicated. Check to make sure all your identifiers of a given type (File, Component, Feature) are unique."
An alternative approach was to use different named .config files and rename/move one to be the web.config, so something like:
<DirectoryRef Id="wwwroot">
<Component Id="setup_a" Guid="some_guid" >
<File Id="setup_a.config" Source="$(var.ConfigSourceDir)\setup_a.config" />
<CopyFile Id="moveit" SourceDirectory="wwwroot" SourceName="setup_a.config" DestinationDirectory="wwwroot" DestinationName="web.config" />
</Component>
This doesn't throw an error, bot the CopyFile command does nothing at all. I just get setup_a.config in the wwwroot folder.
If I nest the CopyFile inside the File, the copy action then works:
<DirectoryRef Id="wwwroot">
<Component Id="setup_a" Guid="some_guid" >
<File Id="setup_a.config" Source="$(var.ConfigSourceDir)\setup_a.config" >
<CopyFile Id="moveit" DestinationName="web.config"/>
</File>
</Component>
...but nested CopyFile means I can't add (it's disallowed) the Delete="yes" attribute to create a 'move' action. Instead I'm left with both setup_a.config and web.config in the wwwroot folder. Alternatively, if I add a seperate removefile within the same component element it also does nothing:
<RemoveFile Id="removefile" On="install" Directory="wwwroot" Name="setup_a.config"/>
</Component>
So, I'm hoping for a working example of how handle multiple web.config files in a conditional deployment, that doesn't leave files behind. the destination filename of web.config is fixed by the framework and can't be changed. The different configs are also pre-generated outside of wix using config transforms, this also can't be changed but the generated filenames could be anything.
cheers!
You complicate it too much. This should work:
<Component Id="setup_a" Guid="some_guid" >
<File Name="web.config" Id="config_a" Source="$(var.ConfigSourceDir)\setup_a\web.config" />
<Condition>ENVIRON = setup_a</Condition>
</Component>
<Component Id="setup_b" Guid="some_guid" >
<File Name="web.config" Id="config_b" Source="$(var.ConfigSourceDir)\setup_b\web.config" />
<Condition>ENVIRON = setup_b</Condition>
</Component>
Pay attention to a couple of things here:
the File/#Name is the same - that's the target file name you'd like to have (web.config)
the File/#Id is different for each File in order to avoid the light error you mentioned first
the File/#Source can be anything - it just describes what file to take as a source
In this sample light will still complain with warning LGHT1076, but that's just a warning - it pays your attention that conditions MUST be mutually exclusive to avoid problems.
I usually take a different approach. Rather then placing multiple mutually exclusive files into an installer that are tightly coupled to specific instances I put a generic file in the installer and use XML changes to transform the XML with the variation point data such as connection string and what not.
This allows me to make installers that can be deployed anywhere silently just by passing a few properties and the command line.