wix xsl transform to conditionally remove components - xslt

I'm creating a transform for WiX's heat utility that needs to suppress the harvesting of folders matching a specific name (.PayloadData) under the tree being harvested.
I can easily get it to suppress the Directory and Component elements but the ComponentRef element is proving tricky.
The folder is called .PayloadData and this successfully suppresses the Directory and Component elements:
<xsl:template match="wix:Directory[#Name='.PayloadData']" />
<xsl:template match="wix:Directory[#Name='.PayloadData']/*" />
I tried something similar for the ComponentRef element but it matches everything.
<xsl:template match="wix:ComponentRef[//wix:Directory[#Name='.PayloadData']/wix:Component[#Id=#Id]]">
I think #Id might be ambiguous in the xpath expression but I don't know how to tell it that the ComponentRef's Id attribute is trying to match the Component's Id attribute.
Here's the input:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?include $(var.ProjectDir)\..\Common\Common.wxi?>
<Fragment>
<DirectoryRef Id="SampleDataDir">
<Directory Id="dirFD22039A64AC1D31F568C1632B5AF8A3" Name=".PayloadData">
<Component Id="cmp846A29F6413B27E8777DD68E6026E461" Guid="*">
<File Id="fil9227EFCE377E7FEBB63A4BD121F278AE" KeyPath="yes" Source="$(var.SampleDataDir)\.PayloadData\SampleData.xml" />
</Component>
</Directory>
<Directory Id="dirA4E41FB410D214A14F0C8A302E5E70D2" Name="AlternativePBS">
<Component Id="cmp3E04EEF702FDD121FD225ABF32550EDB" Guid="*">
<File Id="filF1367714C6CE3472899C32E78D3D6D0C" KeyPath="yes" Source="$(var.SampleDataDir)\AlternativePBS\01-ADMIN_Update_PBSHierarchy.xml" />
</Component>
<Component Id="cmp6732C6415C5574DB586333DE13FAFD1C" Guid="*">
<File Id="fil7F1A16AA0DA338664312C832796DD228" KeyPath="yes" Source="$(var.SampleDataDir)\AlternativePBS\02-SCHEMA_Update_PBSHierarchy.xml" />
</Component>
<Component Id="cmp01BD73A317794376E5323FA329D1BFEB" Guid="*">
<File Id="filFD2213EB9E67560F25B506695650F7B0" KeyPath="yes" Source="$(var.SampleDataDir)\AlternativePBS\ProcedureForAltPBSStructure.doc" />
</Component>
<Component Id="cmp1E93AAFF75E01670D20E84280E7B9B5C" Guid="*">
<File Id="filC02D64539D33E6B5250C883EFF6357DD" KeyPath="yes" Source="$(var.SampleDataDir)\AlternativePBS\SPFAdapter_PBS.xml" />
</Component>
<Component Id="cmp428BA2587DEE28B22239181E175B108B" Guid="*">
<File Id="fil8D32FED82C161537AE2432BFA7F89310" KeyPath="yes" Source="$(var.SampleDataDir)\AlternativePBS\UpdatePBSHierarchyGraphDef.xmlldr" />
</Component>
</Directory>
</DirectoryRef>
</Fragment>
<Fragment>
<ComponentGroup Id="CG_SampleData">
<ComponentRef Id="cmp846A29F6413B27E8777DD68E6026E461" />
<ComponentRef Id="cmp3E04EEF702FDD121FD225ABF32550EDB" />
<ComponentRef Id="cmp6732C6415C5574DB586333DE13FAFD1C" />
<ComponentRef Id="cmp01BD73A317794376E5323FA329D1BFEB" />
<ComponentRef Id="cmp1E93AAFF75E01670D20E84280E7B9B5C" />
<ComponentRef Id="cmp428BA2587DEE28B22239181E175B108B" />
</ComponentGroup>
</Fragment>
</Wix>
And this is the desired output
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?include $(var.ProjectDir)\..\Common\Common.wxi?>
<Fragment>
<DirectoryRef Id="SampleDataDir">
<Directory Id="dirA4E41FB410D214A14F0C8A302E5E70D2" Name="AlternativePBS">
<Component Id="cmp3E04EEF702FDD121FD225ABF32550EDB" Guid="*">
<File Id="filF1367714C6CE3472899C32E78D3D6D0C" KeyPath="yes" Source="$(var.SampleDataDir)\AlternativePBS\01-ADMIN_Update_PBSHierarchy.xml" />
</Component>
<Component Id="cmp6732C6415C5574DB586333DE13FAFD1C" Guid="*">
<File Id="fil7F1A16AA0DA338664312C832796DD228" KeyPath="yes" Source="$(var.SampleDataDir)\AlternativePBS\02-SCHEMA_Update_PBSHierarchy.xml" />
</Component>
<Component Id="cmp01BD73A317794376E5323FA329D1BFEB" Guid="*">
<File Id="filFD2213EB9E67560F25B506695650F7B0" KeyPath="yes" Source="$(var.SampleDataDir)\AlternativePBS\ProcedureForAltPBSStructure.doc" />
</Component>
<Component Id="cmp1E93AAFF75E01670D20E84280E7B9B5C" Guid="*">
<File Id="filC02D64539D33E6B5250C883EFF6357DD" KeyPath="yes" Source="$(var.SampleDataDir)\AlternativePBS\SPFAdapter_PBS.xml" />
</Component>
<Component Id="cmp428BA2587DEE28B22239181E175B108B" Guid="*">
<File Id="fil8D32FED82C161537AE2432BFA7F89310" KeyPath="yes" Source="$(var.SampleDataDir)\AlternativePBS\UpdatePBSHierarchyGraphDef.xmlldr" />
</Component>
</Directory>
</DirectoryRef>
</Fragment>
<Fragment>
<ComponentGroup Id="CG_SampleData">
<ComponentRef Id="cmp3E04EEF702FDD121FD225ABF32550EDB" />
<ComponentRef Id="cmp6732C6415C5574DB586333DE13FAFD1C" />
<ComponentRef Id="cmp01BD73A317794376E5323FA329D1BFEB" />
<ComponentRef Id="cmp1E93AAFF75E01670D20E84280E7B9B5C" />
<ComponentRef Id="cmp428BA2587DEE28B22239181E175B108B" />
</ComponentGroup>
</Fragment>
</Wix>
It needs to strip out:
Directory dirFD22039A64AC1D31F568C1632B5AF8A3
Component cmp846A29F6413B27E8777DD68E6026E461
ComponentRef cmp846A29F6413B27E8777DD68E6026E461

Thank you for your help. I now have the answer. Key was the key (pun intended):
<xsl:key name="ComponentsToSuppress" match="wix:Component[ancestor::wix:Directory[#Name='.PayloadData']]" use="#Id" />
<xsl:template match="wix:Directory[#Name='.PayloadData']" />
<xsl:template match="wix:ComponentRef[key('ComponentsToSuppress', #Id)]" />
This allows me to suppress the Component and ComponentRef of items appearing under a Directory named ".PayloadData" regardless of where it appears (or how often it appears).

Related

Wix Heat harvest: removing directories containing filtered components with transform

I have the following snippet of a .wxs(Ids ommitted) outputted from WiX harvest.
<Directory Id="" Name="tr">
<Component Id="" Guid="*">
<File Id="" KeyPath="yes" Source="$(var.SourceDir)\tr\ZedGraph.resources.dll" />
</Component>
</Directory>
<Directory Id="" Name="zh-cn">
<Component Id="" Guid="*">
<File Id="" KeyPath="yes" Source="$(var.SourceDir)\zh-cn\ZedGraph.resources.dll" />
</Component>
</Directory>
<Directory Id="" Name="zh-tw">
<Component Id="" Guid="*">
<File Id="" KeyPath="yes" Source="$(var.SourceDir)\zh-tw\ZedGraph.resources.dll" />
</Component>
</Directory>
</DirectoryRef>
And the following transform will remove the components but leaves the empty directory elements. How can I remove them as well? Given that I do not want to blanket remove all directory elements. Ideally, I would like to match them based on containing the component Id that is returned from the search.
<xsl:key name="zedResource-search" match="wix:Component[contains(wix:File/#Source, 'ZedGraph.resources.dll')]" use="#Id" />
<xsl:template match="wix:Component[key('zedResource-search', #Id)]" />
<xsl:template match="wix:ComponentRef[key('zedResource-search', #Id)]" />
This question is similar, but uses the directory names which i would like to avoid adding a search for each of these because there are quite a few language variants.
One way to do this is use a separate template to match the Directory element where all the child Component elements are in the key. You do this comparison with a count
<xsl:template match="wix:Directory[count(wix:Component)
= count(wix:Component[key('zedResource-search', #Id)])]" />
Alternately, you can say you want to remove Directory which don't have a Component ref that are not in the key (so, a double negative)
<xsl:template match="wix:Directory[not(wix:Component[not(key('zedResource-search', #Id))])]" />

Can't register dll using WiX - error code "hresult -2147024770"

I am developing an IME (Input Method Editor) for Windows so I compiled this sample from microsoft: https://code.msdn.microsoft.com/windowsdesktop/Input-Method-Editor-IME-b1610980/view/Discussions/1 using Visual Studio 2015 and packaged it using WiX.
It installs fine on the computer on which I compiled it, but it seems like I cannot get regsvr32 to register the dll/ime on my other computer (both running windows 10). I get this error
, and manually registering the dll through cmd doesn't work either. My guess is that I am missing a dependency? Does anyone know what I am doing wrong?
Here is the .wxs packaging code from WiX:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="WiXSetup" Language="1033" Version="1.0.0.0" Manufacturer="lwrnc" UpgradeCode="5973bdd3-dea7-4924-a303-4e881386e030">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Feature Id="ProductFeature" Title="WiXSetup" Level="1">
<ComponentGroupRef Id="StartMenuComponents" />
<!--<ComponentGroupRef Id="IMEComponentsx86" />-->
<ComponentGroupRef Id="IMEComponentsx64" />
</Feature>
</Product>
<!--Directory Structure-->
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<!--Start Menu Shortcut-->
<Directory Id="ProgramMenuFolder">
<Directory Id="MyShortcutsDir" Name="WiXSetup">
</Directory>
</Directory>
<!--x86 Version-->
<Directory Id="ProgramFilesFolder">
<Directory Id="IMEINSTALLFOLDERx86" Name="WiXSetup">
</Directory>
</Directory>
<!--x64 Version-->
<Directory Id="ProgramFiles64Folder">
<Directory Id="IMEINSTALLFOLDERx64" Name="WiXSetup">
</Directory>
</Directory>
</Directory>
</Fragment>
<!--Components-->
<Fragment>
<!--x86 IME-->
<!--<ComponentGroup Id="IMEComponentsx86" Directory="IMEINSTALLFOLDERx86">
<Component Id="CMP_IMEx86" Guid="{0CB17F8D-26FF-4E29-A428-710791CDE1EB}">
<File Id="FILE_IMEINSTALLFOLDER_SampleIMEx86DLL" Source="SampleIMEx86.dll" KeyPath="yes" SelfRegCost="1" />
</Component>
<Component Id="CMP_DICTx86" Guid="{66474BE0-ABE5-4B22-8F9B-EB894C6A6218}">
<File Id="FILE_IMEINSTALLFOLDER_SampleIMESimplifiedQuanPinx86TXT" Source="SampleIMESimplifiedQuanPin.txt" KeyPath="yes"/>
</Component>
</ComponentGroup>-->
<!--x64 IME-->
<ComponentGroup Id="IMEComponentsx64" Directory="IMEINSTALLFOLDERx64">
<Component Id="CMP_IMEx64" Guid="{AEDC5FB8-6BB9-4A9F-B920-D6D8244BB837}">
<File Id="FILE_IMEINSTALLFOLDER_SampleIMEx64DLL" Source="SampleIMEx64.dll" KeyPath="yes" SelfRegCost="1" />
</Component>
<Component Id="CMP_DICT" Guid="{C555385F-4848-48B4-90A8-EB0E722605EB}">
<File Id="FILE_IMEINSTALLFOLDER_SampleIMESimplifiedQuanPinx64TXT" Source="SampleIMESimplifiedQuanPin.txt" KeyPath="yes"/>
</Component>
</ComponentGroup>
<!--Start Menu Components-->
<ComponentGroup Id="StartMenuComponents" Directory="MyShortcutsDir">
<Component Id="CMP_DocumentationShortcut" Guid="{4EFD00CD-2297-4A9D-A0A5-47C26897E223}">
<Shortcut Id="WiXSetupDoc" Name="WiXSetup Doc" Description="Read this please" Target="[INSTALLFOLDER]lwrnc.txt" />
<Shortcut Id="UninstallShortcut" Name="Uninstall WS" Description="uninstall wixsetup practice" Target="[System64Folder]msiexec.exe" Arguments="/x [ProductCode]" />
<RemoveFolder Id="RemoveMyShortcutsDir" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\Microsoft\WiXSetup" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
</Component>
</ComponentGroup>
</Fragment>
</Wix>

Get Install Location in Wix and write in Registry

I have following Wix File that installs the file in Program Files(x86) for 64 bit system and Program Files in 32 bit system. In the program I need to access the file lpa.config that is present in Installed folder, which may be one of two above. For This I need to write the Installed folder in Registry. Is there any way to get the Installed folder location in Wix?
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="CustomWixInstallerWithCustomAction" Language="1033" Version="1.0.0.0" Manufacturer="LogPoint" UpgradeCode="ba9015b9-027f-4451-adb2-e38f9168a850">
<Package InstallerVersion="200" Compressed="no" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Feature Id="ProductFeature" Title="CustomWixInstallerWithCustomAction" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="CustomWixInstaller" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="SomeRandomEXE">
<File Source ="G:\SarVaGYa\myworkspace\LatestLpa\lpa\lpa_c\here\src\lpa\Release\lpa.exe" />
</Component>
<Component Id="registry_values" Guid="{11FB6C4C-3C90-4F46-B0D2-BB95150F60E6}">
<RegistryValue
KeyPath="yes"
Root="HKCU"
Key="Software\Logpoint"
Value="Here I need the path"
Type="string" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
Yes, starting from WiX documentation example:
<DirectoryRef Id="TARGETDIR">
<Component Id="RegistryEntries" Guid="PUT-GUID-HERE">
<RegistryKey Root="HKCU"
Key="Software\Microsoft\MyApplicationName"
Action="createAndRemoveOnUninstall">
<RegistryValue Type="string" Name="SetupPath" Value="PUT-PATH-HERE"/>
</RegistryKey>
</Component>
</DirectoryRef>
WiX is based on Windows Installer and Registry values are Formatted properties, you can use familiar syntax to access properties:
<RegistryValue Type="string" Name="SetupPath" Value="[INSTALLFOLDER]"/>
Property name matches your <Directory> element ID, in your case: <Directory Id="INSTALLFOLDER".
There are other ways to do it but...well IMO this is easiest one.

List box Property value not coming in c++ custom action wix?

I am stuck with this from quite long now , the ListBox "SETUPLOGLEVEL" Property is not showing the value in C++ Custom action when I am calling MsiGetProperty(hInstall, L"SETUPLOGLEVEL", Pid, &PidLength). The pid is showing 0 value after execution of this function also, I checked by debugging the custom action.
This is Product.wxs
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util='http://schemas.microsoft.com/wix/UtilExtension'>
<Product Id="*" Name="MyExampleProject" Language="1033" Version="1.0.0.0" Manufacturer="Mq" UpgradeCode="08bd3c48-deef-4370-ab94-f8b4d49406e3">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" InstallPrivileges="elevated"/>
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<!--System Configuration Condition - Installation install only above Windows XP-->
<Condition Message="This application is only supported on Windows XP, or higher.">
<![CDATA[Installed OR (VersionNT >= 501)]]>
</Condition>
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='ProgramFilesFolder' Name='PFiles'>
<Directory Id='INSTALLDIR' Name='AgentFramework'>
<Directory Id='INSTALLBIN' Name='bin'/>
<Directory Id='INSTALLCONF' Name='conf'/>
<Directory Id='INSTALLMODULES' Name='modules'/>
</Directory>
</Directory>
</Directory>
<Feature
Id = "ProductFeature1"
Title = "AgentFramework"
Level = "1"
Absent="allow">
<ComponentRef Id='libapr_dll'/>
<ComponentRef Id='libapriconv_dll'/>
<ComponentRef Id='libaprutil_dll'/>
<ComponentRef Id='libhttpd_dll'/>
<ComponentRef Id='Pcre_dll'/>
<ComponentRef Id='Configurationfile'/>
<ComponentRef Id='Authzmodule'/>
<ComponentRef Id='Dirmodule'/>
<ComponentRef Id='ServiceComponent'/>
</Feature>
<DirectoryRef Id='INSTALLCONF'>
<Component Id='Configurationfile' Guid='2E0D2957-10EB-463A-A4FC-62B9062FE8A3'>
<File Id='Configurationfile' Name='httpd.conf' DiskId='1' Source='$(sys.CURRENTDIR)\httpd.conf' KeyPath='yes'>
</File>
</Component>
</DirectoryRef>
<DirectoryRef Id='INSTALLMODULES'>
<Component Id='Authzmodule' Guid='62AA97B6-7821-4CB4-9F89-B2A8FF0CC6BD'>
<File Id='Authzmodule' Name='mod_authz_core.so' DiskId='1' Source='$(sys.CURRENTDIR)\mod_authz_core.so' KeyPath='yes'>
</File>
</Component>
<Component Id='Dirmodule' Guid='9966BB3B-8296-43B9-A6DC-712561303329'>
<File Id='Dirmodule' Name='mod_dir.so' DiskId='1' Source='$(sys.CURRENTDIR)\mod_dir.so' KeyPath='yes'>
</File>
</Component>
</DirectoryRef>
<DirectoryRef Id='INSTALLBIN'>
<Component Id='libapr_dll' Guid='FB82D093-0B32-465B-8D8B-08B3127EB414'>
<File Id='libapr_dll' Name='libapr-1.dll' DiskId='1' Source='$(sys.CURRENTDIR)\libapr-1.dll' KeyPath='yes'>
</File>
</Component>
<Component Id='libapriconv_dll' Guid='667D6D5B-6FE4-4A6B-827F-C496239628E2'>
<File Id='libapriconv_dll' Name='libapriconv-1.dll' DiskId='1' Source='$(sys.CURRENTDIR)\libapriconv-1.dll' KeyPath='yes'>
</File>
</Component>
<Component Id='libaprutil_dll' Guid='72C688D2-8E25-49D9-9E76-F6BDBC33D394'>
<File Id='libaprutil_dll' Name='libaprutil-1.dll' DiskId='1' Source='$(sys.CURRENTDIR)\libaprutil-1.dll' KeyPath='yes'>
</File>
</Component>
<Component Id='libhttpd_dll' Guid='8946D5B1-0EA2-443E-8C20-CD8D877ACF75'>
<File Id='libhttpd_dll' Name='libhttpd.dll' DiskId='1' Source='$(sys.CURRENTDIR)\libhttpd.dll' KeyPath='yes'>
</File>
</Component>
<Component Id='Pcre_dll' Guid='0466BB2A-137C-4A95-A510-43E7A274F834'>
<File Id='Pcre_dll' Name='pcre.dll' DiskId='1' Source='$(sys.CURRENTDIR)\pcre.dll' KeyPath='yes'>
</File>
</Component>
<Component Id ="ServiceComponent" Guid="8A1BF3F0-8A84-456E-816A-5907B40B2DDB" >
<File Id='Applicationfile' Name='httpd.exe' DiskId='1' Source='$(sys.CURRENTDIR)\httpd.exe' KeyPath='yes'>
</File>
<ServiceInstall Id="ServiceComponent" Type="ownProcess" Name="Apache2.4"
DisplayName="Apache2.4" Description="Service"
Arguments="-k runservice" Start="auto" Account="LocalSystem" ErrorControl="normal"
Vital="yes" >
<util:PermissionEx User="Everyone" ServicePauseContinue="yes" ServiceQueryStatus="yes"
ServiceStart="yes" ServiceStop="yes" ServiceUserDefinedControl="yes" /> </ServiceInstall>
<ServiceControl Id="ServiceComponent" Start="install" Stop="both"
Remove="uninstall" Name="Apache2.4" Wait="yes" />
</Component>
</DirectoryRef>
<UIRef Id="CustomizeDlg" />
<UI Id="MyWixUI_Mondo">
<UIRef Id="WixUI_Mondo" />
<UIRef Id="WixUI_ErrorProgressText" />
<DialogRef Id="UserRegistrationDlg" />
<Publish Dialog="LicenseAgreementDlg" Control="Next" Event="NewDialog" Value="UserRegistrationDlg" Order="3">LicenseAccepted = "1"</Publish>
<Publish Dialog="SetupTypeDlg" Control="Back" Event="NewDialog" Value="UserRegistrationDlg">1</Publish>
</UI>
<Property Id="PIDTemplate"><![CDATA[1234<####-####-####-####>####]]></Property>
<CustomAction Id='CheckLogLevel' BinaryKey='CheckLogLevel' DllEntry='CustomAction1' />
<Binary Id ='CheckLogLevel' SourceFile='$(sys.CURRENTDIR)\MqAgent_LogLevel.dll'/>
<WixVariable Id="WixUIBannerBmp" Value="C:\Image\style39_banner.bmp" />
<WixVariable Id="WixUIDialogBmp" Value="C:\Image\style39_dialog.bmp" />
</Product>
</Wix>
Here's my code CustomizeDlg.wxs ::
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI Id ="CustomizeDlg">
<Dialog Id="UserRegistrationDlg" Width="370" Height="270" Title="[ProductName] Setup" NoMinimize="yes">
<Control Id="MyListBox"
Type="ListBox" X="52" Y="48"
Width="100" Height="45"
Property="SETUPLOGLEVEL" Sorted="yes">
<ListBox Property="SETUPLOGLEVEL">
<ListItem Text="Debug" Value="1" />
<ListItem Text="info" Value="2" />
<ListItem Text="warn" Value="3" />
</ListBox>
<Property Id="SETUPLOGLEVEL" Value="1"/>
</Control>
<Control Id="CDKeyLabel" Type="Text" X="45" Y="147" Width="50" Height="10" TabSkip="no">
<Text>CD &Key:</Text>
</Control>
<Control Id="CDKeyEdit" Type="MaskedEdit" X="45" Y="159" Width="250" Height="16" Property="PIDKEY" Text="[PIDTemplate]" />
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="&Back">
<Publish Event="NewDialog" Value="LicenseAgreementDlg">1</Publish>
</Control>
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="&Next">
<Publish Event="ValidateProductID" Value="0">1</Publish>
<Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg">CostingComplete = 1</Publish>
<Publish Event="NewDialog" Value="SetupTypeDlg">ProductID</Publish>
</Control>
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="Cancel">
<Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
</Control>
<Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="WixUI_Bmp_Banner" />
<Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes">
<Text>Please mention the log level</Text>
</Control>
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
<Text>{\WixUI_Font_Title}Select Log Level</Text>
</Control>
<Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
</Dialog>
</UI>
</Fragment>
</Wix>
And This is my Custom action:
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <string.h>
using namespace std;
UINT __stdcall CustomAction1(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
string search_string;
string replace_string;
string inbuf;
DWORD PidLength = MAX_PATH;
wchar_t Pid[MAX_PATH] = {L"0"};
MessageBox(NULL,L"debug", L"CustomactionDebug", MB_OK);
hr = WcaInitialize(hInstall, "CustomAction1");
ExitOnFailure(hr, "Failed to initialize");
WcaLog(LOGMSG_STANDARD, "Initialized.");
MsiGetProperty(hInstall, L"SETUPLOGLEVEL", Pid, &PidLength);
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
// DllMain - Initialize and cleanup WiX custom action utils.
extern "C" BOOL WINAPI DllMain(
__in HINSTANCE hInst,
__in ULONG ulReason,
__in LPVOID
)
{
switch(ulReason)
{
case DLL_PROCESS_ATTACH:
WcaGlobalInitialize(hInst);
break;
case DLL_PROCESS_DETACH:
WcaGlobalFinalize();
break;
}
return TRUE;
}
I can't tell where or how your CA is being called, but there are two possible reasons I can think of:
You're calling it from a deferred custom action, and that means you need to use CustomActionData to get the value.
The property is not marked Secure="yes" therefore it's losing its value by the time you call your CA in the execute sequence.

WiX - Copy compiled web.config based on environment to website root

As a part of my WiX installation, I am copying all the transformed/compiled web.config files to the install directory. The names of the compiled web.config are in format web.{ENV}.config. In my install UI I created a Custom Dialog where I parse the ENV and populate a combobox so that the user can select the environment to which we deploy to. This comboBox sets a Property ENV.
I need to understand how i could use this property to copy the installed config files to the website root.
Update: #Rob_Mensching - your solution works, however, on compilation WiX forces me to have a GUID created for each such component. Is there a way I could avoid it? The thing is i am going to generate this piece of code by running XSLT on my wxs file which gets generated using heat; and there is no way I could generate a GUID using XSLT (or can I?)
This is how my code looks now:
<ComponentGroup Id='web.config' Directory='CONFIGLOCATION'>
<Component Id='CopyWebConfigForDev1' Guid='{F207C26A-5D9C-4F19-96A3-D818BB226EFC}' >
<Condition>ENV="Dev1"</Condition>
<CopyFile Id='CopyDev1Config' FileId='fil9C4CFE42035F1A63180142352CF441BC' DestinationDirectory='CONFIGLOCATION' DestinationName='web.config'/>
</Component>
<Component Id='CopyWebConfigForQA1' Guid='{F207C26A-5D9C-4F19-96A3-D818BB226EFC}' >
<Condition>ENV="QA1"</Condition>
<CopyFile Id='CopyQA1Config' FileId='fil12F8B50F03F1BD91A579F6B6CE7195DF' DestinationDirectory='CONFIGLOCATION' DestinationName='web.config'/>
</Component>
</ComponentGroup>
I would use a "Component Condition"b to do so. Something like the following should work well:
<Fragment>
<ComponentGroup Id='web.config' Directory='ConfigFolder'>
<Component>
<Condition>ENV~="Production"</Condition>
<File Source='web.Production.config'>
<CopyFile DestinationDirectory='INSTALLFOLDER' DestinationName='web.config' />
</File>
</Component>
<Component>
<Condition>ENV~="Test"</Condition>
<File Source='web.Test.config'>
<CopyFile DestinationDirectory='INSTALLFOLDER' DestinationName='web.config' />
</File>
</Component>
</ComponentGroup>
</Fragment>
The condition syntax is documented here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa368012(v=vs.85).aspx
With help from the code that Rob provided and after some more research i found out how to avoid having to provide the Guid to each component if your installation folder is not a standard folder. Simply specify the ComponentGuidGenerationSeed for the Custom Directory under which you are trying to install the component to. The directory where you specify this attribute need not be the immediate parent directory of the location where you intend to install the component. This is how my directory structure now looks:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="INETPUBFOLDER" Name="inetpub">
<Directory Id="WWWROOTFOLDER" Name="wwwroot" ComponentGuidGenerationSeed="PUT-YOUR-GUID">
<Directory Id="CONFIGLOCATION" Name="$(var.PublishLocation)" />
<Directory Id="INSTALLLOCATION" Name="$(var.PublishLocation)" >
<Directory Id="APPFOLDER" Name="bin" />
<Directory Id="MyProject.Web.Content" />
<Directory Id="CONFIGSFOLDER" Name="Configs">
<Directory Id="WEBFOLDER" Name="Web">
<Directory Id="WEBCONFIGFILES" />
</Directory>
<Directory Id="NLOGFOLDER" Name="NLog">
<Directory Id="NLOGCONFIGFILES" />
</Directory>
</Directory>
</Directory>
</Directory>
</Directory>
</Directory>
This is how now my harvested and xml transformed wxs file looks:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:wix="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef Id="WEBCONFIGFILES">
<Component Id="cmp9CAF0D4A0C62775945002986D1D99926" Guid="PUT-YOUR-GUID">
<File Id="fil9C4CFE42035F1A63180142352CF441BC" KeyPath="yes" Source="$(var.WebConfigFilesDir)\Web.Dev1.config" />
</Component>
<Component Id="cmpB5117E2029EA9A7CC3AFC247EA4483AD" Guid="PUT-YOUR-GUID">
<File Id="fil0F80FEAFAD0333C3B74BB742C4FE118C" KeyPath="yes" Source="$(var.WebConfigFilesDir)\Web.Prod.config" />
</Component>
<Component Id="cmp340743041F12BBE6C7C40D4351407D08" Guid="PUT-YOUR-GUID">
<File Id="fil12F8B50F03F1BD91A579F6B6CE7195DF" KeyPath="yes" Source="$(var.WebConfigFilesDir)\Web.QA1.config" />
</Component>
</DirectoryRef>
</Fragment>
<Fragment>
<ComponentGroup Id="WebConfigFiles">
<ComponentRef Id="cmp9CAF0D4A0C62775945002986D1D99926" />
<ComponentRef Id="cmpB5117E2029EA9A7CC3AFC247EA4483AD" />
<ComponentRef Id="cmp340743041F12BBE6C7C40D4351407D08" />
</ComponentGroup>
</Fragment>
<Fragment>
<UI Id="EnvironmentComboBox">
<ComboBox Property="ENV">
<ListItem Value="Dev1" Text="Dev1" />
<ListItem Value="Prod" Text="Prod" />
<ListItem Value="QA1" Text="QA1" />
</ComboBox>
</UI>
</Fragment>
<Fragment>
<ComponentGroup Id="web.config" Directory="CONFIGLOCATION">
<Component Id="cmpWebConfigForDev1">
<Condition>ENV="Dev1"</Condition>
<File Id="CopyDev1Config" Source="$(var.WebConfigFilesDir)\Web.Dev1.config" Name="web.config" />
</Component>
<Component Id="cmpWebConfigForProd">
<Condition>ENV="Prod"</Condition>
<File Id="CopyProdConfig" Source="$(var.WebConfigFilesDir)\Web.Prod.config" Name="web.config" />
</Component>
<Component Id="cmpWebConfigForQA1">
<Condition>ENV="QA1"</Condition>
<File Id="CopyQA1Config" Source="$(var.WebConfigFilesDir)\Web.QA1.config" Name="web.config" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
In the above file only the first two fragments are generated by the harvest tool. The next two fragments containing the UI/ComboBox Definition and ComponentGroup for WebconfigFiles are created using XML transform by reading the information from File elements in the first Fragment.