Disclaimer: I do not accept responsibility for any issues arising from scripts being run without adequate understanding. It is the user's responsibility to review and assess any code before execution. More information

Upgrading Windows Server 2012 R2 to 2019 with Dynamics CRM 8.2 : Tip Toe though the Tulips 🌷


I was facing a challenging upgrade scenario: upgrading from Windows Server 2012 R2 to Server 2019 on an Azure VM. This server was running in Azure, which meant I had no access to the hypervisor, making an in-place upgrade the only viable option to preserve all settings. The server was also running Dynamics CRM 8.2, which added another layer of complexity.

Critical Pre-Upgrade Step: Backing Up IIS Configuration

Before starting ANY upgrade, backing up the IIS configuration is absolutely critical. If you don't have an IIS backup, you won't be able to restore the configuration after an offline upgrade. Here's what I should have done (and what you must do):

Backing Up IIS Configuration:

# Create a backup folder with timestamp
$backupDate = Get-Date -Format "yyyyMMdd_HHmmss"
$backupPath = "C:\IIS_Backup_$backupDate"
New-Item -ItemType Directory -Path $backupPath

# Backup IIS configuration using appcmd
C:\Windows\System32\inetsrv\appcmd.exe add backup "PreUpgrade_$backupDate"

# Manual backup of critical files
Copy-Item "C:\Windows\System32\inetsrv\config\applicationHost.config" "$backupPath\applicationHost.config"
Copy-Item "C:\Windows\System32\inetsrv\config\administration.config" "$backupPath\administration.config"

# Export application pool configurations
Import-Module WebAdministration
Get-ChildItem IIS:\AppPools | ForEach-Object {
    $poolName = $_.Name
    $poolConfig = Get-ItemProperty "IIS:\AppPools\$poolName" -Name *
    $poolConfig | Export-Clixml "$backupPath\AppPool_$poolName.xml"
}

# Document service accounts (you'll need passwords later!)
Get-ChildItem IIS:\AppPools | Select Name, @{n='Identity';e={$_.processModel.userName}} | 
    Export-Csv "$backupPath\AppPoolIdentities.csv"

Critical Note: Document all service account passwords - you'll need them if you have to recreate the application pools!

The Online vs Offline Upgrade Decision

When upgrading a server in Azure, you have two options:

Online Upgrade:

  • Start the upgrade and let it run with network connectivity
  • Problem: If you're using a cloud provider like Azure, you get no hypervisor access
  • During the upgrade, you cannot monitor the setup process
  • RDP and Bastion Host will show "unstable connection" or be completely unavailable
  • You're flying blind for 90+ minutes

Offline Upgrade (My Preference):

I personally prefer to perform an offline upgrade and fix IIS after the fact. Here's why:

  • Mount the drive in Hyper-V on a different VM to monitor progress
  • You can see exactly what's happening during the upgrade
  • You can intervene if something goes wrong
  • Yes, you'll have to fix IIS afterwards, but at least you know what happened during the upgrade

My initial plan was the offline approach: mount the drive in Hyper-V on a different virtual machine to monitor the upgrade process. However, this meant the server would be offline and not on the network during the upgrade. The upgrade process took about 90 minutes.

The First Major Problem: Missing Application Pools

After completing the offline upgrade, I discovered a critical issue: all the IIS application pools that ran as network service accounts had disappeared. My assessment was that because I'd upgraded the server off the network, it couldn't look up the service accounts, so it removed the application pools entirely.

This made sense - IIS application pools running as Network Service or custom domain accounts require network access to authenticate. When IIS worker processes run as Network Service, they access the network as the machine account and need to communicate with the domain controller. By mounting the drive offline to monitor the upgrade, the server lost this critical network connectivity.

Discovering Compatibility Issues

While researching solutions, I discovered another major concern: Microsoft Dynamics 365 CRM version 8.2 does NOT officially support Windows Server 2019. The latest supported Windows Server version for Dynamics 8.2 is Windows Server 2016. Multiple sources confirmed that Dynamics 365 on-premises versions 8.2 and 9.0 do not yet officially support Windows Server 2019.

I also learned that Windows Server 2016's extended support doesn't end until January 12, 2027 (not November 2025 as I initially thought), giving more runway than expected for that upgrade path.

The Azure VM Revelation

An important clarification emerged: my virtual machines were actually in Azure (not on-premises), but they depended on an older on-premises CRM. This actually put me in a better position - VMs hosted in Azure automatically get Extended Security Updates FREE until October 2026. For Windows Server 2012 and Windows Server 2012 R2 virtual machines on Azure, ESU updates are automatically unlocked without needing to deploy ESU keys or licensing preparation packages.

The Recovery Challenge: BitLocker and Boot Issues

When I tried to recover from a snapshot, I discovered I couldn't boot from it at all. When attempting to boot from Hyper-V in a VM, I was asked for BitLocker to be connected to a USB drive, but got no options to enter a BitLocker key. The snapshot contained a BitLocker-encrypted disk with TPM/encryption keys tied to the original VM, making it impossible to boot outside the Azure environment.

This meant I was stuck with the Server 2019 disk that would boot, leaving me with a potentially unsupported configuration.

Fixing the Broken System

First Issue: Assembly Loading Errors

After the upgrade, I encountered this error:

Monitoring runtime failed: Exception: Could not load file or assembly 'Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies.

Even though the file existed in C:\Program Files\Microsoft Dynamics CRM\Server\bin, the .NET runtime couldn't load it due to GAC (Global Assembly Cache) issues after the upgrade.

The fix that worked:

# Install GAC utility
[System.Reflection.Assembly]::LoadFrom("C:\Program Files\Microsoft Dynamics CRM\Server\bin\Newtonsoft.Json.dll")
[System.Reflection.Assembly]::LoadWithPartialName("System.EnterpriseServices")
$publish = New-Object System.EnterpriseServices.Internal.Publish
$publish.GacInstall("C:\Program Files\Microsoft Dynamics CRM\Server\bin\Newtonsoft.Json.dll")

Second Issue: Missing Application Pools

After fixing the assembly issue, I still had missing application pools with errors about "The system cannot find the path specified" when trying to access DirectoryServices.

The complete fix I discovered:

  1. Create backups in C:\Windows\System32\inetsrv\config of the old administration and application files

  2. Copy configuration files from C:\inetpub\history\CFGHISTORY_[timestamp]\ to C:\Windows\System32\inetsrv\config:

    • applicationHost.config
    • administration.config
  3. Fix the IIS version mismatch:

    • Open administration.config in Notepad
    • Find and replace version 8.5 (Windows Server 2012 R2 IIS) with 10.0 (Windows Server 2019 IIS)
    • Save the file
  4. Restart IIS: iisreset /restart

After these steps, IIS started properly, all application pools were restored with their service accounts intact, directory linkages were preserved, and CRM smoke tests passed - everything showed green!

Critical Post-Fix Step: Installing Windows Updates

After fixing the IIS issues, it's crucial to immediately install the latest Windows updates, updates, and hotfixes to ensure the system is kept up-to-date. This step is often overlooked but is essential for security and stability:

# Check for updates
Start-Process ms-settings:windowsupdate

# Or use PowerShell (requires PSWindowsUpdate module)
Install-Module PSWindowsUpdate -Force
Get-WindowsUpdate
Install-WindowsUpdate -AcceptAll -AutoReboot

# For Server Core or automated updates
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
Install-Module PSWindowsUpdate -Force
Get-WUInstall -AcceptAll -IgnoreReboot

# Don't forget .NET Framework updates
# Check current version
Get-ItemProperty "HKLM:SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\" | Select Release, Version

# Install cumulative updates for .NET Framework
# These are critical for CRM functionality

Important: After installing updates, test CRM functionality again. Some Windows updates can affect .NET Framework behavior or IIS settings.

Planning the CRM Upgrade

With the system stable and updated, I planned to upgrade CRM next. An important discovery: I needed to download the official ISO for Dynamics 365 v9 from VLSC (Volume License Service Center) as it includes the product key embedded. If I downloaded the public copy, I would need to supply a product key which wouldn't be found in the standard portals.

My upgrade path would be:

  1. Install version 9.0 base
  2. Apply latest 9.0 Cumulative Update
  3. Upgrade to 9.1 base
  4. Apply latest 9.1 Cumulative Update

The SQL Server Prerequisites Discovery

I discovered another critical prerequisite often overlooked: if your CRM is out of date, there's a high chance your SQL is also out of date. The prerequisites for CRM 9.x require SQL Server 2016 as a minimum. In my particular case, I didn't have that, so SQL required an upgrade to the minimum requirement version, which included upgrading the base SQL platform and then each individual instance if applicable.

The correct upgrade sequence should be:

  1. SQL Server upgrade (to minimum 2016)
  2. Verify SQL functioning with CRM 8.2
  3. CRM 8.2 → 9.0 base
  4. Apply 9.0 latest CU
  5. CRM 9.0 → 9.1 base
  6. Apply 9.1 latest CU

The Reality Check: What "Unsupported" Really Means

I came to an important realization: the support situation didn't really matter for my scenario. I was already running unsupported software (Server 2012 R2 was out of support since October 2023), and Microsoft wouldn't help anyway.

Using Server 2019 and SQL 2019 collects quite a few flags for "not supported," but I had to be realistic about what I was expecting support for. If you're using Dynamics CRM, there's a chance it's not being used as a standalone product - it's being integrated with a larger product.

Microsoft will support their software, but not necessarily the ongoing integrations and dependencies. Even with Microsoft support, depending on your exact configuration and integration, they may not be able to help. Microsoft cannot reverse engineer how your solution works if you're not sure yourself. The "Microsoft support" you might be banking on might not be the failsafe you expect.

Key Lessons Learned

  1. Always backup IIS configuration before upgrading - Without this, you cannot restore application pools after an offline upgrade
  2. Choose offline upgrade for visibility - I'd rather fix IIS afterwards than fly blind for 90 minutes
  3. Never do offline upgrades without expecting to fix domain-authenticated services - The server needs network connectivity to validate service accounts
  4. Install all Windows updates immediately after fixing issues - Security and stability depend on being fully patched
  5. Check ALL prerequisites before starting - SQL Server version requirements can catch you off guard
  6. IIS configuration version mismatches must be manually corrected after OS upgrades
  7. "Supported" vs "Unsupported" is largely academic when your real issues are in customizations and integrations that Microsoft won't help with anyway

Conclusion

My pragmatic approach was to make it work, make it stable, and document it well. Running newer "unsupported" versions (Server 2019 + SQL 2019 + CRM 9.1) while maintaining good documentation and understanding the integrations was more sustainable than staying on old "supported" versions and expecting Microsoft to solve complex, customized system issues.

The real questions weren't "Is it supported?" but rather:

  • Is it stable?
  • Is it secure?
  • Is it maintainable by my team?
  • Does it meet business needs?
  • Can I keep it running until ready to modernize?

This journey taught me that in the real world of complex enterprise systems, self-sufficiency and good documentation trump official support status every time. And sometimes, an offline upgrade with known fixes is better than an online upgrade where you're flying blind.

Previous Post Next Post

نموذج الاتصال