My WiX (3.10.3.3007) project has 2 different web.config files from, and installed to, 2 different locations. The 2 errors from my build are:
Error ICE30: The target file 'svcenub9.con|Web.config' is installed in '[TARGETDIR]\inetpub\wwwroot\barcode\' by two different components on an LFN system: 'web_config' and 'views_web_config'. This breaks component reference counting.
Error ICE30: The target file 'svcenub9.con|Web.config' is installed in '[TARGETDIR]\inetpub\wwwroot\barcode\' by two different components on an LFN system: 'web_config' and 'views_web_config'. This breaks component reference counting.
The XML in question, and their directories, are:
<Fragment>
<DirectoryRef Id="barcode">
...
<Component Id="web_config" Guid="*">
<File Id="web_config" KeyPath="yes" Source="$(var.buildSrc)\BarcodeIntegrationService\Web.config" />
</Component>
...
<Directory Id="views">
...
<Component Id="views_web_config" Guid="*">
<File Id="views_web_config" KeyPath="yes" Source="$(var.buildSrc)\BarcodeIntegrationService\Views\Web.config" />
</Component>
...
</Directory>
...
</DirectoryRef>
</Fragment>
Since this is an ICE error I do have an MSI generated. When I look there at the Component table I can see that they do indeed have distinct directories.
Is there something in my WiX project that I'm not adding?
The problem is that my Directory elements did not have a Name attribute. In the Directory table the DefaultDir was set to . for all of my directories. Thus the ICE was viewing them as the same directory.
Related
Despite the different Ids and GUIDs the following code refused to compile because the following components have the same name. Setting the Name attribute does the trick, but I don't want libraries to have different names in GAC and install folder.
So far I have circumvented the issue by creating a CustomAction that renames one of the components on install, but this clearly isn't optimal. Is there an out of the box solution?
<ComponentGroup Id="HistoryGroup" Directory="INSTALLFOLDER">
<Component Id="History" Guid="*">
<File Source="$(var.ProjectName.TargetPath)" KeyPath="yes"/>
</Component>
<Component Id="HistoryGAC" Guid="*">
<File Source="$(var.ProjectName.TargetPath)" KeyPath="yes" Assembly=".net"/>
</Component>
</ComponentGroup>
Give both file elements explicit unique Id attributes. For the one going to the GAC install it to another dummy folder that already exists. (Don't worry it won't get installed there, it'll go to the GAC.)
I have a Visual Studio solution with three projects: Core, Application, Setup (WiX). In the setup project I have a separate ComponentGroup for each VS project. These ComponentGroups contain Component for the project output and Components for all its references. For example:
<ComponentGroup Id="ApplicationComponents" Directory="INSTALLFOLDER">
<Component Id="Application" Guid="SOME-GUID-1">
<File Id="ApplicationExe"
Name="$(var.Application.TargetFileName)"
Source="$(var.Application.TargetPath)"
KeyPath="yes" />
</Component>
<Component Id="ApplicationCommonLogging" Guid="SOME-GUID-2">
<File Id="ApplicationCommonLoggingDll"
Name="Common.Logging.dll"
Source="$(var.Application.TargetDir)Common.Logging.dll"
KeyPath="yes" />
</Component>
...
</ComponentGroup>
However, references to Common.Logging.dll exist in both Core and Application projects, so I get an error like this:
ICE30: The target file '138eezlo.dll|Common.Logging.dll' is installed in '[ProgramFilesFolder]\MyApp\' by two different components on an LFN system: 'CoreCommonLogging' and 'ApplicationCommonLogging'. This breaks component reference counting.
Is there something wrong with the structure of components in my setup project? How and where I should declare Components for Common.Logging and other shared references?
I use auto-guids in my <Product> but can't figure out how to use them with <Module>. I only get this error:
The component X has a key file with path 'TARGETDIR\company...'.
Since this path is not rooted in one of the standard directories (like
ProgramFiles Folder), the component does not meet the criteria for
having an automatically generated guid.
Above, company is the value mapped to !(loc.ProductManufacturerFolderName).
The only problem is that's not true. My directories are rooted in ProgramFiles just like my product is and my product works fine:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder">
<Directory Id="MODULEINSTALLLOCATION" Name="!(loc.ProductManufacturerFolderName)">
<Directory Id="Data" Name="Data">
All my component declarations look roughly like this:
<Component Id="DocumentationParty_Business_TestCases_v1xlsx.component" Guid="{YOURGUID-1234-1234-84B3-C595A63428AD}" MultiInstance="yes">
<File Source="../../Development/Integration/SSIS/Documentation/Party_Business_Test Cases_v1.xlsx" KeyPath="yes" Id="DocumentationParty_Business_TestCases_v1xlsx.file" />
</Component>
Breaking it is easy, you only have to change the GUID to * and the above error results. This is broken:
<Component Id="DocumentationParty_Business_TestCases_v1xlsx.component" Guid="*" MultiInstance="yes">
<File Source="../../Development/ClaimsIntegration/SSIS/Documentation/Party_Business_Test Cases_v1.xlsx" KeyPath="yes" Id="DocumentationParty_Business_TestCases_v1xlsx.file" />
</Component>
I have a .wxs file for each directory to which components will be installed. All my component-holding .wxs files have the following structure:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<ComponentGroup Id="DatabasePolicy_Files">
<ComponentRef Id="DatabasePolicyCreateDatabasecmdtemplate.component" />
</ComponentGroup>
<DirectoryRef Id="DataPolicy">
<Component Id="DatabasePolicyCreateDatabasecmdtemplate.component" Guid="*" MultiInstance="yes">
<File Source="../../Development/Database/Policy/CreateDatabase.cmd.template" KeyPath="yes" Id="DatabasePolicyCreateDatabasecmdtemplate.file" />
</Component>
</DirectoryRef>
</Fragment>
</Wix>
Each <ComponentGroup> is included in my master .wxs file through a <ComponentGroupRef>. This works in all my MSI projects and breaks only now that I've started working with merge modules. Also, I've tried commenting out all components except for which matches the above definition and it still breaks on the same error.
What is the problem?
I've had this similar issue myself and based on your error message it's probably the same.
Try adding a ComponentGuidGenerationSeed, that should solve your issue. The ComponentGuidGenerationSeed acts on all subfolders as well so a single one at the top-level is sufficient for all folders.
Example:
<Directory Id="DOCUMENTATIONFOLDER" Name="Documentation" ComponentGuidGenerationSeed="a9f690d3-22b3-488f-bdac-bb665c25933c"/>
http://wixtoolset.org/documentation/manual/v3/xsd/wix/directory.html
The Component Guid Generation Seed is a guid that must be used when a
Component with the generate guid directive ("*") is not rooted in a
standard Windows Installer directory (for example, ProgramFilesFolder
or CommonFilesFolder).
Using WIX, and trying to install two of the same assemblies, one for .Net35 and the other .Net40. I am using two separate components, however WIX is preventing the project from compiling.
<Directory Id="GAC40" Name="GAC">
<Component Id="MyDllServicesModuleGac40Component" Guid="307675AA-8AEC-473B-A78A-FB362CCEDE2A" Win64="yes">
<File Id="MyDllNet40DllGac" Name="MyDll.dll" KeyPath="yes" Assembly=".net" Source="..\MyDll\bin\Net40\MyDll.dll" />
</Component>
</Directory>
<Directory Id="GAC35" Name="GAC">
<Component Id="MyDllServicesModuleGac35Component" Guid="47E6BD1B-25CD-466D-945E-06DCF0F2A269" Win64="yes">
<File Id="MyDllNet35DllGac" Name="MyDll.dll" KeyPath="yes" Assembly=".net" Source="..\MyDll\bin\Net35\MyDll.dll" />
</Component>
</Directory>
The error I receive is:
Error 29 ICE30: The target file 'MyDll.dll' is installed in '[TARGETDIR]\GAC\' by two different components on an SFN system: 'MyDllServicesModuleGac40Component.DDD7D974_FE9C_4BA3_BDD3_A1A3A23F8057' and 'MyDllServicesModuleGac35Component.DDD7D974_FE9C_4BA3_BDD3_A1A3A23F8057'. This breaks component reference counting. D:\PROJECTS\MyDll.Experimental.3.0.0\Project\MyDll\MyDll.Wix.Services\MergeModule.wxs 34 1 MyDll.Wix.Services
The installer should be able to detect that the .Net35 dll gets installed to the GAC at C:\Windows\assembly, while the .Net40 dll gets installed to the GAC at C:\Windows\Microsoft.NET\assembly.
Renaming the DLLs is not an option.
Thanks!
UPDATE
Naturally I came up with a solution just after posting, seem wrapping the components in additional elements allowed me to get this to work. Later I read Tom Blodget's post so that is correct.
<Directory Id="GAC1" Name="GAC">
<Directory Id="GAC40" Name="GAC">
<Component Id="MyDllServicesModuleGac40Component" Guid="307675AA-8AEC-473B-A78A-FB362CCEDE2A" Win64="yes">
<File Id="MyDllNet40DllGac" Name="MyDll.dll" KeyPath="yes" Assembly=".net" Source="..\MyDll\bin\Net40\MyDll.dll" />
</Component>
</Directory>
</Directory>
<Directory Id="GAC2">
<Directory Id="GAC35" Name="GAC">
<Component Id="MyDllServicesModuleGac35Component" Guid="FD74504A-6FE9-488E-9086-9DAD3024B35D" Win64="yes">
<File Id="MyDllNet35DllGac" Name="MyDll.dll" KeyPath="yes" Assembly=".net" Source="..\MyDll\bin\Net35\MyDll.dll" />
</Component>
</Directory>
</Directory>
Well, hope it helps someone!
As explained by Aaron Stebner,
When you use the attribute Assembly=".net" for a file in WiX, it will
create entries in the MsiAssembly and MsiAssemblyName table for this
component and mark it as a GAC component. That means that the file
will only be installed to the GAC by this component, and it will not
install to the directory that the component is a child of. That
directory will only be used by Windows Installer to stage a copy of
that file when creating an administrative install point.
So the directories for your two components must be different since the file names are the same. If nothing else is targeted for those directories, they won't even be created. I put my GAC components under a subdirectory of my install folder:
<Directory Id="tmp_to_GAC" Name="tmp_to_GAC">
You'd need one for each GAC.
Which would be the proper way to install one publisher policy in to the GAC using WIX 3.5?
I tried to do this:
<File
Id="LIBGAC"
Assembly=".net"
KeyPath="yes"
Vital="yes"
Name="ClassLibrary1.dll"
ProcessorArchitecture="msil"
DiskId="1"
Source="..\ClassLibrary1\bin\Release\ClassLibrary1.dll" >
</File>
</Component>
<Component Id="Config" Guid="F089B1AA-B593-4662-9DF4-F47EB9FBA1F4" >
<File
Id="LIBGACPolicy"
Assembly=".net"
KeyPath="yes"
Vital="yes"
Name="Policy.1.0.ClassLibrary1.dll"
DiskId="1"
Source="..\ClassLibrary1\policy.1.0.ClassLibrary1.dll" >
</File>
<File
Id="LIBGACPolicyConfig"
Source="..\ClassLibrary1\policy.1.0.ClassLibrary1.config"
CompanionFile="LIBGACPolicy">
</File>
</Component>
</Directory>
When compiling with VS2008 appears this error:
policy.1.0.ClassLibrary1.dll appears to be invalid. Please ensure this is a valid assembly file and that the user has the appropriate access rights to this file. More information: HRESULT: 0x8013101b
And lastly, when compiling with VS2010 doesn´t appear to be any problem. But
at finalizing the installation process, the DLL is well installed and the
publisher policy didn´t. Also I read the log generated during the installation and I wasn´t able to find a cause.
Thanks for reading.
I've been doing something similar and works well using Visual Studio 2010 and in a Build Server with MsBuild:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="Gac" Name="Gac">
<!-- The component with the assembly -->
<Component Id="MiClassDLL" Guid="*">
<File Id="MiClass.dll" Assembly=".net" KeyPath="yes"
Source="$(var.MiClass.TargetPath)" />
</Component>
<!-- The component with the policy -->
<Component Id="PolicyMiClassDLL" Guid="{YOUR_GUID_HERE}">
<File Id="PolicyMiClass.dll" KeyPath="yes"
Source="$(var.MiClass.TargetDir)Policy.1.0.MiClass.dll" />
<File Id="PolicyMiClass.config" KeyPath="no"
Source="$(var.MiClass.ProjectDir)Policy.1.0.MiClass.config" />
</Component>
</Directory>
</Directory>
</Directory
In my case I have the policy.config file in the same project directory and I build the policy dll in the same output to make easier the installer script.
I noticed that the policy component must have a guid and for some reason it requires internally that policy dll and config files in the same directory/component.
I build the policy assembly in the Post-Build event of MiClass project with this command:
"C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\al.exe"
/link:"$(ProjectDir)Policy.1.0.MiClass.config"
/out:"$(TargetDir)Policy.1.0.MiClass.dll"
/keyfile:"$(SolutionDir)MyKeys.snk"
/comp:"My Company"
/prod:"My Product"
/productv:1.0
/version:1.0.0.0
I hope this works for you.
I did some work with policy dlls, and the only difference I can see is that your file naming convention is a little different than ours was.
Instead of
policy.1.0.ClassLibrary1.dll
policy.1.0.ClassLibrary1.config
We used
policy.1.0.ClassLibrary1.dll
ClassLibrary1.dll.config
instead of /link switch use /embed to compile the xml-config into publisher policy. then you can install the resulting assembly into GAC without problems