It's happened to almost everyone. Someone installs Evaluation Edition and now you need to upgrade it to a licensed copy using "Edition Upgrade" in the SQL Server installer. Microsoft would have you think this is easy even if the copy has expired but the truth is far more difficult.

First of all, how do you find this has happened? Well the service will be dead and it won't start.

And if you open the ERRORLOG manually you'll see that it has expired.

Great! Now to do the Edition Upgrade. Bear with me… this will only take a second…

Welcome to the dumpster fire. What's going on? Well, one or two things.

The first - which I saw happen in the real world but not in my test environment - is that Setup might try to start the SQL Server service as part of a health check before upgrading the edition. This is documented here however my real-world scenario failed multiple additional health checks.

You'll be able to determine if this happened by opening the Detail.txt file in the newest folder in C:\Program Files\Microsoft SQL Server\130\Setup Bootstrap\Log. If a rule check failed, you will need to start running Setup from the command line like so:

"C:\Program Files\Microsoft SQL Server\130\Setup Bootstrap\SQLServer2016\setup.exe" ^
/Q /ACTION=EDITIONUPGRADE /SKIPRULES= Engine_SqlEngineHealthCheck Engine_OnlySupportedFeaturesUsedCheckSystem ^
Engine_OnlySupportedFeaturesUsedCheckUser /IAcceptSQLServerLicenseTerms /PID= XXXXX-XXXXX-XXXXX-XXXXX

Note 1: You specify multiple SkipRules with spaces.

Note 2: In the GUI you can upgrade directly to Developer Edition. I couldn't see how to do that from the command-line. It seems to only take a PID. You might be able to extract the PID from a Developer ISO.

Now the problem when you follow Microsoft's instructions (from 2008… so 9 years ago with no updates despite numerous releases) is that this still won't work - it will hang. You will be able to find the hang point at the bottom of Detail.txt again.

(01) 2018-01-31 20:58:14 Slp: Sco: Attempting to start service MSSQLSERVER
(01) 2018-01-31 20:58:14 Slp: Sco: Attempting to open SC Manager
(01) 2018-01-31 20:58:14 Slp: Sco: Attempting to open service handle for service MSSQLSERVER
(01) 2018-01-31 20:58:14 Slp: Sco: Service MSSQLSERVER started
(01) 2018-01-31 20:58:14 Slp: Sco: Attempting to close service handle for service MSSQLSERVER
(01) 2018-01-31 20:58:14 Slp: Sco: Attempting to close SC Manager
(01) 2018-01-31 20:58:14 SQLEngine: --SqlServerServiceSCM: Started Engine service successfully
(01) 2018-01-31 20:58:14 Slp: Sco: Attempting to get service process id for service MSSQLSERVER
(01) 2018-01-31 20:58:14 Slp: Sco: Attempting to open SC Manager
(01) 2018-01-31 20:58:14 Slp: Sco: Attempting to open service handle for service MSSQLSERVER
(01) 2018-01-31 20:58:14 Slp: Invoking QueryServiceStatusEx Win32 API
(01) 2018-01-31 20:58:14 Slp: Sco: Attempting to close service handle for service MSSQLSERVER
(01) 2018-01-31 20:58:14 Slp: Sco: Attempting to close SC Manager
(01) 2018-01-31 20:58:14 Slp: Sco: Returning service process id 4012
(01) 2018-01-31 20:58:14 SQLEngine: : Checking Engine checkpoint 'GetSqlServerProcessHandle'
(01) 2018-01-31 20:58:14 SQLEngine: --SqlServerServiceSCM: Waiting for nt event 'Global\sqlserverRecComplete' to be created

Even after all the health checks have been disabled it will still try to start the service before doing the upgrade, and then hang waiting for it (while it has secretly died in the background due to being expired). Note that if you're still using the GUI then this can also hang the GUI so the Cancel button might not work - in which case kill it in Task Manager.

Common advice here is to set the clock backwards. My problem with that is that you're probably doing this on an unsupported unknown black-box flaming garbage can of a system set up by someone who wasn't meant to do it - because otherwise they wouldn't be using the evaluation edition. So what are the repercussions of setting the clock backwards? Perhaps their application spawning silently in the background and trashing this or other databases with bad date information? Perhaps you'll lose your RDP connection and then be unable to connect back in because of the SSPI error generated by a clock mismatch?

No thanks. Instead you need to do some detective work. Take another look at the last SQL ERRORLOG file. The one that was generated when the Setup process stupidly tried to start it.

2017-11-30 21:01:18.14 Server      Command Line Startup Parameters:
	 -s "MSSQLSERVER"
	 -m "SqlSetup"
	 -T 4022
	 -T 4010
	 -T 1905
	 -T 3701
	 -T 8015

Cool trace flags. These are:

  • Instance name MSSQLSERVER (this is the only one that wasn't added by Setup)
  • Start in single-user mode and only allow connections from an application name SqlSetup
  • Bypass startup procedures
  • Allow only shared memory connections
  • Unknown …
  • Unknown …
  • Disable auto-detection of NUMA

Using these some flags you can start the SQL Server service manually - and for some reason while it will still abort due to expiry when Setup does it, it will stay up when you do it!

sc.exe start MSSQLSERVER -m "SqlSetup" -T4022 -T4010 -T1905 -T3701 -T8015

Now run the edition upgrade again (from the GUI if it didn't have health check issues, or the command-line if it did).

Success.