Conditionally install file based on a property in wix - wix

I want to install a file only if a property is set to "yes". Is this the correct way to do it?
The property is ExcelInstalled and is set to "yes" or "no".
<Directory Id="XlStartFolderId" Name="[XLSTART]">
<Component Id="ExcelMacro_xla" Guid="26D21093-B617-4fb8-A5E7-016493D46055" DiskId="1">
<Condition>ExcelInstalled="yes"</Condition>
<File Id="ExcelXLA" Name="AutoTagExcelMacro.xlam" ShortName="XLMacro.xla" Source="$(var.srcFolder)\AutoTagExcelMacro.xlam"/>
</Component>
</Directory>

Figured it out - it goes inside the File node:
<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">ExcelInstalled="yes"</File>
</Component>
</Directory>

Related

I want to install certain set of files based on OS version and another set of files based on another OS version using wix file

I need to install one set of files based on OS version and another set if some other OS is there,I have written a condition also but that condition doesn't work properly .
<Component Id="actionBin_Win7" Guid="6b73cbe1-4017-48d7-9cdc-784517b2d7a9" DiskId="1">
<Condition><![CDATA[(VersionNT >= 600)]]></Condition>
<File Id="file30" Name="AXINTE_2.DLL" LongName="AxInterop.MSTSCLib.dll" src="$(var.agentroot)\bin\AxInterop.MSTSCLib_Win7.dll" />
<File Id="file31" Name="ZENRDP_2.EXE" LongName="ZENRdpClient.exe" src="$(var.agentroot)\bin\ZENRdpClient_Win7.exe" />
<File Id="file32" Name="INTERO_2.DLL" LongName="Interop.MSTSCLib.dll" src="$(var.agentroot)\bin\Interop.MSTSCLib_Win7.dll" />
</Component>
<Component Id="actionBin" Guid="7388F2C9-5CDD-49a8-80F7-7DF5829AE87E" DiskId="1">
<Condition><![CDATA[(VersionNT < 600)]]></Condition>
<File Id="file10" Name="AXINTE_1.DLL" LongName="AxInterop.MSTSCLib.dll" src="$(var.agentroot)\bin\AxInterop.MSTSCLib.dll" />
<File Id="file11" Name="msrdp.ocx" LongName="msrdp.ocx" SelfRegCost="1" src="$(var.agentroot)\bin\msrdp.ocx" />
<File Id="file12" Name="ZENRDP_1.EXE" LongName="ZENRdpClient.exe" src="$(var.agentroot)\bin\ZENRdpClient.exe" />
<File Id="file13" Name="INTERO_1.DLL" LongName="Interop.MSTSCLib.dll" src="$(var.agentroot)\bin\Interop.MSTSCLib.dll" />
<File Id="file14" Name="shortcut.vbs" LongName="shortcut.vbs" src="$(var.agentroot)\bin\shortcut.vbs" />
</Component>
Feature :
<Feature Id="AllComponents" Title="AllComponents" Level="1">
<ComponentRef Id="actionBin" />
<ComponentRef Id="actionBin_Win7" />
</Feature>
Any idea what is going wrong here? Even when OS is windows 7, MSI takes files which I intend for WinXP...
Thanks in advance.
As far as i know about WIX, CDATA is used of ASCII comparison and not for integer comparison.
You can use custom action to compare OS version and then assign true or false value to some session variable and then you can use that session variable in wxs file.

How to install two MSI packages with single MSI package using WIX?

I have a scenario to install two MSI packages with single MSI package.
For example we have two products to install viz. Sample1.MSI and Sample2.MSI.
We need to embed Sample2.MSI package into Sample1.MSI.
If we install Sample1.MSI it should install both Sample1.MSI and Sample2.MSI and this should create two entries in Add or Remove programs (appwiz.cpl).
After a search I found a sample app which is using 'EmbeddedChainer' tag which is working properly with installation. But it is not uninstalling properly.
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLLOCATION" Name="SampleSetup">
<Component Id="InstallMSIComponent" Guid="{7091DE57-7BE3-4b0d-95D5-07EEF6463B62}">
<File Id="ChainRunner.exe" Name="ChainRunner.exe"
Source="C:\ChainRunner.exe"
DiskId="1" KeyPath="yes"/>
<File Id="TestFile.txt" Name="TestFile.txt" Source="TestFile.txt" />
<File Id="Microsoft.Deployment.WindowsInstaller.dll" Name="Microsoft.Deployment.WindowsInstaller.dll" Source="C:\Microsoft.Deployment.WindowsInstaller.dll"/>
<File Id="Microsoft.Deployment.WindowsInstaller.xml" Name="Microsoft.Deployment.WindowsInstaller.xml" Source="C:\Microsoft.Deployment.WindowsInstaller.xml"/>
<RemoveFolder Id='INSTALLLOCATION' On='uninstall' />
</Component>
<Component Id="SampleSetup2Component" Guid="{CB568AA4-9790-4efd-91BB-82682F063321}">
<File Id="SampleSetup2.msi" Name="SampleSetup2.msi"
Source="SampleSetup2.msi"
DiskId="1" KeyPath="yes"/>
</Component>
</Directory>
</Directory>
</Directory>
<EmbeddedChainer Id="Chainer" FileSource="ChainRunner.exe"/>
<Feature Id="ProductFeature" Title="SampleSetup" Level="1">
<ComponentRef Id="InstallMSIComponent"/>
<ComponentRef Id="SampleSetup2Component"/>
<ComponentGroupRef Id="Product.Generated" />
</Feature>
ChainRunner code
public class CustomActions
{
static void Main(string[] args)
{
try
{
IntPtr ptr = new IntPtr(Convert.ToInt32(args[0], 16));
ptr = System.Runtime.InteropServices.Marshal.StringToCoTaskMemAuto(args[0]);
Transaction transaction = Transaction.FromHandle(ptr, true);
transaction.Join(TransactionAttributes.JoinExistingEmbeddedUI);
Installer.InstallProduct(#"C:\SampleSetup2.msi", "");
transaction.Commit();
transaction.Close();
}
catch (Exception e)
{
Console.WriteLine("Exception in Installation:"+e.Message+"\n"+e.StackTrace.ToString());
Console.ReadKey();
throw e;
}
}
[CustomAction]
public static ActionResult CustomAction1(Session session)
{
session.Log("Begin CustomAction1");
return ActionResult.Success;
}
}
Where the this has been messed up?
Please advice if there is any other best way other than this approach?
You can use Wix Burn to create a setup package contained multiple application installers:
Wix Toolset: Building Installation Package Bundles;
Neil Sleightholm's Blog: WiX Burn – tips/tricks.

Multiple MSIs installation using embedded EmbeddedChainer

I am trying to install multiple .msi(s) using a Windows Installer Embedded chain. I researched some information from a website and I tried it. But it doesn't work (WiX + C#).
When I checked the debug, it works successfully until transaction.Commit() and transaction.close(). But SampleApp.msi didn't install.
'Multiple MISs Installer' installed successfully even if SampleApp.msi didn't work, and I can't uninstall 'Multiple MISs Installer'. The entry in the error log is "fatal error during installation".
How do I fix it?
Multiple MSIs Installer\Product.wxs
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLLOCATION" Name="Multiple Installer">
<Component Id="InstallMSIComponent" Guid="{7091DE57-7BE3-4b0d-95D5-07EEF6463B62}">
<File Id="FILE_MprjChainer.exe" Name="MprjChainer.exe"
Source="C:\A_VS2008\WiX\MprjChainer\MprjChainer\bin\Debug\MprjChainer.exe"
DiskId="1" KeyPath="yes"/>
<File Id="Microsoft.Deployment.WindowsInstaller.dll"
Name="Microsoft.Deployment.WindowsInstaller.dll"
Source="C:\Program Files\Windows Installer XML v3.5\SDK\Microsoft.Deployment.WindowsInstaller.dll" />
<File Id="System.dll"
Name="System.dll"
Source="C:\windows\Microsoft.NET\Framework\v2.0.50727\System.dll" />
<File Id="System.Core.dll" Name="System.Core.dll"
Source="C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll" />
<File Id="System.Windows.Forms.dll" Name="System.Windows.Forms.dll"
Source="C:\windows\Microsoft.NET\Framework\v2.0.50727\System.Windows.Forms.dll" />
<File Id="System.Xml.dll"
Name="System.Xml.dll"
Source="C:\windows\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll" />
<File Id="System.Xml.Linq.dll"
Name="System.Xml.Linq.dll"
Source="c:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Xml.Linq.dll" />
<RemoveFolder Id="INSTALLLOCATION" On="uninstall"/>
</Component>
<Component Id="CMPG_SimpleApp" Guid="{CB568AA4-9790-4efd-91BB-82682F063321}">
<File Id="SimpleApp.msi"
Name="SimpleApp.msi"
Source="C:\A_VS2008\WiX\MSIs\SimpleApp.msi"
DiskId="1" KeyPath="yes"/>
</Component>
</Directory>
</Directory>
</Directory>
<EmbeddedChainer Id="Chainer" FileSource="FILE_MprjChainer.exe"/>
<Feature Id="ProductFeature" Title="MPrjInstaller" Level="1">
<ComponentRef Id="InstallMSIComponent"/>
<ComponentRef Id="CMPG_SimpleApp"/>
<ComponentGroupRef Id="Product.Generated" />
</Feature>
Chainer\CustonAction.cs
namespace MprjChainer
{
public class CustomActions
{
static void Main(string[] args)
{
System.Diagnostics.Debugger.Launch();
try
{
IntPtr ptr = new IntPtr(Convert.ToInt32(args[0], 16));
Transaction transaction = Transaction.FromHandle(ptr, true);
transaction.Join(TransactionAttributes.JoinExistingEmbeddedUI);
transaction.Commit();
transaction.Close();
}
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show("e.Message; " + e.Message);
throw e;
}
}
[CustomAction]
public static ActionResult CustomAction1(Session session)
{
System.Diagnostics.Debugger.Launch();
session.Log("Begin CustomAction1");
return ActionResult.Success;
}
}
}
Try calling InstallProduct():
transaction.Join(TransactionAttributes.JoinExistingEmbeddedUI);
// start another installation in the same transaction
Installer.InstallProduct(#"path_To_Your_MSI", arguments);
// it's good to include /l*v install.log in the arguments so that you'll get a verbose log of the installation
transaction.Commit();
An example of Embedded Chainer can be seen at: WiX EmbeddedChainer Examples?
You could also look at Burn (the bootstrapper/chainer from Wix) for chaining multiple msi packages: http://robmensching.com/blog/posts/2009/7/14/Lets-talk-about-Burn
There is a bug in the c# code:
In the line "IntPtr ptr = new IntPtr(Convert.ToInt32(args[0], 16));" the "16" must be a "10"!
Otherwise you will get "bad handle" errors when there are more than 10 transactions (e.g. when there are five or more sub msi's called from the embedded chainer).

string compare in condition

when I get my achitecture type like this:
<Property Id="PLATTFORM">
<RegistrySearch Id="myRegSearchPalttform"
Root="HKLM"
Key="SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
Name="PROCESSOR_ARCHITECTURE"
Type="raw">
</RegistrySearch>
</Property>
and want to check if it is "AMD64" like this:
<?define myPlattform = [PLATTFORM] ?>
<?if $(var.myPlattform) = AMD64 ?>
some stuff
<?else ?>
some stuff
<?endif ?>
it fails.
When I set the value static:
<?define stest = AMD64 ?>
<?if $(var.stest) = AMD64 ?>
it goes in true scope. So why is the value from the registry(there is the value AMD64) not identical with my proof string????
Tanx in advance
<?define myPlattform = [PLATTFORM] ?>
Probably because myPlattform is a preprocessor variable and gets assigned before the PLATTFORM property ever has a value. If you want to conditionally install different components, you can try this way: How to use conditions in features in WiX?
This questions is possibly a duplicate of Is there a way to set a preprocessor variable to the value of a property?.
Update: If your goal is to set an installation location based on architecture, and your architecture is determined by the "PLATTFORM" property using the registry search you specified, then you could try the following:
<Property Id="PLATTFORM">
<RegistrySearch Id="myRegSearchPalttform"
Root="HKLM"
Key="SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
Name="PROCESSOR_ARCHITECTURE"
Type="raw">
</RegistrySearch>
</Property>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="SomeValue" />
</Directory>
</Directory>
<ComponentGroup Id="ProductComponentGroup">
<Component Id="ProductComponent" Guid="INSERT-GUID-HERE" Directory="INSTALLFOLDER">
<File Id="TestTextFile.txt" Source=".\TestTextFile.txt" KeyPath="yes"/>
</Component>
</ComponentGroup>
<Feature Id="ProductFeature" Level="1">
<ComponentGroupRef Id="ProductComponentGroup"/>
</Feature>
<SetDirectory Id="INSTALLFOLDER" Value="[ProgramFilesFolder]\SomeOtherValue">
PLATTFORM="AMD"
</SetDirectory>
Note: See that I used the SetDirectory element. I generally download the WiX weekly releases and never used that element until testing the above sample. Therefore I'm not sure what version SetDirectory was first introduced.

WebAppPool fails if AppPool already exists - WiX 3.5

This was working in WiX 3.0.
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="inetpubDir" Name="inetpub">
<Directory Id="wwwrootDir" Name="wwwroot">
<Directory Id="INSTALLDIR" Name="DS3000Services" FileSource="\Server\Implementation\DS3000Services\Web">
<Component Id="DS3000ServicesVirtualDir" Guid="{4EFD7047-09F4-42e7-ACB5-A209D26B0338}">
<CreateFolder />
<iis:WebAppPool Id="AppPool" Name="[AppPoolName]" Identity="other" User="PortalUser" IdleTimeout="0" RecycleMinutes="0">
<iis:RecycleTime Value="1:00" />
</iis:WebAppPool>
<iis:WebVirtualDir Id="DS3000ServicesVirtualDir" Alias="[VIRTUALDIR]" Directory="INSTALLDIR" WebSite="DefaultWebSite">
<iis:WebApplication Id="DS3000ServicesApp" Name="DS3000 Services" Isolation="medium" WebAppPool="AppPool" />
</iis:WebVirtualDir>
</Component>
Install Log:
MSI (s) (10:E8) [09:57:58:553]: Invoking remote custom action. DLL: C:\Windows\Installer\MSI14A0.tmp, Entrypoint: WriteIIS7ConfigChanges
WriteIIS7ConfigChanges: Error 0x800700b7: Failed to add appPool element
WriteIIS7ConfigChanges: Error 0x800700b7: Failed to configure IIS appPool.
WriteIIS7ConfigChanges: Error 0x800700b7: WriteIIS7ConfigChanges Failed.
CustomAction WriteIIS7ConfigChanges returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
MSI (s) (10:4C) [09:57:58:585]: User policy value 'DisableRollback' is 0
MSI (s) (10:4C) [09:57:58:585]: Machine policy value 'DisableRollback' is 0
Action ended 9:57:58: InstallFinalize. Return value 3.
Installing on Win Server 2008 R2. The AppPool already exists. If I remove the AppPool, the installer succeeds. Any thoughts? Thanks...
I would recommend you to create a customAction for creating virtual directory along with Application Pool.
I have used custom action in my project for that purpose. In the custom action you can check whether the application pool with the given name exists or not.
Added inbuilt commands
<Component Id="VDWeb" Guid="493E3487-AA4C-4476-8CC0-4B1C763AF6F7" Permanent="no">
<iis:WebVirtualDir Id="VDir" Alias="[VDNAME]" Directory="dir_Application_0" WebSite="WebSelectedWebSite">
<iis:WebApplication Id="WebApp" Name="[VDNAME]" WebAppPool="ABCAppPool" />
</iis:WebVirtualDir>
<RegistryKey Root="HKLM" Action="createAndRemoveOnUninstall" Key="SOFTWARE\ABC\[ProductCode]\VirtualDirectory">
<RegistryValue Name="VDName" Type="string" Value="[VDNAME]"/>
</RegistryKey>
</Component>
<Component Id="AppPool_1" Guid="414a377f-e044-49d5-b905-66bf3da6489f" Permanent="no">
<util:User Id="PoolAccount" Domain="[DOMAINNAME]" Name="[LogonUser]" Password="[NT_PASSWORD]" CreateUser="no">
<util:GroupRef Id="IISUsersGroup"/>
</util:User>
<iis:WebAppPool Id="ABCAppPool_NT" Name="[APPPOOLNAME_NT]" ManagedRuntimeVersion="v4.0" ManagedPipelineMode="integrated" Identity="other" User="PoolAccount">
<iis:RecycleTime Value="05:00" />
</iis:WebAppPool>
</Component>
<util:Group Id="IISUsersGroup" Name="IIS_IUSRS"/>
<iis:WebSite Id="WebSelectedWebSite" Description="[WEB_WEBSITE_DESCRIPTION]">
<iis:WebAddress Id="AllUnassigned1" Port="[WEB_WEBSITE_PORT]" IP="[WEB_WEBSITE_IP]" Header="[WEB_WEBSITE_HEADER]" />
</iis:WebSite>
Am using this and it works perfectly fine.