EI-Image-Viewer-Api/Start/Main.cs

645 lines
20 KiB
C#
Raw 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;
namespace Start
{
public partial class Main : Form
{
private bool isCanDBConfig = true;
private bool isPortTestOk = false;
private bool isServiceTestOk = false;
private bool isDBNameTestOK = false;
public Main()
{
InitializeComponent();
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 void connectButton_Click(object sender, EventArgs e)
{
string connectionString = $"Server={serverTextBox.Text};User Id={usernameTextBox.Text};Password={passwordTextBox.Text};";
SqlConnection connection = new SqlConnection(connectionString);
try
{
connection.Open();
WinformLog("数据库连接测试成功!", 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($"数据库连接测试失败:{ex.Message}", Color.Red);
}
finally
{
connection.Close();
}
}
private void portBtn_Click(object sender, EventArgs e)
{
if (int.TryParse(nginxPortTBox.Text, out vuePort) == false || int.TryParse(apiPortTBox.Text, out apiPort) == false)
{
WinformLog($"请输入合法的端口", Color.Red);
return;
}
if (IsPortInUse(vuePort))
{
WinformLog($"服务设置的前端端口被占用,请选择其他端口", Color.Red);
return;
}
if (IsPortInUse(apiPort))
{
WinformLog($"服务设置的后端端口被占用,请选择其他端口", Color.Red);
return;
}
WinformLog("端口测试成功!", Color.Green);
isPortTestOk = true;
}
private void testServicebtn_Click(object sender, EventArgs e)
{
if (ServiceController.GetServices().Any(t => t.ServiceName == serviceNameTBox.Text))
{
WinformLog($"当前服务名称已存在,请更换", Color.Red);
return;
}
WinformLog($"测试服务名称成功", Color.Green);
isServiceTestOk = true;
}
private void testDBBtn_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(dbNameTBox.Text))
{
WinformLog($"请输入部署的数据库名称", 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()}该数据库已存在。", Color.Red);
return;
}
}
WinformLog($"数据库名称测试成功", Color.Green);
isDBNameTestOK = true;
}
private async 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) || isDBNameTestOK == false || isPortTestOk == false || isServiceTestOk == false)
{
WinformLog($"请选择部署路径,测试的端口,数据库名,服务名都成功才可以进行确认", Color.Red);
return;
}
WinformLog($"部署配置确认成功", 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;
}
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(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();
}
private async void activeBtn_Click(object sender, EventArgs e)
{
if (Md5($"{machineTextBox.Text}_XINGCANG") != KeySecreteTextBox.Text.Trim())
{
WinformLog($"秘钥不正确,请联系供应商", Color.Red);
return;
}
this.activeBtn.Enabled = false;
var serviceName = serviceNameTBox.Text;
var serviceDisplayName = serviceDisplayNameTBox.Text;
var deployFoder = this.folderPathTbox.Text;
string nginxExtractName = "nginx-1.20.1";
string apiExtractName = "APIPublish";
string nginxStartPath = Path.Combine(deployFoder, @$"{nginxExtractName}\");
var nginxConfigPath = Path.Combine(nginxStartPath, @$"conf\nginx.conf");
var apiBinPath = Path.Combine(deployFoder, "APIPublish/IRacIS.Core.API.exe");
var apiJsonConfigPath = Path.Combine(deployFoder, "APIPublish/appsettings.CertificateApply.json");
string nginxRarFilePath = Path.Combine(AppContext.BaseDirectory, $@"deploy\nginx-1.20.1.rar"); // 要解压缩的RAR文件路径
string apiRarFilePath = Path.Combine(AppContext.BaseDirectory, "deploy/net6.0.rar"); // 要解压缩的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
#region 解压nginx 和前端部署的文件
WinformLog($"开始解压 nginx 及前端部署 RAR文件", Color.Green);
await Task.Run(() =>
{
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 及前端部署 RAR文件已成功解压缩到 + {extractPath}", Color.Green);
});
#endregion
#region 解压后端部署的文件
WinformLog($"开始解压 后端部署 RAR文件", Color.Green);
await Task.Run(() =>
{
string extractPath = Path.Combine(deployFoder, apiExtractName);
if (!Directory.Exists(extractPath))
{
Directory.CreateDirectory(extractPath);
}
using (var archive = RarArchive.Open(apiRarFilePath))
{
foreach (var entry in archive.Entries)
{
if (!entry.IsDirectory)
{
entry.WriteToDirectory(extractPath, new ExtractionOptions() { ExtractFullPath = true, Overwrite = true });
}
}
}
WinformLog($"后端部署 RAR文件已成功解压缩到 + {extractPath}", Color.Green);
});
#endregion
#region 修改 nginx 配置文件 启动nginx
if (!File.Exists(nginxConfigPath))
{
WinformLog("预设路径不存在nginx", Color.Red);
}
var nginxConfig = File.ReadAllText(nginxConfigPath);
nginxConfig = nginxConfig.Replace("9520", vuePort.ToString());
nginxConfig = nginxConfig.Replace("7100", apiPort.ToString());
File.WriteAllText(nginxConfigPath, nginxConfig);
// 获取nginx.exe所在的目录
// 创建ProcessStartInfo对象指定要启动的可执行文件及其参数
ProcessStartInfo psi = new ProcessStartInfo(nginxStartPath + "nginx.exe");
// 指定工作目录即进入nginx.exe所在的目录
psi.WorkingDirectory = nginxStartPath;
WinformLog(" 开始启动 nginx 服务...", Color.Green);
// 启动可执行文件
Process.Start(psi);
if (Process.GetProcesses().Any(t => t.ProcessName.Contains("nginx") && t.MainModule.FileName.Contains(nginxStartPath)))
{
WinformLog(" nginx 服务启动成功", Color.Green);
}
else
{
WinformLog(" nginx 服务启动失败", Color.Red);
return;
}
#endregion
var configObj = new
{
key = this.machineTextBox.Text,
value = this.KeySecreteTextBox.Text.Trim(),
user = usernameTextBox.Text,
server = serverTextBox.Text,
password = passwordTextBox.Text,
dbName = dbNameTBox.Text,
};
File.WriteAllText($@"C:\ProgramData\.xingcang\config.json", JsonConvert.SerializeObject(configObj));
WinformLog("写入激活秘钥完成", Color.Green);
#region 部署网站配置文件写入
WinformLog("开始写入部署网站服务配置文件...", 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)
{
Console.WriteLine("连接字符串错误");
WinformLog($"连接字符串错误", Color.Red);
return;
}
WinformLog("部署网站服务配置文件写入并测试OK", Color.Green);
#endregion
var createStr = $@"sc create {serviceName} binPath= ""{apiBinPath} --urls=""http://127.0.0.1:{apiPort}"" --env CertificateApply"" DisplayName= ""{serviceDisplayName}"" start= auto";
#region 创建服务
// 删除已存在的服务
//await ProcessStandardInputAsync(process, $"sc delete {serviceName}");
//Log($"删除服务{serviceName}...", Color.Green);
// 执行 sc create 命令来创建服务
await ProcessStandardInputAsync(process, createStr);
WinformLog($"创建服务{serviceName}...", Color.Green);
WinformLog($"执行初始化数据库脚本...", Color.Green);
//执行数据库脚本
//await ProcessStandardInputAsync(process, Path.Combine(AppContext.BaseDirectory, "deploy/sql/bin.bat"));
await ProcessStandardInputAsync(process, $@" SQLCMD -v dbName = ""{dbNameTBox.Text}"" -i {AppContext.BaseDirectory}deploy\sql\dbo.sql ");
await ProcessStandardInputAsync(process, $@" SQLCMD -v dbName = ""{dbNameTBox.Text}"" -i {AppContext.BaseDirectory}deploy\sql\data.sql ");
WinformLog($"初始化数据库脚本执行结束", Color.Green);
// 执行 sc start 启动服务
WinformLog($"启动部署的后端服务...", Color.Green);
await ProcessStandardInputAsync(process, $"sc start {serviceName}");
// 关闭进程流并等待进程退出
process.StandardInput.Close();
process.WaitForExit();
ServiceController sc = new ServiceController(serviceName);
if (sc.Status == ServiceControllerStatus.Running)
{
WinformLog($"后端服务启动成功", Color.Green);
WinformLog($"部署工作已完成", Color.Green);
try
{
WinformLog($"现在打开浏览器...", Color.Green);
// Use ProcessStartInfo class
var start = new ProcessStartInfo($"http://127.0.0.1:{vuePort}")
{
UseShellExecute = true,
Verb = "open"
};
Process.Start(start);
}
catch (Exception ex)
{
// Handle exception
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
WinformLog($"后端服务启动失败", Color.Red);
}
#endregion
}
private async void selectPathBtn_Click(object sender, EventArgs e)
{
FolderBrowserDialog dialog = new FolderBrowserDialog();
if (dialog.ShowDialog() == DialogResult.OK)
{
folderPathTbox.Text = dialog.SelectedPath;
confimDeployBtn.Enabled = true;
WinformLog($"部署路径选择成功", Color.Green);
#region 测试 停止Nginx
var deployFoder = this.folderPathTbox.Text;
string nginxExtractName = "nginx-1.20.1";
string nginxStartPath = Path.Combine(deployFoder, @$"{nginxExtractName}\");
#region 创建进程执行命令
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true; // 不创建新窗口
process.Start();
var proList = Process.GetProcesses().Where(t => t.ProcessName.Contains("nginx") && t.MainModule.FileName.Contains(nginxStartPath));
foreach (var item in proList)
{
item.Kill();
}
await ProcessStandardInputAsync(process, $"sc stop {serviceNameTBox.Text}");
await ProcessStandardInputAsync(process, $"sc delete {serviceNameTBox.Text}");
process.StandardInput.Close();
process.WaitForExit();
#endregion
#endregion
}
}
private void btnCopy_Click(object sender, EventArgs e)
{
Clipboard.SetText(machineTextBox.Text);
WinformLog("机器码拷贝到剪切板成功!", Color.Green);
}
private void Main_Load(object sender, EventArgs e)
{
Serilog.Log.Logger = new LoggerConfiguration()
.WriteTo.File("log.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
}
}
}