1012 lines
33 KiB
C#
1012 lines
33 KiB
C#
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();
|
||
|
||
|
||
}
|
||
|
||
|
||
}
|
||
}
|