From 7e1d545e2901d399a7714d4443df079d44850827 Mon Sep 17 00:00:00 2001 From: Justin Kotalik <jukotali@microsoft.com> Date: Thu, 11 Apr 2019 21:25:54 -0700 Subject: [PATCH] Remove dependency on jscript in IISExpress installers (#8707) * Add a .gitignore --- eng/PatchConfig.props | 2 + .../Windows/AspNetCoreModule-Setup/.gitignore | 3 + .../ANCMIISExpressV1/ancm_iis_express.wxs | 158 +++++------------ .../ANCMIISExpressV2/ancm_iis_expressv2.wxs | 160 +++++------------- .../CustomAction/aspnetcoreCA.cpp | 133 +++++++++++++++ .../CustomAction/aspnetcoreCA.def | 2 + src/Installers/Windows/UpgradeLog.htm | Bin 0 -> 45142 bytes 7 files changed, 224 insertions(+), 234 deletions(-) create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/.gitignore create mode 100644 src/Installers/Windows/UpgradeLog.htm diff --git a/eng/PatchConfig.props b/eng/PatchConfig.props index dd96236f282..319d85992f5 100644 --- a/eng/PatchConfig.props +++ b/eng/PatchConfig.props @@ -51,6 +51,8 @@ Later on, this will be checked using this condition: </PropertyGroup> <PropertyGroup Condition=" '$(VersionPrefix)' == '2.2.5' "> <PackagesInPatch> + Microsoft.AspNetCore.AspNetCoreModule; + Microsoft.AspNetCore.AspNetCoreModuleV2; </PackagesInPatch> </PropertyGroup> diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/.gitignore b/src/Installers/Windows/AspNetCoreModule-Setup/.gitignore new file mode 100644 index 00000000000..06d8a1a8148 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/.gitignore @@ -0,0 +1,3 @@ +Debug/ +Win32/ +x64/ diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV1/ancm_iis_express.wxs b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV1/ancm_iis_express.wxs index 00a8af36cf6..6c60fedb04f 100644 --- a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV1/ancm_iis_express.wxs +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV1/ancm_iis_express.wxs @@ -348,66 +348,26 @@ Value=""[IISEXPRESS_INSTALL_PATH]appcmd.exe" set config -section:system.webServer/httpCompression /+"dynamicTypes.[\[]mimeType='text/event-stream',enabled='FALSE'[\]]" /apphostconfig:"[IISEXPRESS_APPHOST_CONFIG_TMP]""/> <CustomAction Id="CA_UPDATE_DYNAMIC_COMPRESSION_TMP" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/> - <!-- CA to add config section to applicationhost.config --> + <CustomAction Id="CA_ADD_CONFIGSECTION_PROPERTY" Property="CA_ADD_CONFIGSECTION" - Value="[IISEXPRESS_APPHOST_CONFIG];[IISEXPRESS_APPHOST_CONFIG_TMP]"/> - <CustomAction Id="CA_ADD_CONFIGSECTION" Script="jscript" Execute="deferred" Return="check" Impersonate="no"> - <![CDATA[ - var caData = Session.Property("CustomActionData"); - configfiles = caData.split(';'); - for (var i = 0; i < configfiles.length; i++) { - var configfile = configfiles[i]; - var xmlDoc = new ActiveXObject("Msxml2.DOMDocument"); - xmlDoc.async = false; - xmlDoc.preserveWhiteSpace = true; - xmlDoc.load(configfile ); - if (xmlDoc.parseError.errorCode == 0) { - xmlDoc.setProperty("SelectionLanguage", "XPath"); - var websvrNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]"); - if (websvrNode != null) { - var ancmNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]/section[@name=\"$(var.AspNetCoreSectionName)\"]"); - if (ancmNode == null) { - ancmNode = xmlDoc.createElement("section"); - ancmNode.setAttribute("name", "$(var.AspNetCoreSectionName)"); - ancmNode.setAttribute("overrideModeDefault", "Allow"); - websvrNode.appendChild(ancmNode); - xmlDoc.save(configfile ); - } - } - } - } - ]]> - </CustomAction> - - <!-- CA to remove config section to applicationhost.config --> + Value="[IISEXPRESS_APPHOST_CONFIG]"/> + <CustomAction BinaryKey="IISCustomActionDll" Id="CA_ADD_CONFIGSECTION" DllEntry="AddConfigSection" Execute="deferred" Return="check" Impersonate="no"/> + + <CustomAction Id="CA_ADD_CONFIGSECTION_PROPERTY_TMP" + Property="CA_ADD_CONFIGSECTION_TMP" + Value="[IISEXPRESS_APPHOST_CONFIG_TMP]"/> + <CustomAction BinaryKey="IISCustomActionDll" Id="CA_ADD_CONFIGSECTION_TMP" DllEntry="AddConfigSection" Execute="deferred" Return="check" Impersonate="no"/> + <CustomAction Id="CA_REMOVE_CONFIGSECTION_PROPERTY" - Property="CA_REMOVE_CONFIGSECTION" - Value="[IISEXPRESS_APPHOST_CONFIG];[IISEXPRESS_APPHOST_CONFIG_TMP]"/> - <CustomAction Id="CA_REMOVE_CONFIGSECTION" Script="jscript" Execute="deferred" Return="check" Impersonate="no"> - <![CDATA[ - var caData = Session.Property("CustomActionData"); - configfiles = caData.split(';'); - for (var i = 0; i < configfiles.length; i++) { - var configfile = configfiles[i]; - var xmlDoc = new ActiveXObject("Msxml2.DOMDocument"); - xmlDoc.async = false; - xmlDoc.preserveWhiteSpace = true; - xmlDoc.load(configfile ); - if (xmlDoc.parseError.errorCode == 0) { - xmlDoc.setProperty("SelectionLanguage", "XPath"); - var websvrNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]"); - if (websvrNode != null) { - var ancmNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]/section[@name=\"$(var.AspNetCoreSectionName)\"]"); - if (ancmNode != null) { - websvrNode.removeChild(ancmNode); - xmlDoc.save(configfile ); - } - } - } - } - ]]> - </CustomAction> + Property="CA_REMOVE_CONFIGSECTION" + Value="[IISEXPRESS_APPHOST_CONFIG]"/> + <CustomAction Id="CA_REMOVE_CONFIGSECTION" BinaryKey="IISCustomActionDll" DllEntry="RemoveConfigSection" Execute="deferred" Return="check" Impersonate="no" /> + + <CustomAction Id="CA_REMOVE_CONFIGSECTION_PROPERTY_TMP" + Property="CA_REMOVE_CONFIGSECTION_TMP" + Value="[IISEXPRESS_APPHOST_CONFIG_TMP]"/> + <CustomAction Id="CA_REMOVE_CONFIGSECTION_TMP" BinaryKey="IISCustomActionDll" DllEntry="RemoveConfigSection" Execute="deferred" Return="check" Impersonate="no" /> <?if $(var.Platform) = "x64" ?> <CustomAction Id="CA_UNLOCK_HANDLER32_PROPERTY" @@ -502,67 +462,25 @@ Value=""[IISEXPRESS_INSTALL_PATH32]appcmd.exe" set config -section:system.webServer/httpCompression /+"dynamicTypes.[\[]mimeType='text/event-stream',enabled='FALSE'[\]]" /apphostconfig:"[IISEXPRESS_APPHOST_CONFIG32]""/> <CustomAction Id="CA_UPDATE_DYNAMIC_COMPRESSION_TMP32" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/> - <!-- CA to add config section to applicationhost.config --> - <CustomAction Id="CA_ADD_CONFIGSECTION32_PROPERTY" - Property="CA_ADD_CONFIGSECTION32" - Value="[IISEXPRESS_APPHOST_CONFIG32];[IISEXPRESS_APPHOST_CONFIG_TMP32]"/> - <CustomAction Id="CA_ADD_CONFIGSECTION32" Script="jscript" Execute="deferred" Return="check" Impersonate="no"> - <!-- Warning LGHT1076: ICE03: String overflow. Orca.exe inspection shows the custom action value is populated correctly --> - <![CDATA[ - var caData = Session.Property("CustomActionData"); - configfiles = caData.split(';'); - for (var i = 0; i < configfiles.length; i++) { - var configfile = configfiles[i]; - var xmlDoc = new ActiveXObject("Msxml2.DOMDocument"); - xmlDoc.async = false; - xmlDoc.preserveWhiteSpace = true; - xmlDoc.load(configfile); - if (xmlDoc.parseError.errorCode == 0) { - xmlDoc.setProperty("SelectionLanguage", "XPath"); - var websvrNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]"); - if (websvrNode != null) { - var ancmNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]/section[@name=\"$(var.AspNetCoreSectionName)\"]"); - if (ancmNode == null) { - ancmNode = xmlDoc.createElement("section"); - ancmNode.setAttribute("name", "$(var.AspNetCoreSectionName)"); - ancmNode.setAttribute("overrideModeDefault", "Allow"); - websvrNode.appendChild(ancmNode); - xmlDoc.save(configfile); - } - } - } - } - ]]> - </CustomAction> - - <!-- CA to remove config section to applicationhost.config --> + <CustomAction Id="CA_ADD_CONFIGSECTION32_PROPERTY" + Property="CA_ADD_CONFIGSECTION32" + Value="[IISEXPRESS_APPHOST_CONFIG32]"/> + <CustomAction BinaryKey="IISCustomActionDll" Id="CA_ADD_CONFIGSECTION32" DllEntry="AddConfigSection" Execute="deferred" Return="check" Impersonate="no"/> + + <CustomAction Id="CA_ADD_CONFIGSECTION32_PROPERTY_TMP" + Property="CA_ADD_CONFIGSECTION32_TMP" + Value="[IISEXPRESS_APPHOST_CONFIG_TMP32]"/> + <CustomAction BinaryKey="IISCustomActionDll" Id="CA_ADD_CONFIGSECTION32_TMP" DllEntry="AddConfigSection" Execute="deferred" Return="check" Impersonate="no"/> + <CustomAction Id="CA_REMOVE_CONFIGSECTION32_PROPERTY" Property="CA_REMOVE_CONFIGSECTION32" - Value="[IISEXPRESS_APPHOST_CONFIG32];[IISEXPRESS_APPHOST_CONFIG_TMP32]"/> - <CustomAction Id="CA_REMOVE_CONFIGSECTION32" Script="jscript" Execute="deferred" Return="check" Impersonate="no"> - <![CDATA[ - var caData = Session.Property("CustomActionData"); - configfiles = caData.split(';'); - for (var i = 0; i < configfiles.length; i++) { - var configfile = configfiles[i]; - var xmlDoc = new ActiveXObject("Msxml2.DOMDocument"); - xmlDoc.async = false; - xmlDoc.preserveWhiteSpace = true; - xmlDoc.load(configfile); - if (xmlDoc.parseError.errorCode == 0) { - xmlDoc.setProperty("SelectionLanguage", "XPath"); - var websvrNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]"); - if (websvrNode != null) { - var ancmNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]/section[@name=\"$(var.AspNetCoreSectionName)\"]"); - if (ancmNode != null) { - websvrNode.removeChild(ancmNode); - xmlDoc.save(configfile); - } - } - } - } - ]]> - </CustomAction> + Value="[IISEXPRESS_APPHOST_CONFIG32]"/> + <CustomAction Id="CA_REMOVE_CONFIGSECTION32" BinaryKey="IISCustomActionDll" DllEntry="RemoveConfigSection" Execute="deferred" Return="check" Impersonate="no" /> + + <CustomAction Id="CA_REMOVE_CONFIGSECTION32_PROPERTY_TMP" + Property="CA_REMOVE_CONFIGSECTION32_TMP" + Value="[IISEXPRESS_APPHOST_CONFIG_TMP32]"/> + <CustomAction Id="CA_REMOVE_CONFIGSECTION32_TMP" BinaryKey="IISCustomActionDll" DllEntry="RemoveConfigSection" Execute="deferred" Return="check" Impersonate="no" /> <?endif?> <InstallExecuteSequence> @@ -581,6 +499,8 @@ <Custom Action="CA_SET_MODULE" After="CA_SET_MODULE_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom> <Custom Action="CA_ADD_CONFIGSECTION_PROPERTY" After="CA_SET_MODULE"><![CDATA[(NOT REMOVE)]]></Custom> <Custom Action="CA_ADD_CONFIGSECTION" After="CA_ADD_CONFIGSECTION_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom> + <Custom Action="CA_ADD_CONFIGSECTION_PROPERTY_TMP" After="CA_ADD_CONFIGSECTION"><![CDATA[(NOT REMOVE)]]></Custom> + <Custom Action="CA_ADD_CONFIGSECTION_TMP" After="CA_ADD_CONFIGSECTION_PROPERTY_TMP"><![CDATA[(NOT REMOVE)]]></Custom> <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION_PROPERTY" After="CA_ADD_CONFIGSECTION"><![CDATA[(NOT REMOVE)]]></Custom> <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION" After="CA_ADD_TRACE_PROVIDER_DEFINITION_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom> <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION_TMP_PROPERTY" After="CA_ADD_TRACE_PROVIDER_DEFINITION"><![CDATA[(NOT REMOVE)]]></Custom> @@ -591,6 +511,8 @@ <Custom Action="CA_REMOVE_MODULE" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_CONFIGSECTION_PROPERTY" Before="CA_REMOVE_CONFIGSECTION"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_CONFIGSECTION" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> + <Custom Action="CA_REMOVE_CONFIGSECTION_PROPERTY_TMP" Before="CA_REMOVE_CONFIGSECTION_TMP"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> + <Custom Action="CA_REMOVE_CONFIGSECTION_TMP" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION_PROPERTY" Before="CA_REMOVE_TRACE_PROVIDER_DEFINITION"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION_TMP_PROPERTY" Before="CA_REMOVE_TRACE_PROVIDER_DEFINITION_TMP"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> @@ -621,6 +543,8 @@ <Custom Action="CA_SET_MODULE32" After="CA_ADD_MODULE32_PROPERTY"><![CDATA[(NOT REMOVE AND IISEXPRESS_INSTALL_PATH32)]]></Custom> <Custom Action="CA_ADD_CONFIGSECTION32_PROPERTY" After="CA_SET_MODULE32"><![CDATA[(NOT REMOVE)]]></Custom> <Custom Action="CA_ADD_CONFIGSECTION32" After="CA_ADD_CONFIGSECTION32_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom> + <Custom Action="CA_ADD_CONFIGSECTION32_PROPERTY_TMP" After="CA_ADD_CONFIGSECTION32"><![CDATA[(NOT REMOVE)]]></Custom> + <Custom Action="CA_ADD_CONFIGSECTION32_TMP" After="CA_ADD_CONFIGSECTION32_PROPERTY_TMP"><![CDATA[(NOT REMOVE)]]></Custom> <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION32_PROPERTY" After="CA_ADD_CONFIGSECTION32"><![CDATA[(NOT REMOVE)]]></Custom> <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION32" After="CA_ADD_TRACE_PROVIDER_DEFINITION32_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom> <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION_TMP32_PROPERTY" After="CA_ADD_TRACE_PROVIDER_DEFINITION32"><![CDATA[(NOT REMOVE)]]></Custom> @@ -631,6 +555,8 @@ <Custom Action="CA_REMOVE_MODULE32" After="CA_REMOVE_MODULE32_PROPERTY"><![CDATA[(REMOVE~="ALL" AND IISEXPRESS_INSTALL_PATH32 AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_CONFIGSECTION32_PROPERTY" Before="CA_REMOVE_CONFIGSECTION32"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_CONFIGSECTION32" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> + <Custom Action="CA_REMOVE_CONFIGSECTION32_PROPERTY_TMP" Before="CA_REMOVE_CONFIGSECTION32_TMP"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> + <Custom Action="CA_REMOVE_CONFIGSECTION32_TMP" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION32_PROPERTY" Before="CA_REMOVE_TRACE_PROVIDER_DEFINITION32"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION32" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION_TMP32_PROPERTY" Before="CA_REMOVE_TRACE_PROVIDER_DEFINITION_TMP32"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV2/ancm_iis_expressv2.wxs b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV2/ancm_iis_expressv2.wxs index 12a2c887b81..5980137c835 100644 --- a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV2/ancm_iis_expressv2.wxs +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV2/ancm_iis_expressv2.wxs @@ -377,66 +377,25 @@ Value=""[IISEXPRESS_INSTALL_PATH]appcmd.exe" set config -section:system.webServer/httpCompression /+"dynamicTypes.[\[]mimeType='text/event-stream',enabled='FALSE'[\]]" /apphostconfig:"[IISEXPRESS_APPHOST_CONFIG_TMP]""/> <CustomAction Id="CA_UPDATE_DYNAMIC_COMPRESSION_TMP" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/> - <!-- CA to add config section to applicationhost.config --> <CustomAction Id="CA_ADD_CONFIGSECTION_PROPERTY" Property="CA_ADD_CONFIGSECTION" - Value="[IISEXPRESS_APPHOST_CONFIG];[IISEXPRESS_APPHOST_CONFIG_TMP]"/> - <CustomAction Id="CA_ADD_CONFIGSECTION" Script="jscript" Execute="deferred" Return="check" Impersonate="no"> - <![CDATA[ - var caData = Session.Property("CustomActionData"); - configfiles = caData.split(';'); - for (var i = 0; i < configfiles.length; i++) { - var configfile = configfiles[i]; - var xmlDoc = new ActiveXObject("Msxml2.DOMDocument"); - xmlDoc.async = false; - xmlDoc.preserveWhiteSpace = true; - xmlDoc.load(configfile ); - if (xmlDoc.parseError.errorCode == 0) { - xmlDoc.setProperty("SelectionLanguage", "XPath"); - var websvrNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]"); - if (websvrNode != null) { - var ancmNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]/section[@name=\"$(var.AspNetCoreSectionName)\"]"); - if (ancmNode == null) { - ancmNode = xmlDoc.createElement("section"); - ancmNode.setAttribute("name", "$(var.AspNetCoreSectionName)"); - ancmNode.setAttribute("overrideModeDefault", "Allow"); - websvrNode.appendChild(ancmNode); - xmlDoc.save(configfile ); - } - } - } - } - ]]> - </CustomAction> - - <!-- CA to remove config section to applicationhost.config --> + Value="[IISEXPRESS_APPHOST_CONFIG]"/> + <CustomAction BinaryKey="IISCustomActionDll" Id="CA_ADD_CONFIGSECTION" DllEntry="AddConfigSection" Execute="deferred" Return="check" Impersonate="no"/> + + <CustomAction Id="CA_ADD_CONFIGSECTION_PROPERTY_TMP" + Property="CA_ADD_CONFIGSECTION_TMP" + Value="[IISEXPRESS_APPHOST_CONFIG_TMP]"/> + <CustomAction BinaryKey="IISCustomActionDll" Id="CA_ADD_CONFIGSECTION_TMP" DllEntry="AddConfigSection" Execute="deferred" Return="check" Impersonate="no"/> + <CustomAction Id="CA_REMOVE_CONFIGSECTION_PROPERTY" - Property="CA_REMOVE_CONFIGSECTION" - Value="[IISEXPRESS_APPHOST_CONFIG];[IISEXPRESS_APPHOST_CONFIG_TMP]"/> - <CustomAction Id="CA_REMOVE_CONFIGSECTION" Script="jscript" Execute="deferred" Return="check" Impersonate="no"> - <![CDATA[ - var caData = Session.Property("CustomActionData"); - configfiles = caData.split(';'); - for (var i = 0; i < configfiles.length; i++) { - var configfile = configfiles[i]; - var xmlDoc = new ActiveXObject("Msxml2.DOMDocument"); - xmlDoc.async = false; - xmlDoc.preserveWhiteSpace = true; - xmlDoc.load(configfile ); - if (xmlDoc.parseError.errorCode == 0) { - xmlDoc.setProperty("SelectionLanguage", "XPath"); - var websvrNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]"); - if (websvrNode != null) { - var ancmNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]/section[@name=\"$(var.AspNetCoreSectionName)\"]"); - if (ancmNode != null) { - websvrNode.removeChild(ancmNode); - xmlDoc.save(configfile ); - } - } - } - } - ]]> - </CustomAction> + Property="CA_REMOVE_CONFIGSECTION" + Value="[IISEXPRESS_APPHOST_CONFIG]"/> + <CustomAction Id="CA_REMOVE_CONFIGSECTION" BinaryKey="IISCustomActionDll" DllEntry="RemoveConfigSection" Execute="deferred" Return="check" Impersonate="no" /> + + <CustomAction Id="CA_REMOVE_CONFIGSECTION_PROPERTY_TMP" + Property="CA_REMOVE_CONFIGSECTION_TMP" + Value="[IISEXPRESS_APPHOST_CONFIG_TMP]"/> + <CustomAction Id="CA_REMOVE_CONFIGSECTION_TMP" BinaryKey="IISCustomActionDll" DllEntry="RemoveConfigSection" Execute="deferred" Return="check" Impersonate="no" /> <?if $(var.Platform) = "x64" ?> <CustomAction Id="CA_UNLOCK_HANDLER32_PROPERTY" @@ -531,68 +490,25 @@ Value=""[IISEXPRESS_INSTALL_PATH32]appcmd.exe" set config -section:system.webServer/httpCompression /+"dynamicTypes.[\[]mimeType='text/event-stream',enabled='FALSE'[\]]" /apphostconfig:"[IISEXPRESS_APPHOST_CONFIG32]""/> <CustomAction Id="CA_UPDATE_DYNAMIC_COMPRESSION_TMP32" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/> - - <!-- CA to add config section to applicationhost.config --> <CustomAction Id="CA_ADD_CONFIGSECTION32_PROPERTY" - Property="CA_ADD_CONFIGSECTION32" - Value="[IISEXPRESS_APPHOST_CONFIG32];[IISEXPRESS_APPHOST_CONFIG_TMP32]"/> - <CustomAction Id="CA_ADD_CONFIGSECTION32" Script="jscript" Execute="deferred" Return="check" Impersonate="no"> - <!-- Warning LGHT1076: ICE03: String overflow. Orca.exe inspection shows the custom action value is populated correctly --> - <![CDATA[ - var caData = Session.Property("CustomActionData"); - configfiles = caData.split(';'); - for (var i = 0; i < configfiles.length; i++) { - var configfile = configfiles[i]; - var xmlDoc = new ActiveXObject("Msxml2.DOMDocument"); - xmlDoc.async = false; - xmlDoc.preserveWhiteSpace = true; - xmlDoc.load(configfile); - if (xmlDoc.parseError.errorCode == 0) { - xmlDoc.setProperty("SelectionLanguage", "XPath"); - var websvrNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]"); - if (websvrNode != null) { - var ancmNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]/section[@name=\"$(var.AspNetCoreSectionName)\"]"); - if (ancmNode == null) { - ancmNode = xmlDoc.createElement("section"); - ancmNode.setAttribute("name", "$(var.AspNetCoreSectionName)"); - ancmNode.setAttribute("overrideModeDefault", "Allow"); - websvrNode.appendChild(ancmNode); - xmlDoc.save(configfile); - } - } - } - } - ]]> - </CustomAction> - - <!-- CA to remove config section to applicationhost.config --> + Property="CA_ADD_CONFIGSECTION32" + Value="[IISEXPRESS_APPHOST_CONFIG32]"/> + <CustomAction BinaryKey="IISCustomActionDll" Id="CA_ADD_CONFIGSECTION32" DllEntry="AddConfigSection" Execute="deferred" Return="check" Impersonate="no"/> + + <CustomAction Id="CA_ADD_CONFIGSECTION32_PROPERTY_TMP" + Property="CA_ADD_CONFIGSECTION32_TMP" + Value="[IISEXPRESS_APPHOST_CONFIG_TMP32]"/> + <CustomAction BinaryKey="IISCustomActionDll" Id="CA_ADD_CONFIGSECTION32_TMP" DllEntry="AddConfigSection" Execute="deferred" Return="check" Impersonate="no"/> + <CustomAction Id="CA_REMOVE_CONFIGSECTION32_PROPERTY" Property="CA_REMOVE_CONFIGSECTION32" - Value="[IISEXPRESS_APPHOST_CONFIG32];[IISEXPRESS_APPHOST_CONFIG_TMP32]"/> - <CustomAction Id="CA_REMOVE_CONFIGSECTION32" Script="jscript" Execute="deferred" Return="check" Impersonate="no"> - <![CDATA[ - var caData = Session.Property("CustomActionData"); - configfiles = caData.split(';'); - for (var i = 0; i < configfiles.length; i++) { - var configfile = configfiles[i]; - var xmlDoc = new ActiveXObject("Msxml2.DOMDocument"); - xmlDoc.async = false; - xmlDoc.preserveWhiteSpace = true; - xmlDoc.load(configfile); - if (xmlDoc.parseError.errorCode == 0) { - xmlDoc.setProperty("SelectionLanguage", "XPath"); - var websvrNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]"); - if (websvrNode != null) { - var ancmNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]/section[@name=\"$(var.AspNetCoreSectionName)\"]"); - if (ancmNode != null) { - websvrNode.removeChild(ancmNode); - xmlDoc.save(configfile); - } - } - } - } - ]]> - </CustomAction> + Value="[IISEXPRESS_APPHOST_CONFIG32]"/> + <CustomAction Id="CA_REMOVE_CONFIGSECTION32" BinaryKey="IISCustomActionDll" DllEntry="RemoveConfigSection" Execute="deferred" Return="check" Impersonate="no" /> + + <CustomAction Id="CA_REMOVE_CONFIGSECTION32_PROPERTY_TMP" + Property="CA_REMOVE_CONFIGSECTION32_TMP" + Value="[IISEXPRESS_APPHOST_CONFIG_TMP32]"/> + <CustomAction Id="CA_REMOVE_CONFIGSECTION32_TMP" BinaryKey="IISCustomActionDll" DllEntry="RemoveConfigSection" Execute="deferred" Return="check" Impersonate="no" /> <?endif?> <InstallExecuteSequence> @@ -611,7 +527,9 @@ <Custom Action="CA_SET_MODULE" After="CA_SET_MODULE_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom> <Custom Action="CA_ADD_CONFIGSECTION_PROPERTY" After="CA_SET_MODULE"><![CDATA[(NOT REMOVE)]]></Custom> <Custom Action="CA_ADD_CONFIGSECTION" After="CA_ADD_CONFIGSECTION_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom> - <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION_PROPERTY" After="CA_ADD_CONFIGSECTION"><![CDATA[(NOT REMOVE)]]></Custom> + <Custom Action="CA_ADD_CONFIGSECTION_PROPERTY_TMP" After="CA_ADD_CONFIGSECTION"><![CDATA[(NOT REMOVE)]]></Custom> + <Custom Action="CA_ADD_CONFIGSECTION_TMP" After="CA_ADD_CONFIGSECTION_PROPERTY_TMP"><![CDATA[(NOT REMOVE)]]></Custom> + <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION_PROPERTY" After="CA_ADD_CONFIGSECTION_TMP"><![CDATA[(NOT REMOVE)]]></Custom> <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION" After="CA_ADD_TRACE_PROVIDER_DEFINITION_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom> <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION_TMP_PROPERTY" After="CA_ADD_TRACE_PROVIDER_DEFINITION"><![CDATA[(NOT REMOVE)]]></Custom> <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION_TMP" After="CA_ADD_TRACE_PROVIDER_DEFINITION_TMP_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom> @@ -621,6 +539,8 @@ <Custom Action="CA_REMOVE_MODULE" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_CONFIGSECTION_PROPERTY" Before="CA_REMOVE_CONFIGSECTION"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_CONFIGSECTION" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> + <Custom Action="CA_REMOVE_CONFIGSECTION_PROPERTY_TMP" Before="CA_REMOVE_CONFIGSECTION_TMP"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> + <Custom Action="CA_REMOVE_CONFIGSECTION_TMP" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION_PROPERTY" Before="CA_REMOVE_TRACE_PROVIDER_DEFINITION"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION_TMP_PROPERTY" Before="CA_REMOVE_TRACE_PROVIDER_DEFINITION_TMP"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> @@ -651,7 +571,9 @@ <Custom Action="CA_SET_MODULE32" After="CA_ADD_MODULE32_PROPERTY"><![CDATA[(NOT REMOVE AND IISEXPRESS_INSTALL_PATH32)]]></Custom> <Custom Action="CA_ADD_CONFIGSECTION32_PROPERTY" After="CA_SET_MODULE32"><![CDATA[(NOT REMOVE)]]></Custom> <Custom Action="CA_ADD_CONFIGSECTION32" After="CA_ADD_CONFIGSECTION32_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom> - <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION32_PROPERTY" After="CA_ADD_CONFIGSECTION32"><![CDATA[(NOT REMOVE)]]></Custom> + <Custom Action="CA_ADD_CONFIGSECTION32_PROPERTY_TMP" After="CA_ADD_CONFIGSECTION32"><![CDATA[(NOT REMOVE)]]></Custom> + <Custom Action="CA_ADD_CONFIGSECTION32_TMP" After="CA_ADD_CONFIGSECTION32_PROPERTY_TMP"><![CDATA[(NOT REMOVE)]]></Custom> + <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION32_PROPERTY" After="CA_ADD_CONFIGSECTION32_TMP"><![CDATA[(NOT REMOVE)]]></Custom> <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION32" After="CA_ADD_TRACE_PROVIDER_DEFINITION32_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom> <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION_TMP32_PROPERTY" After="CA_ADD_TRACE_PROVIDER_DEFINITION32"><![CDATA[(NOT REMOVE)]]></Custom> <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION_TMP32" After="CA_ADD_TRACE_PROVIDER_DEFINITION_TMP32_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom> @@ -661,6 +583,8 @@ <Custom Action="CA_REMOVE_MODULE32" After="CA_REMOVE_MODULE32_PROPERTY"><![CDATA[(REMOVE~="ALL" AND IISEXPRESS_INSTALL_PATH32 AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_CONFIGSECTION32_PROPERTY" Before="CA_REMOVE_CONFIGSECTION32"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_CONFIGSECTION32" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> + <Custom Action="CA_REMOVE_CONFIGSECTION32_PROPERTY_TMP" Before="CA_REMOVE_CONFIGSECTION32_TMP"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> + <Custom Action="CA_REMOVE_CONFIGSECTION32_TMP" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION32_PROPERTY" Before="CA_REMOVE_TRACE_PROVIDER_DEFINITION32"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION32" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION_TMP32_PROPERTY" Before="CA_REMOVE_TRACE_PROVIDER_DEFINITION_TMP32"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom> diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.cpp index 48d826f7202..7b43840c52a 100644 --- a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.cpp +++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.cpp @@ -2,6 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. #include <precomp.h> +#include <MsiQuery.h> +#include <msxml6.h> DECLARE_DEBUG_PRINT_OBJECT( "proxyCA.dll" ); @@ -40,6 +42,137 @@ struct COMPRESSION_MIME_TYPE COMPRESSION_MIME_TYPE gMimeTypes[] = { { L"text/event-stream", FALSE} }; +#define _HR_RET(hr) __pragma(warning(push)) \ + __pragma(warning(disable:26498)) /*disable constexpr warning */ \ + const HRESULT __hrRet = hr; \ + __pragma(warning(pop)) + +#define _GOTO_FINISHED() __pragma(warning(push)) \ + __pragma(warning(disable:26438)) /*disable avoid goto warning*/ \ + goto Finished \ + __pragma(warning(pop)) + +#define RETURN_IF_FAILED(hrr) do { _HR_RET(hrr); if (FAILED(__hrRet)) { hr = __hrRet; IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Exiting hr=0x%x", hr); return hr; }} while (0, 0) + +// Modifies the configSections to include the aspNetCore section +UINT +WINAPI +AddConfigSection( + IN MSIHANDLE handle +) +{ + HRESULT hr; + CComPtr<IXMLDOMDocument2> pXMLDoc; + VARIANT_BOOL variantResult; + IXMLDOMNode* webServerNode; + IXMLDOMNode* aspNetCoreNode; + IXMLDOMNode* tempNode; + IXMLDOMElement* element; + STRU customActionData; + + CComBSTR selectLanguage = SysAllocString(L"SelectionLanguage"); + CComBSTR xPath = SysAllocString(L"XPath"); + CComBSTR webServerPath = SysAllocString(L"//configuration/configSections/sectionGroup[@name=\"system.webServer\"]"); + CComBSTR aspNetCorePath = SysAllocString(L"//configuration/configSections/sectionGroup[@name=\"system.webServer\"]/section[@name=\"aspNetCore\"]"); + CComBSTR section = SysAllocString(L"section"); + CComBSTR name = SysAllocString(L"name"); + CComBSTR aspNetCore = SysAllocString(L"aspNetCore"); + CComBSTR overrideMode = SysAllocString(L"overrideModeDefault"); + CComBSTR allow = SysAllocString(L"Allow"); + + RETURN_IF_FAILED(CoInitialize(NULL)); + + hr = MsiUtilGetProperty(handle, TEXT("CustomActionData"), &customActionData); + + RETURN_IF_FAILED(hr = pXMLDoc.CoCreateInstance(__uuidof(DOMDocument60))); + + RETURN_IF_FAILED(hr = pXMLDoc->put_async(false)); + + RETURN_IF_FAILED(hr = pXMLDoc->load(CComVariant(customActionData.QueryStr()), &variantResult)); + + if (variantResult == VARIANT_FALSE) + { + return ERROR_SUCCESS; + } + + RETURN_IF_FAILED(hr = pXMLDoc->setProperty(selectLanguage, CComVariant(xPath))); + + RETURN_IF_FAILED(hr = pXMLDoc->selectSingleNode(webServerPath, &webServerNode)); + + RETURN_IF_FAILED(hr = pXMLDoc->selectSingleNode(aspNetCorePath, &aspNetCoreNode)); + + if (aspNetCoreNode == NULL) + { + RETURN_IF_FAILED(hr = pXMLDoc->createElement(section, &element)); + + RETURN_IF_FAILED(hr = element->setAttribute(name, CComVariant(aspNetCore))); + + RETURN_IF_FAILED(hr = element->setAttribute(overrideMode, CComVariant(allow))); + + RETURN_IF_FAILED(hr = webServerNode->appendChild(element, &tempNode)); + + RETURN_IF_FAILED(hr = pXMLDoc->save(CComVariant(customActionData.QueryStr()))); + } + + return ERROR_SUCCESS; +} + +// Modifies the configSections to remove the aspNetCore section +UINT +WINAPI +RemoveConfigSection( + IN MSIHANDLE handle +) +{ + HRESULT hr; + CComPtr<IXMLDOMDocument2> pXMLDoc; + VARIANT_BOOL variantResult; + IXMLDOMNode* webServerNode; + IXMLDOMNode* aspNetCoreNode; + IXMLDOMNode* tempNode; + STRU customActionData; + + CComBSTR selectLanguage = SysAllocString(L"SelectionLanguage"); + CComBSTR xPath = SysAllocString(L"XPath"); + CComBSTR webServerPath = SysAllocString(L"//configuration/configSections/sectionGroup[@name=\"system.webServer\"]"); + CComBSTR aspNetCorePath = SysAllocString(L"//configuration/configSections/sectionGroup[@name=\"system.webServer\"]/section[@name=\"aspNetCore\"]"); + CComBSTR section = SysAllocString(L"section"); + CComBSTR name = SysAllocString(L"name"); + CComBSTR aspNetCore = SysAllocString(L"aspNetCore"); + CComBSTR overrideMode = SysAllocString(L"overrideModeDefault"); + CComBSTR allow = SysAllocString(L"Allow"); + + RETURN_IF_FAILED(CoInitialize(NULL)); + + hr = MsiUtilGetProperty(handle, TEXT("CustomActionData"), &customActionData); + + RETURN_IF_FAILED(hr = pXMLDoc.CoCreateInstance(__uuidof(DOMDocument60))); + + RETURN_IF_FAILED(hr = pXMLDoc->put_async(false)); + + RETURN_IF_FAILED(hr = pXMLDoc->load(CComVariant(customActionData.QueryStr()), &variantResult)); + + if (variantResult == VARIANT_FALSE) + { + return ERROR_SUCCESS; + } + + RETURN_IF_FAILED(hr = pXMLDoc->setProperty(selectLanguage, CComVariant(xPath))); + + RETURN_IF_FAILED(hr = pXMLDoc->selectSingleNode(webServerPath, &webServerNode)); + + RETURN_IF_FAILED(hr = pXMLDoc->selectSingleNode(aspNetCorePath, &aspNetCoreNode)); + + if (aspNetCoreNode != NULL) + { + RETURN_IF_FAILED(webServerNode->removeChild(aspNetCoreNode, &tempNode)); + + RETURN_IF_FAILED(hr = pXMLDoc->save(CComVariant(customActionData.QueryStr()))); + } + + return ERROR_SUCCESS; +} + UINT WINAPI RegisterANCMCompressionCA( diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.def b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.def index 3518cde35f8..ed516a4392b 100644 --- a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.def +++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.def @@ -18,6 +18,8 @@ EXPORTS ExecuteCleanUpWindowsHotfixCA ScheduleRebootIfRequiredCA + AddConfigSection + RemoveConfigSection RegisterANCMCompressionCA CheckForServicesRunningCA diff --git a/src/Installers/Windows/UpgradeLog.htm b/src/Installers/Windows/UpgradeLog.htm new file mode 100644 index 0000000000000000000000000000000000000000..f327ebd6ec8c9266607c164392462b8d434be9e7 GIT binary patch literal 45142 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 F007P++K~VN literal 0 HcmV?d00001 -- GitLab