510k-install/Main.cs

1012 lines
33 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.NetworkInformation;
using System.Windows.Forms;
using System.Net;
using System.Security.Cryptography;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Diagnostics;
using Microsoft.VisualBasic.Logging;
using System.IO.Compression;
using SharpCompress.Archives.Rar;
using SharpCompress.Common;
using SharpCompress.Archives;
using System.Diagnostics.Eventing.Reader;
using System.ServiceProcess;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using System.Security.Policy;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ToolBar;
using System.Data.SqlTypes;
using Serilog;
using System.Xml.Linq;
using System.IO;
using Microsoft.Win32;
using System.Web;
namespace Start
{
public partial class Main : Form
{
private bool isCanDBConfig = true;
private bool isPortTestOk = false;
private bool isServiceTestOk = false;
private bool isDBNameTestOK = false;
private bool isRuntimeTestOk = false;
public Main()
{
InitializeComponent();
this.MaximizeBox = false;
var physicalAddressList = NetworkInterface.GetAllNetworkInterfaces().Select(t => t.GetPhysicalAddress().ToString());
this.machineTextBox.Text = physicalAddressList.FirstOrDefault()?.ToString();
//this.KeySecreteTextBox.Text = Md5($"{this.machineTextBox.Text}_XINGCANG");
}
int apiPort = 7100;
int vuePort = 9527;
private async void connectButton_Click(object sender, EventArgs e)
{
string connectionString = $"Server={serverTextBox.Text};User Id={usernameTextBox.Text};Password={passwordTextBox.Text};";
using (SqlConnection connection = new SqlConnection(connectionString))
{
try
{
await Task.Run(() =>
{
connection.Open();
});
WinformLog("Database connection test succeeded.", Color.Green);
isCanDBConfig = false;
serverTextBox.Enabled = isCanDBConfig;
usernameTextBox.Enabled = isCanDBConfig;
passwordTextBox.Enabled = isCanDBConfig;
connectButton.Enabled = false;
selectPathBtn.Enabled = true;
//portBtn.Enabled = true;
//testDBBtn.Enabled = true;
//testServicebtn.Enabled = true;
}
catch (Exception ex)
{
WinformLog($"Database connection test failed{ex.Message}", Color.Red);
}
}
}
private void portBtn_Click(object sender, EventArgs e)
{
if (int.TryParse(nginxPortTBox.Text, out vuePort) == false || int.TryParse(apiPortTBox.Text, out apiPort) == false)
{
WinformLog($"Please enter a valid port number!", Color.Red);
return;
}
if (IsPortInUse(vuePort))
{
WinformLog($"The front-end port set by the service is already in use. Please choose another port!", Color.Red);
return;
}
if (IsPortInUse(apiPort))
{
WinformLog($"The back-end port set by the service is already in use. Please choose another port!", Color.Red);
return;
}
WinformLog("Port test succeeded.", Color.Green);
isPortTestOk = true;
}
private void testServicebtn_Click(object sender, EventArgs e)
{
if (ServiceController.GetServices().Any(t => t.ServiceName == serviceNameTBox.Text))
{
WinformLog($"Name of the backend service already exists. Please change it!", Color.Red);
return;
}
if (ServiceController.GetServices().Any(t => t.ServiceName == nginxServiceNameTbox.Text))
{
WinformLog($"Name of the nginx service already exists. Please change it!", Color.Red);
return;
}
WinformLog($"Service name test succeeded.", Color.Green);
isServiceTestOk = true;
}
private void testNetcoreRuntime()
{
string runtimeListCommand = "dotnet --list-runtimes";
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c " + runtimeListCommand;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
bool isAspNetCoreRuntimeInstalled = false;
bool isNETCoreRuntimeInstalled = false;
var lineList = output.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).ToList();
foreach (string line in lineList)
{
if (line.Contains("Microsoft.AspNetCore.App") && !line.Contains("Preview"))
{
string versionString = line.Split(' ')[1];
Version version = new Version(versionString);
if (version.Major > 6 || (version.Major == 6 && version.Minor >= 0))
{
// 大于等于 6.0.0 的 .NET 运行时已安装
isAspNetCoreRuntimeInstalled = true;
continue;
}
}
if (line.Contains("Microsoft.NETCore.App") && !line.Contains("Preview"))
{
string versionString = line.Split(' ')[1];
Version version = new Version(versionString);
if (version.Major > 6 || (version.Major == 6 && version.Minor >= 0))
{
// 大于等于 6.0.0 的 .NET 运行时已安装
isNETCoreRuntimeInstalled = true;
continue;
}
}
}
if (isAspNetCoreRuntimeInstalled && isNETCoreRuntimeInstalled)
{
// 执行逻辑,表示大于等于 6.0.0 的 .NET 运行时已安装
WinformLog("Netcore Runtime 6.0.0 or newer has been installed.", Color.Green);
isRuntimeTestOk = true;
}
else
{
WinformLog("Netcore Runtime 6.0.0 or newer is not installed. Please install it before running the deployment software.", Color.Red);
connectButton.Enabled = false;
//await Task.Run(() =>
// {
// WinformLog("Installing Netcore Runtime….", Color.Orange);
// string runtimePath = Path.Combine(AppContext.BaseDirectory, "Resource/NetCoreRuntime/dotnet-hosting-6.0.0-win.exe");
// var processInfo = new ProcessStartInfo
// {
// FileName = runtimePath, // 安装程序的文件名
// Arguments = $"/S /v /qn REINSTALLMODE=vomus",
// UseShellExecute = false
// };
// var otherProcess = new Process { StartInfo = processInfo };
// otherProcess.Start();
// otherProcess.WaitForExit();
// WinformLog("Netcore 6.0.0 Runtime installation completed.", Color.Green);
// });
}
}
private void testDBBtn_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(dbNameTBox.Text))
{
WinformLog($"Please enter the name of the deployed database!", Color.Red);
return;
}
string connectionString = $"Server={serverTextBox.Text};User Id={usernameTextBox.Text};Password={passwordTextBox.Text};";
string sql = $"SELECT COUNT(*) FROM sys.databases WHERE name = '{dbNameTBox.Text.Trim()}';";
// 创建连接对象和命令对象
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(sql, connection))
{
// 打开连接
connection.Open();
// 执行查询,返回结果行数
int rowCount = (int)command.ExecuteScalar();
// 判断结果是否大于0即是否存在该数据库
if (rowCount > 0)
{
WinformLog($"{dbNameTBox.Text.Trim()} This database already exists.", Color.Red);
return;
}
}
WinformLog($"Database name test succeeded. ", Color.Green);
isDBNameTestOK = true;
}
private void confimDeployBtn_Click(object sender, EventArgs e)
{
portBtn_Click(null, null);
testServicebtn_Click(null, null);
testDBBtn_Click(null, null);
if (string.IsNullOrWhiteSpace(this.folderPathTbox.Text))
{
WinformLog($"Please select the deployment path ( Confirmation can be made only after port, database name, and service name pass the test.).", Color.Red);
return;
}
if (isDBNameTestOK == false || isPortTestOk == false || isServiceTestOk == false)
{
WinformLog($"Confirmation can be made only after port, database name, and service name pass the test.", Color.Red);
return;
}
WinformLog($"Deployment configuration confirmed successfully.", Color.Green);
activeBtn.Enabled = true;
confimDeployBtn.Enabled = false;
selectPathBtn.Enabled = false;
//portBtn.Enabled = false;
//testDBBtn.Enabled = false;
//testServicebtn.Enabled = false;
nginxPortTBox.Enabled = false;
apiPortTBox.Enabled = false;
dbNameTBox.Enabled = false;
serviceNameTBox.Enabled = false;
serviceDisplayNameTBox.Enabled = false;
nginxServiceNameTbox.Enabled = false;
nginxServiceDisplayNameTbox.Enabled = false;
}
private static bool IsPortInUse(int port)
{
IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] tcpEndPoints = ipProperties.GetActiveTcpListeners();
foreach (IPEndPoint endPoint in tcpEndPoints)
{
if (endPoint.Port == port)
{
return true;
}
}
return false;
}
public static string Md5(string target)
{
using (MD5 md5 = MD5.Create())
{ // MD5非线程安全
byte[] bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(target));
StringBuilder sb = new StringBuilder(32);
for (int i = 0; i < bytes.Length; ++i)
sb.Append(bytes[i].ToString("x2"));
return sb.ToString();
}
}
private void WinformLog(string message, Color color)
{
if (InvokeRequired)
{
Invoke(new Action(() => WinformLog(message, color)));
return;
}
logTBox.SelectionColor = color;
logTBox.AppendText($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}: {message}" + Environment.NewLine);
Serilog.Log.Information(message);
}
private async Task ProcessStandardInputAsync(Process process, string cmd, string workDirectory = "")
{
if (!string.IsNullOrWhiteSpace(workDirectory))
{
process.StartInfo.WorkingDirectory = workDirectory;
}
await process.StandardInput.WriteLineAsync(cmd);
await process.StandardInput.FlushAsync();
//while (!process.StandardOutput.EndOfStream)
//{
// var output = await process.StandardOutput.ReadLineAsync();
// if (string.IsNullOrWhiteSpace(output))
// {
// break;
// }
//}
}
private async void activeBtn_Click(object sender, EventArgs e)
{
if (Md5($"{machineTextBox.Text}_XINGCANG") != KeySecreteTextBox.Text.Trim())
{
WinformLog($"Secret key is not current. Please contact the vendor!", Color.Red);
return;
}
this.activeBtn.Enabled = false;
var serviceName = serviceNameTBox.Text;
var serviceDisplayName = serviceDisplayNameTBox.Text;
var nginxServiceName = nginxServiceNameTbox.Text;
var nginxServiceDesName = nginxServiceDisplayNameTbox.Text;
var deployFoder = this.folderPathTbox.Text;
string nginxExtractName = "LiLiDICOMViewerWeb";
string apiExtractName = "LiLiDICOMViewerService";
string dataExtraName = "LiLiDICOMViewerData";
string resouceFolder = "Resource";
string nginxStartPath = Path.Combine(deployFoder, @$"{nginxExtractName}");
var nginxConfigPath = Path.Combine(nginxStartPath, @$"conf\nginx.conf");
var nginxEXEPath = Path.Combine(nginxStartPath, "nginx.exe");
string nginxServiceEXEPath = Path.Combine(nginxStartPath, "nginxService.exe");
string nginxServiceXMLPath = Path.Combine(nginxStartPath, "nginxService.xml");
var apiBinPath = Path.Combine(deployFoder, apiExtractName, "EI_Med_Viewer.exe");
var apiJsonConfigPath = Path.Combine(deployFoder, apiExtractName,"appsettings.Test_510K.json");
string nginxRarFilePath = Path.Combine(AppContext.BaseDirectory, resouceFolder, "LiLiDICOMViewerWeb.rar");
string apiRarFilePath = Path.Combine(AppContext.BaseDirectory, resouceFolder, "LiLiDICOMViewerService.rar");
string dataRarFilePath = Path.Combine(AppContext.BaseDirectory, resouceFolder, "LiLiDICOMViewerData.rar");
#region 创建进程执行命令
var startInfo = new ProcessStartInfo();
startInfo.FileName = "cmd.exe"; // 指定要启动的应用程序
startInfo.RedirectStandardInput = true;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
// 创建新进程并启动
var process = new Process();
process.StartInfo = startInfo;
process.Start();
#endregion
await Task.Run(async () =>
{
#region 解压nginx 和前端部署的文件
WinformLog($"Start extracting Nginx and front-end deployment compressed files...", Color.Green);
string extractPath = Path.Combine(deployFoder, nginxExtractName);
if (!Directory.Exists(extractPath))
{
Directory.CreateDirectory(extractPath);
}
using (var archive = RarArchive.Open(nginxRarFilePath))
{
foreach (var entry in archive.Entries)
{
if (!entry.IsDirectory)
{
entry.WriteToDirectory(extractPath, new ExtractionOptions() { ExtractFullPath = true, Overwrite = true });
}
else
{
string directoryPath = Path.Combine(extractPath, entry.Key);
Directory.CreateDirectory(directoryPath);
}
}
}
WinformLog($"Nginx and front-end deployment compressed files have been successfully extracted to: {extractPath}", Color.Green);
#endregion
#region 修改 nginx 配置文件 启动nginx
if (!File.Exists(nginxConfigPath))
{
WinformLog("No nginx exists under the default path.", Color.Red);
}
WinformLog("Prepare to write in Nginx configuration...", Color.Green);
var nginxConfig = File.ReadAllText(nginxConfigPath);
nginxConfig = nginxConfig.Replace("9520", vuePort.ToString());
nginxConfig = nginxConfig.Replace("7100", apiPort.ToString());
File.WriteAllText(nginxConfigPath, nginxConfig);
WinformLog("Nginx deployment configuration write-in completed!", Color.Green);
#region nginxservice
WinformLog("Prepare Nginx self-starting service configuration file...", Color.Green);
var nginxServiceConfig = File.ReadAllText(nginxServiceXMLPath);
nginxServiceConfig = nginxServiceConfig.Replace("{nginxName}", nginxServiceName);
nginxServiceConfig = nginxServiceConfig.Replace("{nginxDesName}", nginxServiceDesName);
nginxServiceConfig = nginxServiceConfig.Replace("{nginxPath}", nginxEXEPath);
nginxServiceConfig = nginxServiceConfig.Replace("{nginxStartPath}", nginxStartPath);
File.WriteAllText(nginxServiceXMLPath, nginxServiceConfig);
WinformLog("Nginx self-starting service configuration write-in completed", Color.Green);
#endregion
WinformLog($"Prepare to create self-starting nginx service...", Color.Green);
var nginxCreateStr = $@"{nginxServiceEXEPath} install ";
// 执行 sc create 命令来创建服务
await ProcessStandardInputAsync(process, nginxCreateStr);
WinformLog($"The execution of creating Service {nginxServiceName} ends", Color.Green);
await Task.Delay(2000);
#region nginx 服务
WinformLog($"Start the deployed service {nginxServiceName}...", Color.Green);
await ProcessStandardInputAsync(process, $"sc start {nginxServiceName}");
ServiceController scNginx = new ServiceController(nginxServiceName);
if (scNginx.Status != ServiceControllerStatus.Running)
{
scNginx.Refresh();
await Task.Delay(3000);
scNginx.Refresh();
await Task.Delay(2000);
}
if (scNginx.Status == ServiceControllerStatus.Running)
{
WinformLog($"Nginx service started successfully.", Color.Green);
}
else
{
WinformLog($"Nginx service failed to start.", Color.Red);
}
#endregion
#region 命令行方式启动 废弃
//// 创建ProcessStartInfo对象指定要启动的可执行文件及其参数
//ProcessStartInfo psi = new ProcessStartInfo(nginxEXEPath);
//// 指定工作目录即进入nginx.exe所在的目录
//psi.WorkingDirectory = nginxStartPath;
//WinformLog(" Start nginx service...", Color.Green);
//// 启动可执行文件
//Process.Start(psi);
//if (Process.GetProcesses().Any(t => t.ProcessName.Contains("nginx") && t.MainModule.FileName.Contains(nginxStartPath)))
//{
// WinformLog(" nginx service started successfully", Color.Green);
//}
//else
//{
// WinformLog(" nginx service failed to start", Color.Red);
// return;
//}
#endregion
#endregion
});
await Task.Run(() =>
{
#region 解压后端部署的文件
WinformLog($"Start extracting the backend deployment compressed file...", Color.Green);
string apiExtractPath = Path.Combine(deployFoder, apiExtractName);
if (!Directory.Exists(apiExtractPath))
{
Directory.CreateDirectory(apiExtractPath);
}
using (var archive = RarArchive.Open(apiRarFilePath))
{
foreach (var entry in archive.Entries)
{
if (!entry.IsDirectory)
{
entry.WriteToDirectory(apiExtractPath, new ExtractionOptions() { ExtractFullPath = true, Overwrite = true });
}
else
{
string directoryPath = Path.Combine(apiExtractPath, entry.Key);
Directory.CreateDirectory(directoryPath);
}
}
}
WinformLog($"The backend deployment compressed file has been successfully extracted to: {apiExtractPath}", Color.Green);
#endregion
});
await Task.Run(() =>
{
#region 解压模板文件
WinformLog($"Start extracting template files…", Color.Green);
string extractPath = Path.Combine(deployFoder, dataExtraName);
if (!Directory.Exists(extractPath))
{
Directory.CreateDirectory(extractPath);
}
using (var archive = RarArchive.Open(dataRarFilePath))
{
foreach (var entry in archive.Entries)
{
if (!entry.IsDirectory)
{
entry.WriteToDirectory(extractPath, new ExtractionOptions() { ExtractFullPath = true, Overwrite = true });
}
}
}
WinformLog($"Template files have been successfully extracted to: {extractPath}", Color.Green);
#endregion
#region 文档等资源文件
var otherFileFolder = Path.Combine(AppContext.BaseDirectory, $@"Resource");
if (Directory.Exists(otherFileFolder))
{
// 获取源目录下所有文件
string[] files = Directory.GetFiles(otherFileFolder);
foreach (string file in files)
{
// 筛选掉文件夹
if (!File.GetAttributes(file).HasFlag(FileAttributes.Directory))
{
string extension = Path.GetExtension(file);
if (extension != ".zip" && extension != ".rar" && extension != ".7z" && extension != ".tar" && extension != ".gz")
{
// 获取文件名
string fileName = Path.GetFileName(file);
// 拷贝文件到目标目录
File.Copy(file, Path.Combine(deployFoder, fileName), true);
}
}
}
}
WinformLog($"Document resources have been released successfully.", Color.Green);
#endregion
});
await Task.Run(() =>
{
#region 激活
try
{
string directoryPath = @"C:\ProgramData\.xingcang";
if (!Directory.Exists(directoryPath))
{
Directory.CreateDirectory(directoryPath);
}
var configObj = new
{
key = this.machineTextBox.Text,
value = this.KeySecreteTextBox.Text.Trim(),
user = usernameTextBox.Text,
server = serverTextBox.Text,
password = passwordTextBox.Text,
dbName = dbNameTBox.Text,
deployFolder = deployFoder,
nginxStartPath = nginxStartPath,
serviceName = serviceName,
nginxServiceName = nginxServiceName,
nginxServiceEXEPath = nginxServiceEXEPath
};
File.WriteAllText(Path.Combine(directoryPath, "config.json"), JsonConvert.SerializeObject(configObj));
WinformLog("Activation key writing has been completed.", Color.Green);
}
catch (Exception ex)
{
WinformLog("Activation key writing failed. Please launch the application in administrator's mode, and make sure that the application has sufficient permissions.", Color.Red);
}
#endregion
});
await Task.Run(async () =>
{
#region 创建服务
WinformLog($"Start creating a service {serviceName}...", Color.Green);
var createTestStr = $"sc create {serviceName} binPath= \"{apiBinPath} --urls=http://*:{apiPort} --env Test_510K\" DisplayName= \"{serviceDisplayName}\" start= auto";
var createStr = $@"sc create {serviceName} binPath= ""{apiBinPath} --urls=http://127.0.0.1:{apiPort} --env Test_510K"" DisplayName= ""{serviceDisplayName}"" start= auto";
// 执行 sc create 命令来创建服务
await ProcessStandardInputAsync(process, createStr);
WinformLog($"Creating {serviceName} service has ended.", Color.Green);
#endregion
#region 初始化数据库脚本
WinformLog($"Initialize database script...", Color.Green);
//执行数据库脚本
await ProcessStandardInputAsync(process, $@" SQLCMD -S {serverTextBox.Text} -U {usernameTextBox.Text} -P {passwordTextBox.Text} -v dbName = ""{dbNameTBox.Text}"" -i ""{AppContext.BaseDirectory}Resource\Data\dbo.sql"" ");
await Task.Delay(3000);
await ProcessStandardInputAsync(process, $@" SQLCMD -S {serverTextBox.Text} -U {usernameTextBox.Text} -P {passwordTextBox.Text} -v dbName = ""{dbNameTBox.Text}"" -i ""{AppContext.BaseDirectory}Resource\Data\data.sql"" ");
WinformLog($"Initializing database script has ended.", Color.Green);
#endregion
#region 部署网站配置文件写入
WinformLog("Start writing service configuration file…", Color.Green);
var appsettingsJson = File.ReadAllText(apiJsonConfigPath);
// 解析 JSON 字符串
var jObject = JObject.Parse(appsettingsJson);
// 获取 UpdateConfig 属性所在的节点
var updateConfigNode = jObject["ConnectionStrings"];
var connectionString = $"Server={serverTextBox.Text};Database={dbNameTBox.Text};User ID={usernameTextBox.Text};Password={passwordTextBox.Text};TrustServerCertificate=true";
updateConfigNode["RemoteNew"] = connectionString;
try
{
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
File.WriteAllText(apiJsonConfigPath, jObject.ToString());
}
}
catch (SqlException ex)
{
WinformLog($"Database connection string error", Color.Red);
return;
}
WinformLog("Service configuration file writing & testing has been done.", Color.Green);
#endregion
});
await Task.Run(async () =>
{
#region 启动后端服务
WinformLog($"Start the backend service.", Color.Green);
await ProcessStandardInputAsync(process, $"sc start {serviceName}");
// 关闭进程流并等待进程退出
process.StandardInput.Close();
process.WaitForExit();
ServiceController sc = new ServiceController(serviceName);
if (sc.Status != ServiceControllerStatus.Running)
{
sc.Refresh();
await Task.Delay(3000);
sc.Refresh();
await Task.Delay(2000);
}
if (sc.Status == ServiceControllerStatus.Running)
{
WinformLog($"Backend service started successfully.", Color.Green);
WinformLog($"Deployment has been completed.", Color.Green);
try
{
WinformLog($"Ready to open the browser…", Color.Green);
await Task.Delay(2000);
// Use ProcessStartInfo class
var start = new ProcessStartInfo($"http://127.0.0.1:{vuePort}")
{
UseShellExecute = true,
Verb = "open"
};
var urlProcess = Process.Start(start);
urlProcess.WaitForExit(); // 等待进程结束
}
catch (Exception ex)
{
// Handle exception
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
WinformLog($"Backend service failed to start. Please try to start {serviceDisplayName} manually. If a manual start still fails, please contact tech support to confirm the deployment environment.", Color.Red);
}
#endregion
await Task.Delay(10000);
Application.Exit();
});
}
private void selectPathBtn_Click(object sender, EventArgs e)
{
FolderBrowserDialog dialog = new FolderBrowserDialog();
if (dialog.ShowDialog() == DialogResult.OK)
{
folderPathTbox.Text = dialog.SelectedPath;
confimDeployBtn.Enabled = true;
WinformLog($"Deployment path selection was successful.", Color.Green);
}
}
private void btnCopy_Click(object sender, EventArgs e)
{
Clipboard.SetText(machineTextBox.Text);
WinformLog("Machine code has been copied to the clipboard successfully. ", Color.Green);
}
private void Main_Load(object sender, EventArgs e)
{
Serilog.Log.Logger = new LoggerConfiguration()
.WriteTo.File("logs\\log.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
// 检查是否安装了 SQL Server
bool isSqlServerInstalled = false;
RegistryKey key = null;
try
{
key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Microsoft SQL Server");
if (key != null)
isSqlServerInstalled = true;
}
finally
{
key?.Close();
}
if (isSqlServerInstalled)
{
// 获取 SQL Server 实例列表
key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL");
if (key != null)
{
foreach (var instanceName in key.GetValueNames())
{
WinformLog($"An SQL Server instance already exists and its name is: {instanceName}", Color.Green);
}
}
}
else
{
WinformLog("SQL Server is not installed. Please install it before running the deployment program.", Color.Red);
}
key?.Close();
testNetcoreRuntime();
//this.TopMost = true;
this.Activate();
}
}
}