How to set permissions for directory - wix

I followed the SO link to add permission to a folder. However if I would like to set permission for directory, what can I do?
For example, in the link it has the following code:
<DirectoryRef Id="ProgramFilesFolder">
<Directory Id="PHPFolder" Name="PHP">
<Component Id="PHP_comp" DiskId="1" Guid="*">
<CreateFolder>
<Permission User="Everyone" GenericAll="yes" />
</CreateFolder>
How can I set permission for directory PHPFolder?

Maybe try with a CreateFolder Element:
<Directory Id="INSTALLFOLDER" Name="Myfolder">
<Component Feature="ProductFeature">
<File Source="TestFile.exe" />
<CreateFolder>
<Permission User="Everyone" GenericAll="yes"/>
</CreateFolder>
</Component>
</Directory>
General Tip: Try to pillage github.com for snippets when you are stuck. Random Sample.
Further Links:
Several ways to apply permissions in WiX (mid page)
How to deny folder permission to Users with wix installer
System.UnauthorizedAccessException while running .exe under program files

Related

How do I tell wix to install a file in a directory set in a property?

I want to do the following where XLSTART is defined as:
<CustomAction Id="AssignXLSTART" Return="check" Execute="firstSequence" Directory ='XLSTART' Value='[AppDataFolder]\Microsoft\Excel\XLSTART'>
</CustomAction>
And then I have a subsequent CustomAction that calls some C# code that may change this value.
And then in the list of files to install I have:
<Directory Id="XlStartFolderId" Name="[XLSTART]">
<Component Id="ExcelMacro_xla" Guid="26D21093-B617-4fb8-A5E7-016493D46055" DiskId="1">
<File Id="ExcelXLA" Name="AutoTagExcelMacro.xlam" ShortName="XLMacro.xla" Source="$(var.srcFolder)\AutoTagExcelMacro.xlam"/>
</Component>
</Directory>
But the above puts it in the INSTALLDIR[XLSTART]. How do I get it to read this as a property?
You should be able to install to the userprofile directory you refer to like this:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="LocalAppDataFolder">
<Directory Id="Microsoft" Name="Microsoft">
<Directory Id="Excel" Name="Excel">
<Directory Id="XLSTART" Name="XLSTART">
<Component Id="ExcelAddIn" Feature="MyFeature" Guid="{11111-1111-GUID-HERE-YOURGUIDHERE}">
<File Source="C:\SourceFiles\MyAddin.xla" />
<RemoveFolder Id="Microsoft" On="uninstall" Directory="Microsoft" />
<RemoveFolder Id="Excel" On="uninstall" Directory="Excel" />
<RemoveFolder Id="XLSTART" On="uninstall" Directory="XLSTART" />
<RegistryValue Root="HKCU" Key="Software\MySoftware" Name="installed" Type="integer" Value="1" KeyPath="yes" />
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
I would suggest you use the per-machine xlstart folder instead - if it still exists. I am not sure it does. The the addin is loaded for every user on the box on every launch. Generally I prefer this. It has been ages since I looked at this, so this could have changed in newer Office versions - in fact I am sure it has, but the details are unclear to me.
System Folder Properties: There are a number of System Folder Properties that can be used in MSI files to specify installation location - LocalAppDataFolder is just one of them: https://learn.microsoft.com/en-us/windows/win32/msi/property-reference#system-folder-properties
Figured it out. You need to install to the INSTALLDIR and then use CopyFile
<!-- place it in C:\Program Files (x86)\Microsoft Office\Root\Office16\XLSTART\ -->
<Component Id="ExcelMacro_xla" Guid="26D21093-B617-4fb8-A5E7-016493D46055" DiskId="1">
<File Id="ExcelXLA" Name="AutoTagExcelMacro.xlam" ShortName="XLMacro.xla" Source="$(var.srcFolder)\AutoTagExcelMacro.xlam">
<CopyFile Id='CopyXlMacro' DestinationProperty='XLPATH' DestinationName='AutoTagExcelMacro.xlam'/>
</File>
</Component>

Add resource files in wix installer

I have created a multi lingual app that uses 2 diferent resource files to manage the UI language, so when I build and execute my program, in my bin directory I have my app files and two folders, en-GB and pt-PT.
I am now trying to create a installer with Wix, for that I am defining the following directories:
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="App" >
<Directory Id="LOCALEEN" Name="en-GB"/>
<Directory Id="LOCALEPT" Name="pt-PT"/>
</Directory>
</Directory>
</Directory>
</Fragment>
And then, I define the following components:
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="App.resources.en.GB.dll" Guid="...">
<CreateFolder />
<File Id="App.resources.en.GB.dll" Name="App.resources.dll" Source="$(var.App.App_TargetDir)en-GB\App.resources.dll" />
</Component>
<Component Id="App.resources.pt.PT.dll" Guid="...">
<CreateFolder />
<File Id="App.resources.pt.PT.dll" Name="App.resources.dll" Source="$(var.App.App_TargetDir)pt-PT\App.resources.dll" />
</Component>
... Other components...
</ComponentGroup>
</Fragment>
When I rebuild my solution I get the following error:
'App.resources.dll' is installed in '[ProgramFilesFolder]\App\' by two
different components on an LFN system: 'App.resources.en.GB.dll' and
'App.resources.pt.PT.dll'. This breaks component reference counting.
I understand the problem, both resources dll are being copied to the installation folder, and not to the specific resources file... But I don't know how to solve it. Anyone can give any hints on how to solve this?
Just reference the directory where you want your components eg. Directory="LOCALEEN". There is no need to specify <CreateFolder />
I also recomend to maintain some kind of naming convention. Your Components and Fils have the same id. See https://stackoverflow.com/a/1801464/4634044. So this should do what you expect:
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="C_EnglishLocale" Guid="..." Directory="LOCALEEN">
<File Id="Fi_EnglishLocale" Name="App.resources.dll" Source="$(var.App.App_TargetDir)en-GB\App.resources.dll" />
</Component>
<Component Id="C_PolnishLocale" Guid="..." Directory="LOCALEPT">
<File Id="Fi_PolnishLocale" Name="App.resources.dll" Source="$(var.App.App_TargetDir)pt-PT\App.resources.dll" />
</Component>
</ComponentGroup>
</Fragment>

WIX Writing user data into config file

I would like to ask a WiX installer question. I created a working installer that does many things already. I still need to ask the user for some specific information (the GUI is already done), and write it into a config file.
From this snippet, I think I could use the INSTALLFOLDER global variable.
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="IISROOT" Name='WebDir'>
<Directory Id="INSTALLFOLDER" Name="IVRDesigner">
</Directory>
</Directory>
</Directory>
This is the part, when I want to use that. This code is taken from a tutorial, should work well, if the source tag is filled properly. The ..\src\Web.config is just a dummy, so the code can compile. The default installed path for the web.config file will be C:\inetpub\wwwroot\myfolder, but the user can change this during the installation.
The question is: how could I use the global variable here, or what kind of solution, do you recommend?
Thanks in advance.
<Component Id="ConfigureWebConfig" Guid="*">
<File Id="Web.config" Name="MyConfigfile" Vital="yes" KeyPath="yes"
Source="..\src\Web.config" />
<util:XmlFile Id="AppConfigSetConnStr" Action="setValue"
Permanent="yes" File="[#Web.config]"
ElementPath="/configuration/connectionStrings/add[\[]#name='GeoIVRDesignerEntities'[\]]" Name="connectionString"
Value="data source=[DBSERVER];" />
</Component>
Under the Product tag I would add the properties that I want to be able to change in the config file like this:
<Property Id="BUILDRAN" Value="INSTALLER"/>
<Property Id="EMAIL_RECEIPIANT" Value="thisisnotme#notthere.com" />
Create the Fragment for the Directory Structure
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir" >
<Directory Id="BasicDir" Name="Dev_Home">
<Directory Id="BasicDirSuite" Name="TEST">
<Directory Id="INSTALLFOLDER" Name="DesignPatterns" />
</Directory>
</Directory>
</Directory>
</Fragment>
Declare another Fragment for the transformation of the config file
<util:XmlFile Id="AppConfigSetBuildRan" Action="setValue" Permanent="yes" File="[#App.config]"
ElementPath="/configuration/applicationSettings/MyApp.Properties.Settings/setting[\[]#name='BuildRan'[\]]/value"
Value="[BUILDRAN]" />
<util:XmlFile Id="AppConfigSetEmail" Action="setValue" Permanent="yes" File="[#App.config]"
ElementPath="/configuration/applicationSettings/MyApp.Properties.Settings/setting[\[]#name='TestValue'[\]]/value"
Value="[EMAIL_RECEIPIANT]" />
If you want you can create your own custom dialog to let the End user enter values for the properties [BUILDRAN] && [EMAIL_RECEIPIANT], or you could use the command line and set the properties with parameters
msiexec /i My.msi BUILDRAN=SuperDebug EMAIL_RECEIPIANT=you#home.com

WIX 3.8 installer: Add files to a pre-existing folder

How would I install files directly into a pre-existing folder on the user's computer? All documentation I read only explains creating a custom INSTALLDIR.
Eg. c:\ProgramFiles(x86)\ExampleFolderA\ExampleFolderB\InstalledFile.exe
You should first define the directory structure:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="ExampleFolderAId" Name="ExampleFolderA">
<Directory Id="ExampleFolderBId" Name="ExampleFolderB" />
</Directory>
</Directory>
</Directory>
Note that the definition above does NOT create directories when the installation runs. In order for the directories to be actually "created" you have to either place files there (using Component elements), or explicitly state that the directory is empty.
Something like this:
<DirectoryRef Id="ExampleFolderAId">
<Component Id="SampleComponent" Guid="GUID-GOES-HERE">
<File Id="SampleFile" Source="C:\readme.txt" KeyPath="yes" />
</Component>
</DirectoryRef>
or
<DirectoryRef Id="ExampleFolderBId">
<Component Id="EmptyFolderComponent" Guid="GUID-GOES-HERE">
<CreateFolder />
</Component>
</DirectoryRef>
Hope you get the idea.

Wix creates an application data directory which is read only

I'm creating a folder structure in WiX in the following manner:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="MyApp">
</Directory>
</Directory>
<Directory Id="CommonAppDataFolder">
<Directory Id="CONFIGFOLDER" Name="MyAppConfig">
<Directory Id="Configdir1" Name="Configdir1">
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="MyApp"/>
</Directory>
</Directory>
I'm then populating these directories later on using Component tags like this:
<ComponentGroup Id="ProductConfiguration" Directory="CONFIGFOLDER">
<Component Id="ConfigFile1" Guid="*">
<File Id="ConfigFile1.xml" Name="ConfigFile1.xml" Source="..\Configuration\ConfigFile1.xml" Vital="yes" KeyPath="yes" DiskId="1"/>
</Component>
<Component Id="ConfigFile2" Guid="*">
<File Id="ConfigFile2.xml" Name="ConfigFile2.xml" Source="..\Configuration\ConfigFile2.xml" Vital="yes" KeyPath="yes" DiskId="1"/>
</Component>
<Component Id="ConfigFile3" Guid="*">
<File Id="ConfigFile3.xml" Name="ConfigFile3.xml" Source="..\Configuration\ConfigFile3.xml" Vital="yes" KeyPath="yes" DiskId="1"/>
</Component>
</ComponentGroup>
My problem is this: WiX creates the Configuration directory (CommonAppDataFolder/MyAppConfig) as a read only folder. Since it's full of application data, users need to be able to modify its contents without having admin privileges. I can create other folders in the CommonAppDataFolder programmatically, which do not require admin privileges.
How do I set the write privileges for my folder in WiX?
Turns out that the answer looks something like this:
<Directory Id="MYFOLDER" Name="My folder name">
<Component Id="MyFolderComponent" Guid="*">
<CreateFolder Directory="MYFOLDER">
<Permission User="Everyone" GenericAll="yes" />
</CreateFolder>
</Component>
</Directory>
CommonAppDataFolder is a per-machine store and so requires elevated privileges to write to. If you want a per-user store, use the AppDataFolder or LocalAppDataFolder directory properties instead.