WiX installer: can we add a new element in web.config using a patch when it is set to NeverOverwrite=yes in its initial msi - wix

I am working on a web application. the Web.config file is set to NeverOverwrite (=yes) in its initial installation. Now i need to add DBproviderfactories like below. Can i add this entire block using XmlFile in a patch.msp? I do not want to write a custom action. All I need is to add this block in the web.config. Any suggestion here is appreciated.
<system.data>
<DbProviderFactories>
<!-- Remove in case this is already defined in machine.config -->
<remove invariant="Oracle.ManagedDataAccess.Client" />
<add name="Oracle Data Provider for .NET" invariant="Oracle.ManagedDataAccess.Client" description="Oracle Data Provider for .NET, Managed Driver" type="Oracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess, Version=4.122.19.1, Culture=neutral, PublicKeyToken=89b483f429c47342" />
</DbProviderFactories>
</system.data>

Sample: Maybe try this:
https://github.com/glytzhkof/WiXUpdateXmlFile
Below is the gist of it - please use the sample above for testing. The markup below is just for illustration.
Set the XML file both permanent and never overwrite.
See inline instructions in the sample above for testing.
Check what happens on uninstall - this markup will remove the entries it added.
<!-- Set app.config permanent and never overwrite to yes -->
<Component Feature="ProductFeature" NeverOverwrite="yes" Permanent="yes">
<File Source="app.config" />
</Component>
<!-- The XML update -->
<!-- Use a NEW GUID here, do not go live with this one -->
<Component Id="XmlFileUpdate" Guid="{00000000-0000-0000-0000-7405EED51B57}" Feature='ProductFeature'>
<!--Create New Element-->
<util:XmlFile Id='XmlSettings1' File='[INSTALLFOLDER]app.config' Action='createElement' Name='MyConfig' ElementPath='//configuration' Sequence='1' />
<!--Set New Value-->
<util:XmlFile Id='XmlSettings2' File='[INSTALLFOLDER]app.config' Action='setValue' Name='newVersion' Value='6.6.8' ElementPath='//configuration/MyConfig' Sequence='2' />
<!--Set New Value-->
<util:XmlFile Id='XmlSettings3' File='[INSTALLFOLDER]app.config' Action='setValue' Name='Server' Value='Pusevov' ElementPath='//configuration/MyConfig' Sequence='3' />
<!--Update Existing Value, Existing Element-->
<util:XmlFile Id='XmlSettings4' File='[INSTALLFOLDER]app.config'
Action='setValue' Name='newVersion' Value='7.7.7' ElementPath='//configuration/ExistingConfig/bindingRedirect' Sequence='4' />
<CreateFolder />
</Component>
</Directory>
</Directory>
Link:
Added new application setting to app.config but MSI won't install it (doesn't overwrite)

Related

XmlException: Root element is missing (but it's not)

I have a VB.Net 4.7.2 desktop application that is throwing an exception occasionally. The exception is usually, "Root element is missing".
When this happens, I am able to view the file after the fact and the root element is there.
The file is written to the share by a remote Linux system and is accessed by this application using an SMB share.
I thought there might be a timing issue with the file being written to the share, so I implemented a retry and I still get the same exception after trying 3 times, 10 seconds apart.
The xmlPath is passed in as a parameter.
' xmlPath is the UNC path to a local network share.
Dim xmlDoc As New XmlDocument()
xmlDoc.Load(xmlPath)
When I view the XML file at the file location, here's what I see.
<reportrequest Version="1.0">
<report ReportGUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" ReportCode="LENDPG_1" ABSReportCode="" Title="Lender Portal Collateral Screen Basic" Description="CS Basic Report" Price="0">
<account AccountNumber="6551198" Address="000 Main St" City="Spokane" State="WA" ZipCode="99201" />
<contact FirstName="Person" LastName="Ordering" Email="person#domain.com" Phone="000-000-0000" />
<outputtypecoll>
<outputtype Type="XML" FileName="" />
</outputtypecoll>
<featurecoll>
<feature Name="CSRDISTANCE" Value="false" />
<feature Name="CSRDBSTATUS" Value="false" />
<feature Name="CSRELEVATION" Value="false" />
<feature Name="FINDTP" Value="TRUE" />
<feature Name="DETAILS" Value="TRUE" />
</featurecoll>
<targetpropertycoll>
<targetproperty SiteIndex="0" PropertyGUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" ExternalPropertyGUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" MonitoringGUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" PortfolioGUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" OrderGUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" PropertyName="My Property" Address="1 Wherever Ave" City="Sometown" State="CA" ZipCode="99999" Latitude="30.111111" Longitude="-110.88888">
<georeferenced Address="My Property" City="Sometown" State="CA" ZipCode="99999" Latitude="30.111111" Longitude="-110.88888" Fips="" County="" PostalCity="" />
<searchdistancecoll SetID="0000" SetName="LendPort Collateral" MaxDistance="5280" />
<edrdatacoll>
<edrdata Name="REPORTCOST" Value="0.00" />
<edrdata Name="BORROWER" Value="" />
<edrdata Name="LOANTYPE" Value="Other" />
<edrdata Name="LOANNUMBER" Value="" />
<edrdata Name="PROPERTYTYPE" Value="" />
<edrdata Name="DESTHOST" Value="www.xxxxxxxxxxx.com" />
</edrdatacoll>
</targetproperty>
</targetpropertycoll>
</report>
</reportrequest>
This certainly has a root element.
What can be causing this seemingly bogus exception?
Try adding this as the first line of the file
<?xml version="1.0" encoding="UTF-8"?>
EDIT:
Change this
Dim xmlDoc As New XmlDocument()
xmlDoc.Load(xmlPath)
to this
Dim xmlDoc As New XmlDocument()
Try
xmlDoc.Load(xmlPath)
Catch ex As Exception
Dim xe As XElement
xe = XElement.Load(xmlPath)
Stop
End Try

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.

System.diagnostics logging issue + Wix application name change

In my application i have configured the Trace listener as below
"HelloWorld" is my AssemblyName and Namespace
<system.diagnostics>
<sources>
<source name="DebugCategory" switchName="DebugSwitch" switchType="System.Diagnostics.SourceSwitch">
<listeners>
<remove name="Default"/>
<!-- Add the listeners below -->
<add name="LogFile"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add name="Console" type="System.Diagnostics.ConsoleTraceListener" initializeData="true"/>
<add name="LogFile" type="HelloWorld.Diagnostics.FileLogTraceListener, HelloWorld" initializeData="HelloWorld.log" traceOutputOptions="DateTime" cycle="Month"/>
</sharedListeners>
While creating an installer using WIX, in my WIX file i will make the Target exe file from "HelloWorld.exe" to "MyWorld.exe" as below
<Component Id="MyWorld.exe" Guid="*">
<File Id="MyWorld.exe" Name="MyWorld.exe"
DiskId="1" Source="HelloWorld.exe" />
<Shortcut Id="HelloWorld.menu.exe" Name="Hello world application" Directory="McnMenu" Advertise="yes" WorkingDirectory="INSTAL32LLOCATION" />
</Component>
Since there is change in the EXE name, Tracelistener is not creating a log file.
Target name should be "Myworld.exe", If i revert the File element to
<File Id="HelloWorld.exe" Name="HelloWorld.exe" />
it works well
Can any one help me.
In this line of your .config file:
<add name="LogFile" type="HelloWorld.Diagnostics.FileLogTraceListener, HelloWorld" initializeData="HelloWorld.log" traceOutputOptions="DateTime" cycle="Month"/>
You have type="HelloWorld.Diagnostics.FileLogTraceListener, HelloWorld". That is a reference to a class in an assembly. The assembly name (the name of the file) is the part after the comma. Therefore your .config file requires the assembly (the executable in your case) to be named "HelloWorld".
To fix you can either leave the file name HelloWorld.exe (as you found) or change the .config file like so:
<add name="LogFile" type="HelloWorld.Diagnostics.FileLogTraceListener, MyWorld" initializeData="HelloWorld.log" traceOutputOptions="DateTime" cycle="Month"/>
Notice the MyWorld in the type after the comma.

Is setting "ASP.NET Impersonation" possible using WiX 3.x with IISExtension?

I have this component in my .wxs file:
<Component Id="Component.IisConfiguration" Guid="[COMPONENT_GUID_IISSITE]">
<iis:WebAppPool Id="IIS.AppPool" Name="[WEB_APP_POOL_NAME]" Identity="networkService" ManagedRuntimeVersion="v4.0" />
<iis:WebSite Id="IIS.WebSite" Description="[WEB_APP_NAME]" SiteId="[WEB_APP_SITEID]" Directory="TARGETDIR" >
<iis:WebApplication Id="IIS.WebSite.Application" Name="[WEB_APP_POOL_NAME]" WebAppPool="IIS.AppPool" />
<iis:WebAddress Id="IIS.WebSite.WebAddress.Port" Port="[WEB_APP_ADDRESS_PORT]" />
<iis:WebDirProperties Id="IIS.WebSite.Authentication" WindowsAuthentication="yes" />
</iis:WebSite>
</Component>
Is it possible to set "ASP.NET Impersonation" anywhere ?
It seems there's no out-of-the-box switch for this. You can have a custom action which calls:
appcmd set config /commit:WEBROOT/section:identity /impersonate:true
See this article for more information.
On the other hand, you can always set this setting on the application level, and use the standard XmlConfig element to modify the web.config file for this.

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.