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>
Related
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 want to create folder in specific location that is different from TARGETDIR.
I'm installing to TARGETDIR located at C:\Program Files\Company\Product.
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder" Name="PFiles">
<Directory Id="COMPANYDIR" Name="Company">
<Directory Id="PRODUCTDIR" Name="Product">
<Component Id="libraries" Guid="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX" Win64="yes">
<File Id="library.dll" Name="library.dll" Source="library.dll" />
</Component>
<Directory Id="example" Name="example">
<Component Id="example" Guid="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX" Win64="yes">
<File Id="EXAMPLE.EXE" Name="example.exe" Source="example.exe" />
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
</Directory>
Using this code will create folder C:\Program Files\Company\Product\example.
My goal is to create folders for example at D:\Product\logs. How can I achieve that using WixEdit?
I have built a WiX installer for an application and in it I need to copy some files to a specific folder on the "C:" drive. I originally coded my directories like this:
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="MyCompanyInstall" Name="MyCompany">
<Directory Id="INSTALLFOLDER" Name="$(var.ProductName)" />
</Directory>
</Directory>
<Directory Id="MYCOMPANYROOT" Name="MyCompany" FileSource="[WindowsVolume]\MyCompany">
<Directory Id="MYCOMPANYMYSPECIALFOLDERDATAFOLDER" Name="MySpecialFolder">
<Directory Id="MYCOMPANYMYSPECIALFOLDERTRENDINGFOLDER" Name="Trending"/>
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="MyCompanyProgramMenu" Name="MyCompany">
<Directory Id="ProgramMenuDir" Name="$(var.ProductName)"/>
</Directory>
</Directory>
<Directory Id="DesktopFolder"/>
</Directory>
</Fragment>
<Fragment>
<DirectoryRef Id="MYCOMPANYROOT">
<Component Id="CreateDirectories" Guid="60D9E460-89C8-42D2-8581-D858785A1817">
<CreateFolder Directory="MYCOMPANYROOT"/>
<CreateFolder Directory="MYCOMPANYMYPRODUCTDATAFOLDER"/>
<CreateFolder Directory="MYCOMPANYMYPRODUCTTRENDINGFOLDER"/>
</Component>
</DirectoryRef>
<!-- trimmed -->
<DirectoryRef Id="MYCOMPANYMYPRODUCTDATAFOLDER">
<Component Id="FirstFile.xml" Guid="E9879B51-1C74-47BF-A475-3B77D66297E2">
<File Id="FirstFile.xml" Source="$(var.TargetDir)FirstFile.xml" KeyPath="yes" Checksum="yes"/>
</Component>
<Component Id="SecondFile.xml" Guid="69A86F79-4596-4714-9FE7-628882ADA303">
<File Id="SecondFile.xml" Source="$(var.TargetDir)SecondFile.xml" KeyPath="yes" Checksum="yes"/>
</Component>
<Component Id="MyCompanyMyProductHelp.pdf" Guid="D2D3CDF1-61FA-4021-8F56-F23770580AA0">
<File Id="MyCompanyMyProductHelp.pdf" Source="$(var.TargetDir)Documents\MyCompany My Product Help.pdf" KeyPath="yes" Checksum="yes"/>
</Component>
</DirectoryRef>
<!-- trimmed -->
<Icon Id="$(var.ProductName)Icon.EXE" SourceFile="$(var.TargetPath)"/>
</Fragment>
But on one computer in the office I kept getting the case that the files meant for "C:\MyCompany\MySpecialFolder\" were not copied. I then tried to hard code the "C:" drive like so:
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="MyCompanyInstall" Name="MyCompany">
<Directory Id="INSTALLFOLDER" Name="$(var.ProductName)" />
</Directory>
</Directory>
<Directory Id="MYCOMPANYROOT" Name="MyCompany" FileSource="C:\MyCompany">
<Directory Id="MYCOMPANYMYSPECIALFOLDERDATAFOLDER" Name="MySpecialFolder">
<Directory Id="MYCOMPANYMYSPECIALFOLDERTRENDINGFOLDER" Name="Trending"/>
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="MyCompanyProgramMenu" Name="MyCompany">
<Directory Id="ProgramMenuDir" Name="$(var.ProductName)"/>
</Directory>
</Directory>
<Directory Id="DesktopFolder"/>
</Directory>
</Fragment>
<Fragment>
<DirectoryRef Id="MYCOMPANYROOT">
<Component Id="CreateDirectories" Guid="60D9E460-89C8-42D2-8581-D858785A1817">
<CreateFolder Directory="MYCOMPANYROOT"/>
<CreateFolder Directory="MYCOMPANYMYPRODUCTDATAFOLDER"/>
<CreateFolder Directory="MYCOMPANYMYPRODUCTTRENDINGFOLDER"/>
</Component>
</DirectoryRef>
<!-- trimmed -->
<DirectoryRef Id="MYCOMPANYMYPRODUCTDATAFOLDER">
<Component Id="FirstFile.xml" Guid="E9879B51-1C74-47BF-A475-3B77D66297E2">
<File Id="FirstFile.xml" Source="$(var.TargetDir)FirstFile.xml" KeyPath="yes" Checksum="yes"/>
</Component>
<Component Id="SecondFile.xml" Guid="69A86F79-4596-4714-9FE7-628882ADA303">
<File Id="SecondFile.xml" Source="$(var.TargetDir)SecondFile.xml" KeyPath="yes" Checksum="yes"/>
</Component>
<Component Id="MyCompanyMyProductHelp.pdf" Guid="D2D3CDF1-61FA-4021-8F56-F23770580AA0">
<File Id="MyCompanyMyProductHelp.pdf" Source="$(var.TargetDir)Documents\MyCompany My Product Help.pdf" KeyPath="yes" Checksum="yes"/>
</Component>
</DirectoryRef>
<!-- trimmed -->
<Icon Id="$(var.ProductName)Icon.EXE" SourceFile="$(var.TargetPath)"/>
</Fragment>
But I got the same results.
Does anyone know why this won't work on only one machine?
Well I stumbled upon a fix. I don't understand why this fixes it, but it now works.
The key was to add the line:
<SetDirectory Id="MYCOMPANYROOT" Value="[WindowsVolume]MyCompany"/>
I would have thought that the "FileSource" attribute in the "Directory" tag would have done the trick, but alas it didn't.
<Directory Id="MYCOMPANYROOT" Name="MyCompany" FileSource="[WindowsVolume]MyCompany">
I don't really understand why I needed this. If someone could explain, I would appreciate it.
Code follows:
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="MyCompanyInstall" Name="MyCompany">
<Directory Id="INSTALLFOLDER" Name="$(var.ProductName)" />
</Directory>
</Directory>
<Directory Id="MYCOMPANYROOT" Name="MyCompany" FileSource="[WindowsVolume]MyCompany">
<Directory Id="MYCOMPANYMYSPECIALFOLDERDATAFOLDER" Name="MySpecialFolder">
<Directory Id="MYCOMPANYMYSPECIALFOLDERTRENDINGFOLDER" Name="Trending"/>
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="MyCompanyProgramMenu" Name="MyCompany">
<Directory Id="ProgramMenuDir" Name="$(var.ProductName)"/>
</Directory>
</Directory>
<Directory Id="DesktopFolder"/>
</Directory>
</Fragment>
<Fragment>
<!-- New line -->
<SetDirectory Id="MYCOMPANYROOT" Value="[WindowsVolume]MyCompany"/>
<!-- -->
<DirectoryRef Id="MYCOMPANYROOT">
<Component Id="CreateDirectories" Guid="60D9E460-89C8-42D2-8581-D858785A1817">
<CreateFolder Directory="MYCOMPANYROOT"/>
<CreateFolder Directory="MYCOMPANYMYPRODUCTDATAFOLDER"/>
<CreateFolder Directory="MYCOMPANYMYPRODUCTTRENDINGFOLDER"/>
</Component>
</DirectoryRef>
<!-- trimmed -->
<DirectoryRef Id="MYCOMPANYMYPRODUCTDATAFOLDER">
<Component Id="FirstFile.xml" Guid="E9879B51-1C74-47BF-A475-3B77D66297E2">
<File Id="FirstFile.xml" Source="$(var.TargetDir)FirstFile.xml" KeyPath="yes" Checksum="yes"/>
</Component>
<Component Id="SecondFile.xml" Guid="69A86F79-4596-4714-9FE7-628882ADA303">
<File Id="SecondFile.xml" Source="$(var.TargetDir)SecondFile.xml" KeyPath="yes" Checksum="yes"/>
</Component>
<Component Id="MyCompanyMyProductHelp.pdf" Guid="D2D3CDF1-61FA-4021-8F56-F23770580AA0">
<File Id="MyCompanyMyProductHelp.pdf" Source="$(var.TargetDir)Documents\MyCompany My Product Help.pdf" KeyPath="yes" Checksum="yes"/>
</Component>
</DirectoryRef>
<!-- trimmed -->
<Icon Id="$(var.ProductName)Icon.EXE" SourceFile="$(var.TargetPath)"/>
</Fragment>
Have a read up on TARGETDIR, you will see that this links to ROOTDRIVE, which states:
If ROOTDRIVE is not set at a command line or authored into the
Property table, the installer sets this property. During an
administrative installation the installer sets ROOTDRIVE to the first
connected network drive it finds that can be written to. If it is not
an administrative installation, or if the installer can find no
network drives, the installer sets ROOTDRIVE to the local drive that
can be written to having the most free space.
So I suspect that on the single machine which you are having issues with, that it has another local drive with more space than c:
I had a similar problem.
On one of our machines WIX installed on E drive (flash disk) instead of C dive.
I have come across this answer which solve my problem: https://stackoverflow.com/a/8591139/1891969
Just replace the TARGETDIR value with "C:\".
<InstallExecuteSequence>
<Custom Action="FormatTargetDirectory" After="CostFinalize">NOT Installed</Custom>
</InstallExecuteSequence>
<CustomAction Directory="TARGETDIR" Value="[DRIVE_NAMES]" Id="FormatTargetDirectory"/>
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.