Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
0500372
:robot: add initial GitHub Copilot draft using agent mode with GPT-4.1
FH-Inway Jun 7, 2025
dffffb8
:robot: Add IIS Preload cmdlets to module exports
FH-Inway Jun 7, 2025
7182041
:robot: Add WebAdministration module availability checks
FH-Inway Jun 7, 2025
e4c8c33
:robot: Refactor Get-D365IISPreload to simplify property access for I…
FH-Inway Jun 7, 2025
61add6e
:robot: Add preload page retrieval to Get-D365IISPreload function
FH-Inway Jun 7, 2025
e7c488d
:robot: Add preload page setting
FH-Inway Jun 7, 2025
246fe63
:robot: Enhance documentation for Enable-D365IISPreload function to c…
FH-Inway Jun 7, 2025
2c59dd8
:robot: Add backup functionality for IIS Preload configuration in Ena…
FH-Inway Jun 8, 2025
f7145de
:robot: Add logic to remove initializationPage in Disable-D365IISPrel…
FH-Inway Jun 8, 2025
c55c7d7
:robot: Refactor Disable-D365IISPreload function to restore previous …
FH-Inway Jun 8, 2025
e922131
:robot: Fix condition to check PreloadEnabled value in Disable-D365II…
FH-Inway Jun 8, 2025
5884008
:robot: Update initializationPage property setting in Enable-D365IISP…
FH-Inway Jun 8, 2025
5f01f25
:robot: Refactor Get-D365IISPreload function to fix initializationPag…
FH-Inway Jun 8, 2025
43cc6b2
replace not working automatic reset/restore of initilizationPage with…
FH-Inway Jun 8, 2025
be5b721
:robot: Replace Write-Host with Write-PSFMessage for improved logging…
FH-Inway Jun 8, 2025
92bb0b3
ensure simple string values for startMode and idleTimeout variables
FH-Inway Jun 8, 2025
2d26bcd
:robot: use splatting
FH-Inway Jun 8, 2025
1c22d0b
fixing application initialization settings
FH-Inway Jun 9, 2025
8bd1557
Update author information and references in function documentation fo…
FH-Inway Jun 9, 2025
c3f0a1f
:robot: Add IIS Application Initialization feature management to prel…
FH-Inway Jun 9, 2025
c727e4e
move IIS Application Initialization feature check and installation af…
FH-Inway Jun 9, 2025
b5187ba
remove invalid tests
FH-Inway Jun 9, 2025
0dfecaf
update documentation and change encoding to UTF8 BOM
FH-Inway Jun 9, 2025
e2369e3
remove trailing space
FH-Inway Jun 9, 2025
3388270
🤖 Fix best practice deviations
FH-Inway Jun 9, 2025
052d430
:robot: Add IIS service restart after enabling/disabling preload sett…
FH-Inway Jun 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions d365fo.tools/bin/d365fo.tools-index.json
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,23 @@
"Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eDisable-D365Flight -FlightName DMFEnableAllCompanyExport\nDisables the flight DMFEnableAllCompanyExport",
"Syntax": "Disable-D365Flight [-FlightName] \u003cString\u003e [[-DatabaseServer] \u003cString\u003e] [[-DatabaseName] \u003cString\u003e] [[-SqlUser] \u003cString\u003e] [[-SqlPwd] \u003cString\u003e] [\u003cCommonParameters\u003e]"
},
{
"CommandName": "Disable-D365IISPreload",
"Description": "Reverts IIS Preload settings for the AOSService application:\n- Sets Application Pool Start Mode to OnDemand\n- Sets Idle Time-out to 0 (default)\n- Disables Preload on the AOSService website\n- Sets doAppInitAfterRestart to false (if Application Initialization is installed)\n- Restores previous IIS Preload configuration from backup if available\n- Restores or removes the initializationPage property as appropriate\n- Uninstalls IIS Application Initialization feature if it was not installed in the backup",
"Params": [

],
"Alias": "",
"Author": "Florian Hopfner (FH-Inway)",
"Synopsis": "Disables IIS Preload for the AOSService application pool and website.",
"Name": "Disable-D365IISPreload",
"Links": [
null,
null
],
"Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eDisable-D365IISPreload\nDisables IIS Preload for the AOSService application pool and website, restoring previous settings from backup if available.",
"Syntax": "Disable-D365IISPreload [\u003cCommonParameters\u003e]"
},
{
"CommandName": "Disable-D365MaintenanceMode",
"Description": "Sets the Dynamics 365 environment back into operating / running state after it has been in maintenance mode.",
Expand Down Expand Up @@ -1096,6 +1113,30 @@
"Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eEnable-D365Flight -FlightName DMFEnableAllCompanyExport\nEnables the flight DMFEnableAllCompanyExport",
"Syntax": "Enable-D365Flight [-FlightName] \u003cString\u003e [[-DatabaseServer] \u003cString\u003e] [[-DatabaseName] \u003cString\u003e] [[-SqlUser] \u003cString\u003e] [[-SqlPwd] \u003cString\u003e] [\u003cCommonParameters\u003e]"
},
{
"CommandName": "Enable-D365IISPreload",
"Description": "Configures IIS to preload the AOSService application, improving startup time after X++ compile.\n- Sets Application Pool Start Mode to AlwaysRunning\n- Sets Idle Time-out to 0\n- Enables Preload on the AOSService website\n- Sets doAppInitAfterRestart to true (if Application Initialization is installed)\n- Optionally sets the initializationPage to a custom base URL",
"Params": [
[
"BaseUrl",
"The base URL to use for the initializationPage setting in IIS Application Initialization.\r\nIf not provided, the function will attempt to determine the base URL automatically using Get-D365Url.\r\nExample: https://usnconeboxax1aos.cloud.onebox.dynamics.com",
"",
false,
"false",
""
]
],
"Alias": "",
"Author": "Florian Hopfner (FH-Inway)",
"Synopsis": "Enables IIS Preload for the AOSService application pool and website.",
"Name": "Enable-D365IISPreload",
"Links": [
null,
null
],
"Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eEnable-D365IISPreload\nThis will enable IIS Preload and set the initializationPage using the automatically detected base URL.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eEnable-D365IISPreload -BaseUrl \"https://usnconeboxax1aos.cloud.onebox.dynamics.com\"\nThis will enable IIS Preload and set the initializationPage to https://usnconeboxax1aos.cloud.onebox.dynamics.com/?mi=DefaultDashboard",
"Syntax": "Enable-D365IISPreload [[-BaseUrl] \u003cString\u003e] [\u003cCommonParameters\u003e]"
},
{
"CommandName": "Enable-D365MaintenanceMode",
"Description": "Sets the Dynamics 365 environment into maintenance mode to enable the user to update the license configuration",
Expand Down Expand Up @@ -2612,6 +2653,23 @@
"Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eGet-D365Flight\nThis will list all flights that are configured on the environment.\r\nIt will show the name and the enabled status.\nA result set example:\nFlightName Enabled FlightServiceId\r\n---------- ------- ---------------\r\nWHSWorkCancelForcedFlight 1 12719367\r\nTAMRebateGlobalEnableFeature 1 12719367\r\nEnablePerfInfoSimpleLoggerV2 1 12719367\r\nEnablePerfInfoLogODataV2 1 12719367\r\nEnablePerfInfoLogEtwRequestTableV2 1 12719367\r\nEnablePerfInfoCursorLayerV2 1 12719367\r\nEnablePerfInfoFormEngineLayerV2 1 12719367\r\nEnablePerfInfoMutexWaitLayerV2 1 12719367\r\nEnablePerfInfoSecurityLayerV2 1 12719367\r\nEnablePerfInfoSessionLayerV2 1 12719367\r\nEnablePerfInfoSQLLayerV2 1 12719367\r\nEnablePerfInfoXppContainerLayerV2 1 12719367\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eGet-D365Flight -FlightName WHSWorkCancelForcedFlight\nThis will list the flight with the specified name on the environment.\r\nIt will show the name and the enabled status.\nA result set example:\nFlightName Enabled FlightServiceId\r\n---------- ------- ---------------\r\nWHSWorkCancelForcedFlight 1 12719367\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eGet-D365Flight -FlightName WHS*\nThis will list the flight with the specified pattern on the environment.\r\nIt will filter the output to match the \"WHS*\" pattern.\r\nIt will show the name and the enabled status.\nA result set example:\nFlightName Enabled FlightServiceId\r\n---------- ------- ---------------\r\nWHSWorkCancelForcedFlight 1 12719367",
"Syntax": "Get-D365Flight [[-FlightName] \u003cString\u003e] [[-DatabaseServer] \u003cString\u003e] [[-DatabaseName] \u003cString\u003e] [[-SqlUser] \u003cString\u003e] [[-SqlPwd] \u003cString\u003e] [\u003cCommonParameters\u003e]"
},
{
"CommandName": "Get-D365IISPreload",
"Description": "Returns the current IIS Preload configuration for the AOSService application:\n- Application Pool Start Mode\n- Idle Time-out\n- Website Preload Enabled\n- doAppInitAfterRestart (if Application Initialization is installed)",
"Params": [

],
"Alias": "",
"Author": "Florian Hopfner (FH-Inway)",
"Synopsis": "Gets IIS Preload status for the AOSService application pool and website.",
"Name": "Get-D365IISPreload",
"Links": [
null,
null
],
"Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eGet-D365IISPreload\nRetrieves the IIS Preload configuration for the AOSService application pool and website.",
"Syntax": "Get-D365IISPreload [\u003cCommonParameters\u003e]"
},
{
"CommandName": "Get-D365InstalledHotfix",
"Description": "Get all relevant details for installed hotfixes on environments that are not on a \"One Version\" version. This cmdlet is deprecated since 2021-10-05 and will be removed by 2022-04-05.",
Expand Down
6 changes: 4 additions & 2 deletions d365fo.tools/d365fo.tools.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,13 @@
'Disable-D365User',
'Disable-D365Flight',
'Disable-D365Exception',

'Disable-D365IISPreload',
'Enable-D365Exception',
'Enable-D365MaintenanceMode',
'Enable-D365SqlChangeTracking',
'Enable-D365User',
'Enable-D365Flight',
'Enable-D365IISPreload',

'Export-D365BacpacModelFile',
'Export-D365Model',
Expand Down Expand Up @@ -114,7 +115,8 @@
'Get-D365ExternalIP',

'Get-D365Flight',

'Get-D365IISPreload',

'Get-D365JsonService',

'Get-D365InstalledHotfix',
Expand Down
174 changes: 174 additions & 0 deletions d365fo.tools/functions/disable-d365iispreload.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@

<#
.SYNOPSIS
Disables IIS Preload for the AOSService application pool and website.

.DESCRIPTION
Reverts IIS Preload settings for the AOSService application:
- Sets Application Pool Start Mode to OnDemand
- Sets Idle Time-out to 0 (default)
- Disables Preload on the AOSService website
- Sets doAppInitAfterRestart to false (if Application Initialization is installed)
- Restores previous IIS Preload configuration from backup if available
- Restores or removes the initializationPage property as appropriate
- Uninstalls IIS Application Initialization feature if it was not installed in the backup

.EXAMPLE
PS C:\> Disable-D365IISPreload

Disables IIS Preload for the AOSService application pool and website, restoring previous settings from backup if available.

.NOTES
Author: Florian Hopfner (FH-Inway)
Based on Denis Trunin's article "Enable IIS Preload to Speed Up Restart After X++ Compile" (https://www.linkedin.com/pulse/enable-iis-preload-speed-up-restart-after-x-compile-denis-trunin-86j5c)
Written with GitHub Copilot GPT-4.1, mostly in agent mode. See commits for prompts.

.LINK
Get-D365IISPreload

.LINK
Enable-D365IISPreload
#>
function Disable-D365IISPreload {
[CmdletBinding()]
param ()

if (-not (Get-Module -ListAvailable -Name WebAdministration)) {
Write-PSFMessage -Level Warning -Message "The 'WebAdministration' module is not installed. Please install it with: Install-WindowsFeature -Name Web-WebServer -IncludeManagementTools or Install-Module -Name WebAdministration -Scope CurrentUser"
return
}

Import-Module WebAdministration -ErrorAction Stop

$appPool = "AOSService"
$site = "AOSService"

# Set default values first
$startMode = 'OnDemand'
$idleTimeout = [TimeSpan]::Zero
$preloadEnabled = $false
$doAppInitAfterRestart = 'False'
$preloadPage = $null

# Try to restore previous IIS Preload configuration from backup if available
$backupDir = Join-Path $Script:DefaultTempPath "IISConfigBackup"
$backupFile = $null
if (Test-Path $backupDir) {
$backupFiles = Get-ChildItem -Path $backupDir -Filter 'IISPreloadConfig.*.json' | Sort-Object LastWriteTime -Descending
if ($backupFiles) {
$backupFile = $backupFiles[0].FullName
}
}
if ($backupFile) {
Write-PSFMessage -Level Host -Message "Restoring IIS Preload configuration from backup: $backupFile"
$preloadConfig = Get-Content $backupFile | ConvertFrom-Json
if ($preloadConfig.StartMode) { $startMode = $preloadConfig.StartMode }
if ($preloadConfig.IdleTimeout) { $idleTimeout = $preloadConfig.IdleTimeout }
if ($null -ne $preloadConfig.PreloadEnabled) { $preloadEnabled = $preloadConfig.PreloadEnabled }
if ($preloadConfig.DoAppInitAfterRestart) { $doAppInitAfterRestart = $preloadConfig.DoAppInitAfterRestart }
if ($preloadConfig.PreloadPage) { $preloadPage = $preloadConfig.PreloadPage }
# Uninstall IIS Application Initialization feature if it was not installed in the backup
if ($preloadConfig.IISApplicationInitFeature -eq 'Not installed') {
Write-PSFMessage -Level Host -Message "Uninstalling IIS Application Initialization feature (Web-AppInit) as per backup state."
try {
Uninstall-WindowsFeature -Name Web-AppInit -Confirm:$false | Out-Null
} catch {
Write-PSFMessage -Level Warning -Message "Failed to uninstall IIS Application Initialization feature. $_"
}
}
}

# Set Application Pool Start Mode and Idle Time-out
$setAppPoolStartModeParams = @{
Path = "IIS:\AppPools\$appPool"
Name = 'startMode'
Value = $startMode
}
Write-PSFMessage -Level Verbose -Message "Setting Application Pool '$appPool' startMode to '$startMode'"
Set-ItemProperty @setAppPoolStartModeParams
$setAppPoolIdleTimeoutParams = @{
Path = "IIS:\AppPools\$appPool"
Name = 'processModel.idleTimeout'
Value = $idleTimeout
}
Write-PSFMessage -Level Verbose -Message "Setting Application Pool '$appPool' idleTimeout to '$idleTimeout'"
Set-ItemProperty @setAppPoolIdleTimeoutParams
$setSitePreloadParams = @{
Path = "IIS:\Sites\$site"
Name = 'applicationDefaults.preloadEnabled'
Value = $preloadEnabled
}
Write-PSFMessage -Level Verbose -Message "Setting Site '$site' applicationDefaults.preloadEnabled to '$preloadEnabled'"
Set-ItemProperty @setSitePreloadParams
try {
$setDoAppInitParams = @{
pspath = "MACHINE/WEBROOT/APPHOST/$site"
filter = 'system.webServer/applicationInitialization'
name = 'doAppInitAfterRestart'
value = $doAppInitAfterRestart
ErrorAction = 'Stop'
}
Write-PSFMessage -Level Verbose -Message "Setting Site '$site' doAppInitAfterRestart to '$doAppInitAfterRestart'"
Set-WebConfigurationProperty @setDoAppInitParams
} catch {
Write-PSFMessage -Level Verbose -Message "Application Initialization not installed or not available. Skipping doAppInitAfterRestart."
}

# Reset or remove initializationPage setting
$getInitPagesParams = @{
pspath = 'MACHINE/WEBROOT/APPHOST'
filter = 'system.webServer/applicationInitialization'
name = '.'
location = $site
ErrorAction = 'Stop'
}
$initPages = Get-WebConfigurationProperty @getInitPagesParams
if ($initPages -and $initPages.Collection -and $initPages.Collection.Count -gt 0) {
$currentPreloadPage = $initPages.Collection[0].initializationPage
}
if ($currentPreloadPage) {
if ($preloadPage -and $preloadPage -ne "Not configured" -and $preloadPage -ne "Not available") {
try {
Write-PSFMessage -Level Verbose -Message "Setting Site '$site' initializationPage to '$preloadPage'"
$setInitPageParams = @{
pspath = "MACHINE/WEBROOT/APPHOST/$site"
filter = 'system.webServer/applicationInitialization'
name = '.'
value = @{ initializationPage = $preloadPage }
AtElement = @{ initializationPage = $currentPreloadPage }
ErrorAction = 'Stop'
}
Set-WebConfigurationProperty @setInitPageParams
} catch {
Write-PSFMessage -Level Verbose -Message "Preload page $preloadPage cannot be set. Application Initialization may not be installed or not available. Skipping initializationPage."
}
} else {
try {
Write-PSFMessage -Level Verbose -Message "Removing initializationPage from Site '$site'"
if ($currentPreloadPage) {
$removeInitPageParams = @{
pspath = "MACHINE/WEBROOT/APPHOST/$site"
filter = 'system.webServer/applicationInitialization'
name = '.'
AtElement = @{ initializationPage = $currentPreloadPage }
ErrorAction = 'Stop'
}
Remove-WebConfigurationProperty @removeInitPageParams
}
} catch {
Write-PSFMessage -Level Verbose -Message "Failed to remove initializationPage from Site '$site'. It may not exist."
}
}
}

Write-PSFMessage -Level Host -Message "IIS Preload disabled for $site."

# Restart IIS service to apply changes
try {
Write-PSFMessage -Level Host -Message "Restarting IIS service (W3SVC) to apply changes..."
Restart-Service -Name 'W3SVC' -Force -ErrorAction Stop
Write-PSFMessage -Level Host -Message "IIS service restarted successfully."
} catch {
Write-PSFMessage -Level Warning -Message "Failed to restart IIS service (W3SVC): $_"
}
}
Loading
Loading