Consider I have a WiX Setup Library Project named MyLib.wixproj with 2 files that are shared with different installers. This project has the following (simplified) structure:
MyLib.wxs:
<Wix>
<Fragment>
<Feature Id="MySharedFeature" ...>
<ComponentGroupRef Id="MySharedCompGroup" />
</Feature>
<ComponentGroup Id="MySharedCompGroup" Directory="Directory_SharedFiles">
<Component Id="SharedCompA" Guid="*">
<File Id="SharedFileA Source="$(var.Source)fileA.txt" KeyPath="yes" />
</Component>
<Component Id="SharedCompB" Guid="*">
<File Id="SharedFileB Source="$(var.Source)fileB.txt" KeyPath="yes" />
</Component>
</ComponentGroup>
<Directory Id="Directory_SharedFiles" Name="SharedFiles" />
</Fragment>
</Wix>
One of my installers (Setup Project) references the library this way:
Product.wxs:
<Wix>
<Product>
<FeatureRef Id="MySharedFeature" />
</Product>
</Wix>
Directories.wxs:
<Wix>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLDIR" Name="MyApp">
<!-- Here I want to add a reference to Directory_SharedFiles. -->
<Directory Id="OtherFilesNotShared" Name="MoreFiles">
</Directory>
<Directory>
</Directory>
</Directory>
</Fragment>
<Wix>
Inside the INSTALLDIR directory I want to add a DirectoryRef to Directory_SharedFiles, declared in my shared project. I tried using DirectoryRef but this tag doesn't exist as a child of Directory and it is not clear to me how to use Directory Id="TARGETDIR" inside the shared project, like this:
MyLib.wxs:
<!-- This code does not compile! -->
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="Directory_SharedFiles" Name="SharedFiles" />
</Directory>
</Fragment></Wix>
Is there a way to do this?
Don't nest the DirectoryRef element under a Directory element. Put it directly under the Fragment element. Read more on DirectoryRef.
Build the directory structure in a shared WiX fragment instead of in each product separately.
Related
I want to predefine Subfolders for my ComponentGroups.
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?include Constants.wxi?>
<Fragment>
<ComponentGroup Id="CG.MYLIBRARY" Directory="INSTALLFOLDER">
<Component Id="C.MYLIBRARY" Guid="*">
<File Id="MYLIBRARY" Source="$(var.MyProject.TargetPath)" KeyPath="yes" Checksum="yes" />
</Component>
<ComponentGroupRef Id="CG.DependencyLibrary" />
<!-- Resources -->
<Component Directory="Configuration">
<File Id="MyFile" Source="$(var.MyProject.TargetPath)\Configuration\MyFile" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
So I want MyLibrary.dll at my TopDirectory - where ever is "INSTALLFOLDER",
but I want automaticly MyFile.xml in a Subdirectory named Configuration.
#InstallFolder
-> MyLibrary.dll
-> DependencyLibrary.dll
#InstallFolder\Configuration
--> MyFile.xml
But when I try it like that - i just get:
The Component/#Directory attribute cannot be specified when the
Component element is nested underneath a Directory element. If this
Component is a member of a ComponentGroup where
ComponentGroup/#Directory is set, then the Component/#Directory
attribute should be removed.
Why do I have to remove the Directory-Element, when i just want subfolders under the given Directory in my ComponentGroup?
I don't use this construct (ComponentGroup), but this compiles:
<...>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="SetupProject4">
<Directory Id="Configuration" />
</Directory>
</Directory>
</Directory>
</Fragment>
<...>
<Fragment>
<ComponentGroup Id="ProductComponents">
<Component Id="C.MYLIBRARY" Directory="INSTALLFOLDER">
<File Source="1.txt" />
</Component>
<Component Directory="Configuration">
<File Source="2.txt" />
</Component>
</ComponentGroup>
</Fragment>
I am creating a Wix installer. I want to install my program and another file into the default programs folder, This is working fine.
I also want to put a file in folder "C:\Checkmark\Data", if this folder doesn't exist I want WiX to create it. This folder is not being created, and nothing is happening with the file.
My WiX file:
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes"/>
<Feature Id="ProductFeature" Title="Checkmark" Level="1">
<ComponentGroupRef Id="ProductComponents" />
<ComponentGroupRef Id="ProductData"/>
</Feature>
<!--<UIRef Id="WixUI_Minimal"/>-->
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="Checkmark" />
</Directory>
<Directory Id="CommonAppDataFolder">
<Directory Id="CHECKMARKFOLDER" Name="Checkmark">
<Directory Id="DATAFOLDER" Name="Data" />
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="cmp_Checkmark.exe" Guid="B67B6527-C685-417F-A749-C8B908DF6AEF">
<File Id="fil_Checkmark.exe" KeyPath="yes" Source="C:\WPF test Projects\Checkmark\Checkmark\bin\Release\Checkmark.exe"/>
</Component>
<!--Overwrites file no matter what-->
<Component Id="cmp_TestDoc.txt" Guid="D2147C11-E2A4-4B78-8195-63788F88B012">
<File Id="fil_TestDoc.txt" KeyPath="yes" Source="C:\WPF test Projects\Checkmark\Checkmark\TestDoc.txt"/>
</Component>
</ComponentGroup>
<ComponentGroup Id="ProductData" Directory="DATAFOLDER">
<!--Does not overwrite File if it exists-->
<Component Id="cmp_KeepDoc.txt" NeverOverwrite="yes" Guid="02B29D8B-813C-4782-A6EC-EB614B218D84">
<File Id="fil_KeepDoc.txt" KeyPath="yes" Source="C:\WPF test Projects\Checkmark\Checkmark\KeepDoc.txt"/>
</Component>
</ComponentGroup>
</Fragment>
Can someone tell me why this folder isn't being created and my file not going in it?
If you want to put data in C:\CheckMark\Data
You could use following directory structure:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="Checkmark" />
</Directory>
<Directory Id="CHECKMARKFOLDER" Name="Checkmark">
<Directory Id="DATAFOLDER" Name="Data" />
</Directory>
</Directory>
But TARGETDIR resolves to drive with maximum freespace.
So If you seriously want to deploy in C Drive,
you should update value of TARGETDIR to "C:\" explicitly.
Also CommonAppDataFolder resolves to another directory depending on host os.
On Windows Vista/7 it resolves to C:\ProgramData.
You should check this link for more info.
https://msdn.microsoft.com/en-us/library/aa367992(v=vs.85).aspx
this is the markup i used to create the directory structure and create sub directories. it does work just fine. it creates the software directory of the c:\ root and creates the sub directories under that. But then i add a new component group called "shortcuts". I want to create a short cut on the start menu and a desktop icon.i am not sure of what to call the id where the ?????? are in the start menu directory. i also get the following error when i build the project.
Error 1 The Component/#Directory attribute was not found; it is required.
it occurs twice. one at this line Component Id="cmpStartMenuShortcut" and one at this line Component Id="cmpDesktopShortcut"
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="WINDOWSVOLUME">
<Directory Id="SoftwareDirectory" Name="UnionAdministrator">
<Directory Id="RuntimeFolder" Name="Runtime" />
<Directory Id="ReportsFolder" Name="Reports" />
<Directory Id="TasksFolder" Name="Tasks" />
<Directory Id="DebugLogsFolder" Name="DebugLogs" />
</Directory>
</Directory>
<Directory Id ="FontsFolder" />
<Directory Id ="???????????r">
<Directory Id="AppStartMenuFolder" Name="Runtime" />
</Directory>
<Directory Id="DesktopFolder" />
</Directory>
<SetDirectory Id="WINDOWSVOLUME" Value="[WindowsVolume]" />
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents">
<Component Id="cmpCreateRuntimeFolder"
Guid="{27D409D8-8D86-4CB0-8165-E30A6E3998EC}"
Directory="RuntimeFolder">
<CreateFolder />
</Component>
<Component Id="cmpCreateReportsFolder"
Guid="{9621003B-0BDC-44D8-B981-C5B9CA76C733}"
Directory="ReportsFolder">
<CreateFolder />
</Component>
<Component Id="cmpCreateTasksFolder"
Guid="{785A0024-16B2-499D-9B67-6BCBB8094C55}"
Directory="TasksFolder">
<CreateFolder />
</Component>
<Component Id="cmpCreateDebugLogsFolder"
Guid="{9C91955B-967A-411D-ACD9-6C6AA15F84E8}"
Directory="DebugLogsFolder">
<CreateFolder />
</Component>
</ComponentGroup>
</Fragment>
<Fragment>
<ComponentGroup Id="Shortcuts">
<Component Id="cmpStartMenuShortcut"
Guid="{2A561F4E-118A-4927-9C29-7FF441B77097}">
<Shortcut Id="StartMenuShortcut"
Name="Union Adminstrator"
Description="Runs UnionAdminstrator"
Directory="AppStartMenuFolder"
Target="[RuntimeFolder]UnionAdministrator.exe" />
</Component>
<Component Id="cmpDesktopShortcut"
Guid="{6A686136-06D9-469B-93BA-076D5F32D46B}">
<Shortcut Id="DesktopShortcut"
Name="Union Adminstrator"
Description="Runs UnionAdminstrator"
Directory="DesktopFolder"
Target="[#FILE_UAEXE] " />
</Component>
</ComponentGroup>
</Fragment>
Give directory for shortcuts.and assign it like you have done for other components.
Also since you cant give shortcut as keypath, you could keep registry in shortcut component as keypath.
I'm a beginner in WIX. I want to create multiple folders inside the main folder, but ending with just one folder. Can someone help me on how to create multiple folders?
<!-- Step 1: Define the directory structure -->
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="APPLICATIONROOTDIRECTORY" Name="TEST">
<Directory Id="HTML" Name="HTML" />
</Directory>
</Directory>
</Directory>
<!-- Step 2: Add files to your installer package -->
<DirectoryRef Id="APPLICATIONROOTDIRECTORY">
<Component Id="NewSHU_TM.exe" Guid="3977B09E-B696-471A-9C29-419301EDF6A0">
<File Id="NewSHU_TM.exe" Source="C:\Program Files\Debug\NewSHU_TM.exe" KeyPath="yes" Checksum="yes"/>
</Component>
</DirectoryRef>
<DirectoryRef Id="HTML">
<Component Id="exec.html" Guid="61D58D90-F9A3-4649-9113-6AD7B1249DE8">
<File Id="exec.html" Source="C:\Program Files\Debug\HTML\exec.html" KeyPath="yes" Checksum="yes"/>
<File Id="exec_001.html" Source="C:\Program Files\Debug\HTML\exec_001.html" KeyPath="no" Checksum="yes"/>
</Component>
</DirectoryRef>
<!-- Step 3: Tell WiX to install the files -->
<Feature Id="MainApplication" Title="Main Application" Level="1">
<ComponentRef Id="NewSHU_TM.exe" />
<ComponentRef Id="exec.html"/>
<!--<ComponentRef Id="documentation.html" />-->
</Feature>
</Product>
You need to nest the directories you want to install to within TARGETDIR:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLDIR" Name="Example">
<Component Id="ApplicationFiles" Guid="12345678-1234-1234-1234-222222222222">
<File Id="ApplicationFile1" Source="example.exe"/>
</Component>
</Directory>
</Directory>
</Directory>
See the source for this sample here:
http://www.codeproject.com/Tips/105638/A-quick-introduction-Create-an-MSI-installer-with
You need to close each "Directory" element. Please notice the endding "/>" in the "TEST" and "HTML" folder below.
The following will create (given you are adding files to these directories) the two folders at the same level under the "Example" folder:
c:\Program Files (x86)\Example\TEST and
c:\Program Files (x86)\Example\HTML
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLDIR" Name="Example">
<Directory Id="ChildFolder1" Name="TEST" />
<Directory Id="ChildFolder2" Name="HTML" />
</Directory>
</Directory>
My requirement is to create a directory in programdata/test/example. How can I do that in wix?
Define the folder like this:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="CommonAppDataFolder">
<Directory Id="TestFolder" Name="test">
<Directory Id="ExampleFolder" Name="example" />
</Directory>
</Directory>
</Directory>
The important part here is the CommonAppDataFolder Id, which is known by Windows installer. You can find the full list of known system folders in the Windows Installer Property Reference.
If you install any files to that folder, it will be created implicitly. If not, you can force it to be created by installing a component like this:
<Component Id="CreateTestFolder" Directory="ExampleFolder" Guid="PUT-RANDOM-GUID-HERE">
<CreateFolder />
</Component>
Under <Product> you can enter:
<DirectoryRef Id="TARGETDIR">
<Directory Id="CommonAppDataFolder">
<Directory Id="CommonAppXXXX" Name="test">
<Directory Id="CommonAppYYYY" Name="example">
<Component Id="CreateProgramDataZZZ" Guid="ABC-ETC">
<CreateFolder />
</Component>
</Directory>
</Directory>
</Directory>
</DirectoryRef>
And reference the component CreateProgramDataZZZ in your feature.
It can also be helpful to set permissions on the directory like this:
<CreateFolder>
<util:PermissionEx User="Users" GenericAll="yes" />
</CreateFolder>
(in place of <CreateFolder />)
this will create folder for you...
<Directory Id="DIR_ID" Name="DIR_NAME">
<Component Guid="GUID" Id="id" KeyPath="no" NeverOverwrite="no" Permanent="no" Location="local">
<CreateFolder>
<util:PermissionEx CreateChild="yes" CreateFile="yes" Delete="yes" Read="yes" ReadAttributes="yes" ReadExtendedAttributes="yes" ReadPermission="yes" Traverse="yes" GenericRead="yes" GenericWrite="yes" User="Everyone" />
</CreateFolder>
</Component>
</Directory>