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

566 lines
17 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;
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");
}
private void Main_Load(object sender, EventArgs e)
{
portBtn.Enabled = false;
activeBtn.Enabled = false;
//serverTextBox.DataBindings.Add(new Binding("Enabled", this, "isCanDBConfig"));
//usernameTextBox.DataBindings.Add(new Binding("Enabled", this, "isCanDBConfig"));
//passwordTextBox.DataBindings.Add(new Binding("Enabled", this, "isCanDBConfig"));
//nginxPortTBox.DataBindings.Add(new Binding("Enabled", this, "isCanServerConfig"));
//apiPortTBox.DataBindings.Add(new Binding("Enabled", this, "isCanServerConfig"));
//dbNameTBox.DataBindings.Add(new Binding("Enabled", this, "isCanServerConfig"));
//connectButton.DataBindings.Add(new Binding("Enabled", this, "isCanDBConfig"));
}
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();
Log("数据库连接成功!", Color.Green);
isCanDBConfig = false;
serverTextBox.Enabled = isCanDBConfig;
usernameTextBox.Enabled = isCanDBConfig;
passwordTextBox.Enabled = isCanDBConfig;
connectButton.Enabled = false;
portBtn.Enabled = true;
}
catch (Exception ex)
{
Log($"数据库连接失败:{ex.Message}", Color.Red);
}
finally
{
connection.Close();
}
}
private async void portBtn_Click(object sender, EventArgs e)
{
#region 测试 停止Nginx
string nginxPath = Path.Combine(AppContext.BaseDirectory, @$"deploy\nginx-1.20.1\");
var serviceConfig = await File.ReadAllTextAsync("deploy/ServiceConfig.json");
var jObject = JObject.Parse(serviceConfig);
#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(nginxPath));
foreach (var item in proList)
{
item.Kill();
}
await ProcessStandardInputAsync(process, $"sc stop {jObject["serviceName"].ToString()}");
process.StandardInput.Close();
process.WaitForExit();
#endregion
#endregion
if (int.TryParse(nginxPortTBox.Text, out vuePort) == false || int.TryParse(apiPortTBox.Text, out apiPort) == false)
{
Log($"请输入合法的端口", Color.Red);
return;
}
if (IsPortInUse(vuePort))
{
Log($"服务设置的前端端口被占用,请选择其他端口", Color.Red);
return;
}
if (IsPortInUse(apiPort))
{
Log($"服务设置的后端端口被占用,请选择其他端口", Color.Red);
return;
}
Log("端口测试成功!", Color.Green);
isPortTestOk = true;
}
private void testServicebtn_Click(object sender, EventArgs e)
{
if (ServiceController.GetServices().Any(t => t.ServiceName == serviceNameTBox.Text))
{
Log($"当前服务名称已存在,请更换", Color.Red);
return;
}
isServiceTestOk = true;
}
private void testDBBtn_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(dbNameTBox.Text))
{
Log($"请输入部署的数据库名称", 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)
{
Log($"{dbNameTBox.Text.Trim()}该数据库已存在。", Color.Red);
return;
}
}
isDBNameTestOK = true;
}
private void confimDeployBtn_Click(object sender, EventArgs e)
{
activeBtn.Enabled = true;
nginxPortTBox.Enabled = false;
apiPortTBox.Enabled = false;
portBtn.Enabled = false;
dbNameTBox.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 Log(string message, Color color)
{
if (InvokeRequired)
{
Invoke(Log, message, color);
return;
}
logTBox.SelectionColor = color;
logTBox.AppendText(message + Environment.NewLine);
}
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)
{
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");
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 和前端部署的文件
Log($"开始解压 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);
}
}
}
Log($"nginx 及前端部署 RAR文件已成功解压缩到 + {extractPath}", Color.Green);
});
#endregion
#region 解压后端部署的文件
Log($"开始解压 后端部署 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 });
}
}
}
Log($"后端部署 RAR文件已成功解压缩到 + {extractPath}", Color.Green);
});
#endregion
#region 修改 nginx 配置文件 启动nginx
if (!File.Exists(nginxConfigPath))
{
MessageBox.Show("预设路径不存在nginx");
}
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;
Log(" 开始启动 nginx 服务...", Color.Green);
// 启动可执行文件
Process.Start(psi);
if (Process.GetProcesses().Any(t => t.ProcessName.Contains("nginx") && t.MainModule.FileName.Contains(nginxStartPath)))
{
Log(" nginx 服务启动成功", Color.Green);
}
else
{
Log(" 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));
Log("写入激活秘钥完成", Color.Green);
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);
Log($"创建服务{serviceName}...", Color.Green);
Log($"执行初始化数据库脚本...", 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 ");
Log($"初始化数据库脚本执行结束", Color.Green);
// 执行 sc start 启动服务
Log($"启动部署的后端服务...", Color.Green);
await ProcessStandardInputAsync(process, $"sc start {serviceName}");
// 关闭进程流并等待进程退出
process.StandardInput.Close();
process.WaitForExit();
ServiceController sc = new ServiceController(serviceName);
if (sc.Status == ServiceControllerStatus.Running)
{
Log($"后端服务启动成功", Color.Green);
try
{
// 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
{
Log($"后端服务启动失败", Color.Red);
}
#endregion
}
private void selectPathBtn_Click(object sender, EventArgs e)
{
FolderBrowserDialog dialog = new FolderBrowserDialog();
if (dialog.ShowDialog() == DialogResult.OK)
{
folderPathTbox.Text = dialog.SelectedPath;
}
}
}
}