我正在尝试卸载 SqlServer 2017 并安装 SqlServer 2022。它正在卸载 SqlServer 2017,但从未安装 2022。请帮忙。
我有一个名为RemoveSql2017.cs的类,如下所示:
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());
}
}
我按如下方式调用此类:我能够看到 SqlServer 2017 被卸载。
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";
}
我有一个SqlServer.wxi,其中注册表项和exe文件如下。在删除 SqlServer2017 之前,这是注册表中的内容,
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>
在日志中显示以下内容:
SqlInstanceFound64
变量,该变量在您的 DetectCondition 中用于指示 SQL Express 2022 已安装。捆绑包不会安装已经存在的东西。
我认为您需要搜索 SQL Express 2022 特有的注册表项(或其他内容)。您现在看到的内容似乎是由许多版本的 SQL Express 设置的。