I am trying to uninstall SqlServer 2017 and install SqlServer 2022. It is uninstalling SqlServer 2017 but never installing the 2022. Please help.
I have a class named RemoveSql2017.cs that's as follows:
public class RemoveSQL2017
{
const string UNINSTALL_SQL_2017 = "/Action=Uninstall /INSTANCENAME=PHARMSPEC /FEATURES=SQL /QS /HIDECONSOLE";
const string sqlFile = "DetachPharmSpecDB.sql";
const string DB_INSTANCE = "PHARMSPEC";
const int COMMAND_LINE_WAIT = 10000;
private static WixBootstrapper _bootstrapper;
const string registryKey = @"SOFTWARE\HIAC\PharmSpec\Database";
const string subKeyValue = "DataPath";
public RemoveSQL2017(WixBootstrapper bootstrapper)
{
_bootstrapper = bootstrapper;
}
public void Remove(string bootStrapFolder, string dataFilePath)
{
CreateDetachSQLFile();
CopyFiles(dataFilePath);
UninstallSQL(bootStrapFolder);
DeleteDBRegistryPath();
}
public static void UninstallSQL(string bootstrapFolder)
{
try
{
_bootstrapper.Engine.Log(LogLevel.Verbose, "Beginning UninstallSQL; bootstrapFolder=" + bootstrapFolder);
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo(bootstrapFolder + "//SQL2017//setup.exe", UNINSTALL_SQL_2017);
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
_bootstrapper.Engine.Log(LogLevel.Verbose, "Completing UninstallSQL; bootstrapFolder=" + bootstrapFolder);
}
catch (Exception e)
{
_bootstrapper.Engine.Log(LogLevel.Verbose, "Error in UninstallSQL:\n " + e.ToString());
throw (e);
}
}
public static void CopyFiles(string dataFilePath)
{
try
{
_bootstrapper.Engine.Log(LogLevel.Verbose, "Beginning CopyFiles; dataFilePath=" + dataFilePath + " tempDBFilePath=" + Globals.tempDBFilePath);
File.Copy(Path.Combine(dataFilePath, Globals.MDF_FILE), Path.Combine(Globals.tempDBFilePath, Globals.MDF_FILE));
File.Copy(Path.Combine(dataFilePath, Globals.LDF_FILE), Path.Combine(Globals.tempDBFilePath, Globals.LDF_FILE));
_bootstrapper.Engine.Log(LogLevel.Verbose, "Completing CopyFiles; dataFilePath=" + dataFilePath + " tempDBFilePath=" + Globals.tempDBFilePath);
}
catch (Exception e)
{
_bootstrapper.Engine.Log(LogLevel.Verbose, "Error in CopyFiles:\n " + e.ToString());
}
}
public static void DetachDB(string sqlFilePath)
{
try
{
_bootstrapper.Engine.Log(LogLevel.Verbose, "Beginning DetachDB; sqlFilePath=" + sqlFilePath);
string command = string.Format("-S .\\{0} -E -i \"{1}\"", DB_INSTANCE, sqlFilePath);
ProcessStartInfo info = new ProcessStartInfo("sqlcmd", command);
info.UseShellExecute = false;
info.CreateNoWindow = false;
info.WindowStyle = ProcessWindowStyle.Hidden;
Process proc = new Process();
proc.StartInfo = info;
proc.StartInfo.RedirectStandardOutput = true;
proc.Start();
string outputD = proc.StandardOutput.ReadToEnd();
if (proc.WaitForExit(COMMAND_LINE_WAIT))
{
_bootstrapper.Engine.Log(LogLevel.Verbose, outputD);
}
else
{
_bootstrapper.Engine.Log(LogLevel.Verbose, "Process timeout in DetachDb");
}
_bootstrapper.Engine.Log(LogLevel.Verbose, "Completing DetachDB; sqlFilePath=" + sqlFilePath);
}
catch (Exception e)
{
_bootstrapper.Engine.Log(LogLevel.Verbose, "Error in DetachDB:\n " + e.ToString());
throw (e);
}
}
public static void CreateDetachSQLFile()
{
try
{
string sqlFilePath = Path.Combine(Path.GetTempPath(), sqlFile);
var sqlScript = new StringBuilder();
sqlScript.AppendLine("GO");
sqlScript.AppendLine("IF EXISTS (SELECT * FROM sysdatabases WHERE name = N'PharmSpecDB')");
sqlScript.AppendLine("use PharmSpecDB");
sqlScript.AppendLine("DROP SCHEMA PharmSpecUsr");
sqlScript.AppendLine("DROP USER PharmSpecUsr");
sqlScript.AppendLine("use master");
sqlScript.AppendLine("EXEC sp_detach_db 'PharmSpecDB'");
sqlScript.AppendLine("GO");
sqlScript.AppendLine("IF EXISTS (SELECT * FROM syslogins WHERE name = N'PharmSpecUsr')");
sqlScript.AppendLine("DROP LOGIN PharmSpecUsr");
sqlScript.AppendLine("GO");
using (StreamWriter sw = new StreamWriter(sqlFilePath))
{
sw.Write(sqlScript.ToString());
}
DetachDB(sqlFilePath);
}
catch (Exception e)
{
_bootstrapper.Engine.Log(LogLevel.Verbose, "error in CreateDetachSQLFile:\n " + e.ToString());
throw (e);
}
}
public static void DeleteDBRegistryPath()
{
try
{
using (RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
{
RegistryKey subkey = key.OpenSubKey(registryKey, true);
if (subkey != null)
{
subkey.DeleteValue(subKeyValue);
}
}
}
catch (Exception e)
{
_bootstrapper.Engine.Log(LogLevel.Verbose, "error in DeleteDBRegistryPath:\n" + e.ToString());
}
}
I am calling this class as follows: I am able to see SqlServer 2017 getting uninstalled.
if (Bootstrapper.Engine.StringVariables["PreviousVersion"].CompareTo("3.5.99") <= 0 &&
Bootstrapper.Engine.StringVariables["SqlInstanceKeyFound64"] == "1")
{
RemoveSQL2017 removeSQL = new RemoveSQL2017(Bootstrapper);
removeSQL.Remove(Bootstrapper.Engine.StringVariables["DB2017SETUP"], Bootstrapper.Engine.StringVariables["2017DBDataPath"]);
Bootstrapper.Engine.StringVariables["OLDDBDATAPATH"] = Globals.tempDBFilePath;
Bootstrapper.Engine.StringVariables["INSTALLSQL"] = "1";
}
I have a SqlServer.wxi in which the registry keys and the exe file are as follows. Before removing SqlServer2017 this is what is in the registry,
SqlServer.wxi
<Variable Name="SqlInstanceKeyFound" Value="0"/>
<Variable Name="SqlInstanceKeyFound64" Value="0"/>
<util:RegistrySearch
Id="SqlInstanceKeyFound64"
Root="HKLM" Key="SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL" Value="PHARMSPEC"
Result="exists" Variable="SqlInstanceKeyFound64" Win64="yes"/>
<util:RegistrySearch
Id="SqlInstanceKey64"
Root="HKLM" Key="SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL" Value="PHARMSPEC"
Variable="SqlInstanceKey64" After="SqlInstanceKeyFound64" Condition="SqlInstanceKeyFound64" Win64="yes" />
<util:RegistrySearch
Id="SqlInstanceFound64"
Root="HKLM" Key="SOFTWARE\Microsoft\Microsoft SQL Server\[SqlInstanceKey64]"
Result="exists" Variable="SqlInstanceFound64" After="SqlInstanceKey64" Condition="SqlInstanceKeyFound64" Win64="yes" />
<util:RegistrySearch
Id="SqlVersion64"
Root="HKLM" Key="SOFTWARE\Microsoft\Microsoft SQL Server\[SqlInstanceKey64]\Setup" Value="Version"
Variable="SqlVersion64" After="SqlInstanceKey64" Condition="SqlInstanceFound64" Win64="yes" />
<PackageGroup Id="SQL2022Express">
<ExePackage Id="SQL2022Express"
DisplayName="SQL Server 2022 Express"
Cache="yes"
Compressed="no"
PerMachine="yes"
Permanent="no"
Vital="yes"
DetectCondition="SqlInstanceFound64"
InstallCondition="INSTALLSQL=1"
Name="Redist\SQLEXPR_x64_!(loc.LANG).exe"
SourceFile="$(var.DependencyFolder)\SQLEXPR_x64_!(loc.LANG).exe"
InstallCommand="/ACTION=Install /IACCEPTSQLSERVERLICENSETERMS [SQLQUIET] /HIDECONSOLE /FEATURES=SQLEngine /UpdateEnabled=0 /INSTANCENAME=PHARMSPEC /SQLSYSADMINACCOUNTS=Builtin\Administrators /SQLSVCACCOUNT="NT AUTHORITY\NETWORK SERVICE" /SECURITYMODE=SQL /SAPWD=[SAPASSWORD] /NPENABLED=1 /TCPENABLED=1 /SKIPRULES=RebootRequiredCheck"
UninstallCommand="/Action=Uninstall /INSTANCENAME=PHARMSPEC /FEATURES=SQL /QS /HIDECONSOLE">
<ExitCode Value ="3010" Behavior="forceReboot" />
</ExePackage>
</PackageGroup>
In the log its showing the following:
SqlInstanceFound64
variable was found, which is used in your DetectCondition to indicate that SQL Express 2022 was already installed. The bundle will not install something that already exists.
I think you need to search for a registry key (or something) that is unique to SQL Express 2022. What you're looking at right now seems to be set by many versions of SQL Express.