DNN module uninstall how to remove settings from web.config - web-config

I have a DNN manifest file with this:
<configuration>
<nodes>
<node path="/configuration/appSettings" action="update" key="key" collision="overwrite">
<add key="LocalCurrencyCode" value="ARS"/>
</node>
and for uninstall I have this:
<uninstall>
<configuration>
<nodes>
<node path="/configuration/appsettings/add[#name='LocalCurrencyCode']" action="remove" />
However, when I uninstall the module the setting is not removed from web.config.
Can anyone see what I am doing wrong?

Fixed it:
<uninstall>
<configuration>
<nodes>
<node path="/configuration/appSettings/add[#key='InvoiceEmailSubject']" action="remove" />
Turns out that I needed "appSettings" because xml nodes are case sensitive. I also needed to use #key= as provided by Dexterity above.

I think you can try to replace #name with #key in <uninstall> section like this. There are no any name attribute in appsettings.
<node path="/configuration/appsettings/add[#key='LocalCurrencyCode']" action="remove" />

Related

Adding custom Dict to spell check extension of Libre office

I am trying to create and distribute a custom dictionary along with the primary one. I tried the steps mentioned here...
https://forum.openoffice.org/en/forum/viewtopic.php?f=7&t=33297
A user franx has provided step-by-step guide of ho to create a custom dictionary. But my question is how do I include both, primary and custom dict in the same extension. The custom dict should be installed in AppData path. For e.g.
C:\Users\Administrator\AppData\Roaming\LibreOffice\4\user\wordbook
Is this possible using .oxt file?
The "Dictionaries" sub-node of "ServiceManager" can have multiple entries.
If you already have one "HunSpellDic_mr_IN" then you can create one more "HunSpellDic_mr_IN_private" like this...
<?xml version="1.0" encoding="UTF-8"?>
<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="Linguistic" oor:package="org.openoffice.Office">
<node oor:name="ServiceManager">
<node oor:name="Dictionaries">
<node oor:name="HunSpellDic_mr_IN" oor:op="fuse">
<prop oor:name="Locations" oor:type="oor:string-list">
<value>%origin%/dicts/mr_IN.aff %origin%/dicts/mr_IN.dic</value>
</prop>
<prop oor:name="Format" oor:type="xs:string">
<value>DICT_SPELL</value>
</prop>
<prop oor:name="Locales" oor:type="oor:string-list">
<value>mr-IN</value>
</prop>
</node>
<node oor:name="HunSpellDic_mr_IN_private" oor:op="fuse">
<prop oor:name="Locations" oor:type="oor:string-list">
<value>%origin%/dicts/mr_IN_private.aff %origin%/dicts/mr_IN_private.dic</value>
</prop>
<prop oor:name="Format" oor:type="xs:string">
<value>DICT_SPELL</value>
</prop>
<prop oor:name="Locales" oor:type="oor:string-list">
<value>mr-IN</value>
</prop>
</node>
The actual location where the files like "*_private.dic" are stored is not known. The words from private files are still considered correct and hence the location does not matter. This will help you to group words into different categories.

Major Upgrade without uninstallation of Windows Service

I am really very sorry for being redundant. I have checked a lot of other posts in this site itself and perhaps some other sites. I am not able to get Major Upgrade working without uninstalling & reinstalling of service. I am changing the Product Code and Version and the UpgradeFileComponent is the component that is part of the Upgrade. All the remaining are the same as in 1.0.0. I am doing a POC and hence would like to make only this small change (not as a patch, but as a major upgrade). Following is my Product.wxs. I am not including the markup for the other things like ServiceAccountDlg, Variables.wxi or en-us.wxl, since it may make it really long. Can anyone please help me? I have already tried WIX_UPGRADE_DETECTED, UPGRADINGPRODUCTCODE and so on, but not able to get it working. Everytime, the service is getting uninstalled and reinstalled. I am verifying this in the following way. Once the service starts, it creates a log file in ProgramData and keeps appending it to every 5 seconds. During uninstallation of the MSI, I am deleting this log file and its folder. After the service gets reinstalled and restarts, the log file gets created again. With this I am able to figure out that the service is getting reinstalled always with the major upgrade. I only want the new file to be deployed without reinstalling the service or any other component being uninstalled. I have heard from some people that the toolset checks for changed files and reinstalls them only if there is a change. But this doesn't seem to be the case. I have tried using the Schedule attribute with various values also, but no luck. Any help will be really great. I have been trying this for so many days without any luck. Please let me know if any more info is required from me.
<?xml version="1.0" encoding="UTF-8"?>
<?include Variables.wxi ?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util='http://schemas.microsoft.com/wix/UtilExtension'>
<Product Id="$(var.ProductCode)" Name="$(var.ProductName)" Language="!(loc.LANG)" Version="$(var.ProductVersion)" Manufacturer=" MyCompany" UpgradeCode="$(var.UpgradeCode)">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" Id="*" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<!--<Upgrade Id="$(var.UpgradeCode)">
<UpgradeVersion OnlyDetect="yes" Minimum="1.0.0" Maximum="2.0.0" IncludeMinimum="yes" IncludeMaximum="yes" Property="NEWERFOUND" />
</Upgrade>-->
<InstallExecuteSequence>
<!--<RemoveExistingProducts After="InstallExecute" />
<DeleteServices>NOT UPGRADINGPRODUCTCODE</DeleteServices>-->
<!--<InstallServices>NOT UPGRADINGPRODUCTCODE,NOT WIX_UPGRADE_DETECTED</InstallServices>-->
<DeleteServices>NOT UPGRADINGPRODUCTCODE</DeleteServices>
</InstallExecuteSequence>
<Condition Message='This application only runs on Windows 7 or higher OS versions.'>
<![CDATA[Installed OR (VersionNT64 >= 601)]]>
</Condition>
<MediaTemplate />
<Property Id="MSIFASTINSTALL" Value="1"/>
<Property Id="MsiLogging" Value="v" />
<Property Id="MSIENFORCEUPGRADECOMPONENTRULES" Value="1" />
<Property Id="INSTALLDIR">
<RegistrySearch Id='MyCompanyMSISampleRegistry' Type='raw' Root='HKLM' Key='SOFTWARE\MyCompany\CustomApp' Name='INSTALLDIR' Win64='yes' />
</Property>
<WixVariable Id="WixUILicenseRtf" Value="License.rtf" />
<Feature Id='Complete' Title='Foobar 1.0' Description='The complete package.'
Display='expand' Level='1' ConfigurableDirectory='INSTALLDIR' AllowAdvertise='no' InstallDefault='local' Absent='disallow'>
<Feature Id="FileFeature" Title="File Feature" Level="1" AllowAdvertise='no' InstallDefault='local' Absent='disallow' Display='expand'>
<ComponentRef Id="FileComponent"/>
<ComponentRef Id="UpgradeFileComponent"/>
</Feature>
<Feature Id="ServiceFeature" Title="Service Feature" Level="1" AllowAdvertise='no' InstallDefault='local' Absent='disallow' Display='expand'>
<ComponentRef Id="ServiceComponent"/>
<ComponentRef Id="deleteFolder"/>
</Feature>
<Feature Id="RegistryFeature" Title="Registry Feature" Level="1" AllowAdvertise='no' InstallDefault='local' Absent='disallow' Display='expand'>
<ComponentRef Id="RegistryComponent"/>
</Feature>
<Feature Id='Documentation' Title='Description' Description='The instruction manual.' Level='2' AllowAdvertise='no' InstallDefault='followParent' Absent='disallow'>
<ComponentRef Id='Manual' />
</Feature>
</Feature>
<!--<UIRef Id="WixUI_Mondo"/>
<UIRef Id="WixUI_ErrorProgressText" />-->
<UI Id="MyWixUI_Mondo">
<UIRef Id="WixUI_Mondo" />
<DialogRef Id="ServiceAccountDlg" />
<Publish Dialog="LicenseAgreementDlg" Control="Next" Event="NewDialog" Value="ServiceAccountDlg" Order="2">LicenseAccepted = "1"</Publish>
<Publish Dialog="SetupTypeDlg" Control="Back" Event="NewDialog" Value="ServiceAccountDlg">1</Publish>
</UI>
<UIRef Id="WixUI_ErrorProgressText" />
<Icon Id="MyCompanyBanner.ico" SourceFile="Binary\MyCompanyBanner.ico" />
</Product>
<Fragment>
<Component Id='Manual' Guid='7470A2CD-B07C-4AB4-9152-8C6AA53FA0F7' Directory='INSTALLDIR'>
<File Id='Manual' Name='Manual.pdf' DiskId='1' Source='1.0.0\Manual.pdf' KeyPath='yes'>
<Shortcut Id="startmenuManual" Directory="DesktopFolder" Name="Instruction Manual" Advertise="yes" />
</File>
</Component>
</Fragment>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLDIR" Name="$(var.InstallFolderName)" />
</Directory>
<Directory Id="DesktopFolder" Name="Desktop" />
<Directory Id="CommonAppDataFolder">
<Directory Id="MyCompanyTestInstallerLogs" Name="MyCompanyTestInstallerLogs">
<Component Id="deleteFolder" Guid="323549D2-90B7-4D5D-8A36-EEA0ACCCC35E">
<RemoveFile Id="deleteServiceFile" Name="MyCompanyTestWinSvcLog.txt" On="both" Directory="MyCompanyTestInstallerLogs"/>
<RemoveFolder Directory="MyCompanyTestInstallerLogs" Id="MyCompanyTestInstallerLogs" On="both"/>
</Component>
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<Component Id="FileComponent" Directory="INSTALLDIR" Guid="F143BE3C-48D6-4138-B4E6-5CF44773CBA5" >
<File Id="SampleTextFile.txt" Name="Sample.txt" Source="$(var.Version)\Sample.txt" KeyPath="yes">
<Shortcut Id="startmenuSampleText" Directory="DesktopFolder" Name="MyCompany MSI Sample" WorkingDirectory='INSTALLDIR' Icon='MyCompanyBanner.ico' Advertise='yes' />
</File>
</Component>
</Fragment>
<Fragment>
<Component Id="UpgradeFileComponent" Directory="INSTALLDIR" Guid="4582597C-2CE0-451E-8B89-83BA4ABCE464">
<File Id="SampleXMLFile.xml" Name="Sample.xml" Source="$(var.Version)\Sample.xml" KeyPath="yes" />
</Component>
</Fragment>
<Fragment>
<Component Id='ServiceComponent' Directory="INSTALLDIR" Guid="AEA0E53F-3D70-4010-8592-9A01FE49344D">
<util:User Domain="[DOMAIN]" Id="svcUser" Name="[USER_NAME]" Password="[PASSWORD]" LogonAsService="yes" CreateUser="no"/>
<File Id='MyCompanyTestWinSvc' Name='MyCompanyTestWinSvc.exe' Source='Binary\MyCompanyTestWinSvc.exe' KeyPath='yes' />
<ServiceInstall Id="installMyCompanyTestWinSvc" Name="MyCompanyTestWinSvc" DisplayName="MyCompany Install Test Windows Service" Start="auto" ErrorControl="normal" Type="ownProcess" Account="[DOMAIN]\[USER_NAME]" Password="[PASSWORD]" />
<ServiceControl Id="sc_MyCompanyTestWinSvc" Name="MyCompanyTestWinSvc" Start="install" Stop="both" Remove="uninstall" Wait="yes" />
<ServiceControl Id="stopAndStartIIS" Name="IISADMIN" Start="uninstall" Stop="install" Wait="yes" />
<ServiceControl Id="stopAndStartSQL" Name="MSSQLSERVER" Start="uninstall" Stop="install" Wait="yes" />
</Component>
</Fragment>
<Fragment>
<Component Id="RegistryComponent" Directory="INSTALLDIR" Guid="8D8D93A4-09F5-4511-B291-720A7BC70529">
<RegistryValue Root='HKCU' Key='Software\[Manufacturer]\[ProductName]' Type='string' Value='' KeyPath='yes' />
</Component>
</Fragment>
</Wix>
Your MajorUpgrade does not specify where it is scheduled. As the docs say, the default is after InstallValidate and "This scheduling removes the installed product entirely before installing the upgrade product. " So your major upgrade will uninstall the older product completely, deleting the service, and then install your upgrade.
So you should start by having your major upgrade scheduled afterInstallExecute, because this will behave like an update on top of the existing installed product and the reference counting should minimize disruption to your service. This means that you must follow component rules, and increment the file versions of versioned files that need replacing.
Having said that, an upgrade is always an uninstall of the older product, so the ServiceControl in that older version will run, and Remove="both" might be the problem, deleting the service during the upgrade. So the original WiX ServiceControl matters.
Also, if the component rules haven't been followed an upgrade afterInstallValidate will work fine because it uninstalls everything then installs the new product. But if the component rules have not been followed in an upgrade afterInstallExecute the service component may be getting uninstalled (because of differing component ids), and there may well be other effects of not following the rules.
And to make it clear, you do not need a condition on delete services in your new install. I would start just by sequencing the major upgrade in a better place. Also, UPGRADINGPRODUCTCODE as a condition in your new upgrade has absolutely no effect. This property is set in the older product if it is being uninstalled with an upgrade. If you want to use this property it should be in the original product that is already installed, so if it's shipped and installed it is too late to alter that code now (without a patch and so on).
A more verbose MSI log would show more detail about what is happening and in what order, specify the string as voicewarmup.
I added this to my <InstallExecuteSequence>
<!-- http://stackoverflow.com/questions/15965539/how-to-only-stop-and-not-uninstall-windows-services-when-major-upgrade-in-wix don't change service config on upgrade -->
<DeleteServices>NOT UPGRADINGPRODUCTCODE</DeleteServices>
<InstallServices>NOT WIX_UPGRADE_DETECTED</InstallServices>
Seemed to work for me but I don't use this anymore due to changes in the product. You have to be sure you won't be changing the configuration of the service between versions since when you do change the configuration you do need to uninstall and install the services during the upgrade.
Services only get deleted on real unininstall (Rob [answerer of commented question] notes you don't need to condition around the Remove state since the install/uninstall state of the services is noted in the components)
And we only install the services on the first install.

How do you enable logging for CrmServiceClient in the Xrm Tooling toolkit?

I'm having issues trying to log in to a CRM Online organization through the use of the latest version of the Xrm Tooling nuget package using the connection string constructor from a custom powershell cmdlet.
I'm receiving a rather unhelpful "Unable to Login to Dynamics CRM" error message and am attempting to enable tracing to troubleshoot but have not been able to enable it by modifying the .dll.config file like the below (taken from an XrmToolbox issue on GitHub):
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.diagnostics>
<trace autoflush="true" />
<sources>
<source name="Microsoft.Xrm.Tooling.Connector.CrmServiceClient"
switchName="Microsoft.Xrm.Tooling.Connector.CrmServiceClient"
switchType="System.Diagnostics.SourceSwitch">
<listeners>
<add name="console" type="System.Diagnostics.DefaultTraceListener" />
<remove name="Default" />
<add name ="fileListener" />
</listeners>
</source>
<source name="Microsoft.Xrm.Tooling.CrmConnectControl"
switchName="Microsoft.Xrm.Tooling.CrmConnectControl"
switchType="System.Diagnostics.SourceSwitch">
<listeners>
<add name="console" type="System.Diagnostics.DefaultTraceListener" />
<remove name="Default" />
<add name ="fileListener" />
</listeners>
</source>
</sources>
<switches>
<!--
Possible values for switches: Off, Error, Warning, Info, Verbose
Verbose: includes Error, Warning, Info, Trace levels
Info: includes Error, Warning, Info levels
Warning: includes Error, Warning levels
Error: includes Error level
-->
<add name="Microsoft.Xrm.Tooling.Connector.CrmServiceClient" value="Verbose" />
<add name="Microsoft.Xrm.Tooling.CrmConnectControl" value="Verbose" />
<add name="Microsoft.Xrm.Tooling.WebResourceUtility" value="Verbose" />
</switches>
<sharedListeners>
<add name="fileListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="XRMToolingLogs.log" />
<!--<add name="eventLogListener" type="System.Diagnostics.EventLogTraceListener" initializeData="XRMTooling" />-->
</sharedListeners>
</system.diagnostics>
</configuration>
I was able to work around this by configuring the listener programmatically through:
Microsoft.Xrm.Tooling.Connector.TraceControlSettings.TraceLevel = System.Diagnostics.SourceLevels.All;
Microsoft.Xrm.Tooling.Connector.TraceControlSettings.AddTraceListener(new TextWriterTraceListener("log.txt"));
Which pointed me to the actual error which was that the CrmServiceClient was expecting a URL with the organization unique name instead of the URL name.

Web.config transformation and search and replace

I need to switch out an IP address in multiple WCF services in web.config. With web.config transformation, is there any way, besides specifying each an every address by xpath, to create a search and replace statement. E.g. switch out IP address 1.2.3.4 with 4.3.2.1 for all instances of 1.2.3.4
Say your Web.config is something like this (a simplified scenario, but // in XPath works everywhere):
<configuration>
<endpoint address="1.2.3.4" />
<endpoint address="1.2.3.4" />
<endpoint address="1.2.3.4" />
<endpoint address="1.2.3.4" />
</configuration>
then you will need something like this:
<?xml version="1.0"?>
<!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<replaceAll>
<endpontAddresses xdt:Locator="XPath(//endpoint[#address='1.2.3.4'])" xdt:Transform="SetAttributes(address)" address="4.3.2.1" />
</replaceAll>
</configuration>
NOTE: this XPath will look for every element in the whole Web.config and check whether given element has address attribute with value equal to "1.2.3.4".
If you need something more general then try this:
<?xml version="1.0"?>
<!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<replaceAll>
<endpontAddresses xdt:Locator="XPath(//*[#address='1.2.3.4'])" xdt:Transform="SetAttributes(address)" address="4.3.2.1" />
</replaceAll>
</configuration>
This will look at every XML element (due to the asterisk: *) and check whether it has address attribute with value equal to "1.2.3.4".
So this will work for a file like this:
<configuration>
<endpoint name="serviceA" address="1.2.3.4" />
<endpoint name="serviceB" address="1.2.3.4" />
<endpoint name="serviceC" address="1.2.3.4" />
<endpoint2 address="1.2.3.4" />
<endpoint3 address="1.2.3.4" />
<endpoint4 address="1.2.3.4" />
<innerSection>
<endpoint address="1.2.3.4" />
<anotherEndpoint address="1.2.3.4" />
<sampleXmlElement address="1.2.3.4" />
</innerSection>
</configuration>
Now if you want to limit substitutions to a certain section i.e. <system.serviceModel> then you can use an XPath like this:
<endpontAddresses xdt:Locator="XPath(/configuration/system.serviceModel//*[#address='1.2.3.4'])" xdt:Transform="SetAttributes(address)" address="4.3.2.1" />
This will update addresses only in <system.serviceModel> section
<configuration>
<endpoint name="serviceA" address="1.2.3.4" />
<endpoint name="serviceB" address="1.2.3.4" />
<endpoint name="serviceC" address="1.2.3.4" />
<endpoint2 address="1.2.3.4" />
<endpoint3 address="1.2.3.4" />
<endpoint4 address="1.2.3.4" />
<innerSection>
<endpoint address="1.2.3.4" />
<anotherEndpoint address="1.2.3.4" />
<sampleXmlElement address="1.2.3.4" />
</innerSection>
<system.serviceModel>
<endpoint name="serviceB" address="1.2.3.4" />
<endpoint name="serviceC" address="1.2.3.4" />
<endpoint2 address="1.2.3.4" />
<innerSection>
<endpoint address="1.2.3.4" />
<anotherEndpoint address="1.2.3.4" />
<sampleXmlElement address="1.2.3.4" />
</innerSection>
</system.serviceModel>
</configuration>
Give those a try and choose the one that suits your needs most.
NOTE: This has a limitation that you need to specify what is the name of the attribute that contains the IP (1.2.3.4) but I think its better to be explicit rather than have magic happen here. If you have many attibute names just repeat the

Web config transform on microsoft.identityModel - 'http://schemas.microsoft.com/XML-Document-Transform' attribute is not declared

I have got a Web.Release.config that is successfully transforming a connection string.
When I add a microsoft.identityModel section I get a warning saying
The 'http://schemas.microsoft.com/XML-Document-Transform' attribute is
not declared
And the transform doesnt work on that section.
What am I missing to get the transform to work?
Complete Web.Release.config here
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<connectionStrings>
<add name="MYNAME"
connectionString="metadata=res://*/Models.MYCOMPANY-Sales-Demo.csdl|res://*/Models.MYCOMPANY-Sales-Demo.ssdl|res://*/Models.MYCOMPANY-Sales-Demo.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=MYCOMPANYDemo;UID=MYCOMPANYDBUser;Password=********;multipleactiveresultsets=True;App=EntityFramework""
xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
</connectionStrings>
<system.web>
<compilation xdt:Transform="RemoveAttributes(debug)" />
</system.web>
<microsoft.identityModel>
<service>
<audienceUris>
<add value="http://MYCOMPANY-sales-demo.cloudapp.net/" xdt:Transform="Replace"/>
</audienceUris>
<federatedAuthentication>
<wsFederation realm="http://MYCOMPANY-sales-demo.cloudapp.net/" xdt:Transform="SetAttributes(realm)" />
</federatedAuthentication>
</service>
</microsoft.identityModel>
</configuration>
I've run into this also but have gotten it to work. What I did was a "RemoveAll" and an "Insert" instead of a replace/match:
<audienceUris>
<add xdt:Transform="RemoveAll" />
<add value="http://example.com/" xdt:Transform="Insert" />
</audienceUris>
When I do it that way I get the desired transform and output config file.
This appears to be working now with Visual Studio 2012 (v4.5.50709). I still get the 'attribute is not declared' warning in the editor, but the xdt:Transform="Replace" directive is working for me.