using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Security; using System.Diagnostics; using System.Net; using Renci.SshNet; using Serilog; using Newtonsoft.Json.Linq; using System.ServiceProcess; using Renci.SshNet.Messages; using System.Management; using System.IO; using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window; namespace PublishSite { public partial class PublishForm : Form { public PublishForm() { InitializeComponent(); Serilog.Log.Logger = new LoggerConfiguration() .WriteTo.File("logs\\log.txt", rollingInterval: RollingInterval.Day) .CreateLogger(); } public string EnvName = ""; public JObject jObjectCofig; public string Host = ""; public string UserName = ""; public string Password = ""; private void WinformLog(string message, Color? color = null) { if (InvokeRequired) { Invoke(new Action(() => WinformLog(message, color))); return; } logTBox.SelectionColor = color == null ? Color.Green : (Color)color; logTBox.AppendText($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}: {message}" + Environment.NewLine); Serilog.Log.Information(message); } #region 切换环境 配置回写 private void rb_Env_CheckedChanged(object sender, EventArgs e) { //本地 if (rb_local.Checked) { EnvName = "本地"; WinformLog($"当前操作环境切换为: 本地", Color.DarkRed); var configJson = File.ReadAllText("appsettings.local.json"); jObjectCofig = JObject.Parse(configJson); } //测试 if (rb_test.Checked) { EnvName = "测试"; WinformLog($"当前操作环境切换为: 测试", Color.DarkRed); var configJson = File.ReadAllText("appsettings.Development.json"); jObjectCofig = JObject.Parse(configJson); } //验证 if (rb_Verify.Checked) { EnvName = "验证"; WinformLog($"当前操作环境切换为: 验证", Color.DarkRed); var configJson = File.ReadAllText("appsettings.Verify.json"); jObjectCofig = JObject.Parse(configJson); } //生产 if (rb_production.Checked) { EnvName = "生产"; WinformLog($"当前操作环境切换为: 生产", Color.DarkRed); var configJson = File.ReadAllText("appsettings.Production.json"); jObjectCofig = JObject.Parse(configJson); } #region 界面控件赋值 Host = rb_local.Checked ? "" : jObjectCofig["Credential"]["Host"].ToString(); UserName = rb_local.Checked ? "" : jObjectCofig["Credential"]["UserName"].ToString(); Password = rb_local.Checked ? "" : jObjectCofig["Credential"]["Password"].ToString(); serviceNameTBox.Text = jObjectCofig["DefaultService"]["ServiceName"].ToString(); serviceDisplayNameTBox.Text = jObjectCofig["DefaultService"]["ServiceDisplayName"].ToString(); servicePortTBox.Text = jObjectCofig["DefaultService"]["ServicePort"].ToString(); exePathTbox.Text = jObjectCofig["DefaultService"]["BinPath"].ToString(); en_TBox.Text = jObjectCofig["DefaultService"]["Env"].ToString(); startOrStopServiceTbox.Text = jObjectCofig["DefaultService"]["ServiceName"].ToString(); bakDbName.Text = jObjectCofig["BackUp"]["DataBaseName"].ToString(); backPathTBox.Text = jObjectCofig["BackUp"]["BackPath"].ToString(); backExePath.Text = jObjectCofig["DefaultService"]["BinPath"].ToString(); var credentialNode = jObjectCofig["Credential"]; var defaultServiceNode = jObjectCofig["DefaultService"]; var BackUpNode = jObjectCofig["BackUp"]; #endregion } private void serviceConfigSaveBtn_Click(object sender, EventArgs e) { serviceConfigSaveBtn.Enabled = false; var serviceName = serviceNameTBox.Text; DialogResult dr = MessageBox.Show($"{EnvName}环境服务配置回写 ?", "保存提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning); if (dr == DialogResult.OK) { var path = string.Empty; if (rb_local.Checked) { path = "appsettings.local.json"; } if (rb_test.Checked) { path = "appsettings.Development.json"; } if (rb_Verify.Checked) { path = "appsettings.Verify.json"; } if (rb_production.Checked) { path = "appsettings.Production.json"; } var configJson = File.ReadAllText(path); jObjectCofig = JObject.Parse(configJson); jObjectCofig["DefaultService"]["ServiceName"] = serviceNameTBox.Text.Trim(); jObjectCofig["DefaultService"]["ServiceDisplayName"] = serviceDisplayNameTBox.Text.Trim(); jObjectCofig["DefaultService"]["ServicePort"] = servicePortTBox.Text.Trim(); jObjectCofig["DefaultService"]["BinPath"] = exePathTbox.Text.Trim(); jObjectCofig["DefaultService"]["Env"] = en_TBox.Text.Trim(); File.WriteAllText(path, jObjectCofig.ToString()); WinformLog("服务配置回写成功!"); } serviceConfigSaveBtn.Enabled = true; } private void bakConfigSaveBtn_Click(object sender, EventArgs e) { bakConfigSaveBtn.Enabled = false; var serviceName = serviceNameTBox.Text; DialogResult dr = MessageBox.Show($"{EnvName}环境备份配置回写 ?", "保存提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning); if (dr == DialogResult.OK) { var path = string.Empty; if (rb_local.Checked) { path = "appsettings.local.json"; } if (rb_test.Checked) { path = "appsettings.Development.json"; } if (rb_Verify.Checked) { path = "appsettings.Verify.json"; } if (rb_production.Checked) { path = "appsettings.Production.json"; } var configJson = File.ReadAllText(path); jObjectCofig = JObject.Parse(configJson); jObjectCofig["BackUp"]["DataBaseName"] = bakDbName.Text.Trim(); jObjectCofig["BackUp"]["BackPath"] = backPathTBox.Text.Trim(); File.WriteAllText(path, jObjectCofig.ToString()); WinformLog("备份配置回写成功!"); bakConfigSaveBtn.Enabled = true; } } #endregion #region 备份 private async void startBakBtn_Click(object sender, EventArgs e) { await Task.Run(() => { if (rb_local.Checked) { WinformLog("本地环境不支持备份操作,懒得开发"); return; } else { using (var client = new SshClient(Host, UserName, Password)) { // 连接到远程服务器 client.Connect(); try { var dbName = bakDbName.Text.Trim(); var backRootPath = backPathTBox.Text.Trim(); var serviceName = jObjectCofig["DefaultService"]["ServiceName"].ToString().Trim(); var programPath = backExePath.Text.Trim(); var programFolder = Path.GetDirectoryName(programPath); var dbUser = jObjectCofig["BackUp"]["DBUser"].ToString().Trim(); var dbPwd = jObjectCofig["BackUp"]["DBPwd"].ToString().Trim(); var backupFolderPath = Path.Combine(backRootPath, DateTime.Now.ToString("yyyyMMdd")); //创建文件夹 WinformLog("准备当日备份文件夹..."); var command = client.CreateCommand($"if not exist \"{backupFolderPath}\" mkdir \"{backupFolderPath}\""); command.Execute(); if (command.ExitStatus != 0) { throw new Exception($"Failed to create {backupFolderPath}."); } //停止服务 WinformLog($"停止后台服务{serviceName}..."); var stopServiceCommand = client.CreateCommand($"sc stop \"{serviceName}\""); stopServiceCommand.Execute(); if (stopServiceCommand.ExitStatus != 0) { throw new Exception($"Failed to stop {serviceName}."); } Task.Delay(1000); //备份后端文件 WinformLog($"备份后端文件..."); string archivePath = $"{backupFolderPath}\\NetCore.zip"; var compressCommand = client.CreateCommand($"powershell.exe Compress-Archive -Path \"{programFolder}\\*.*\" -DestinationPath \"{archivePath}\" -Force"); compressCommand.Execute(); if (compressCommand.ExitStatus != 0) { throw new Exception("Failed to compress and move folder contents."); } //启动服务 WinformLog($"启动后台服务{serviceName}..."); var startServiceCommand = client.CreateCommand($"sc start \"{serviceName}\""); startServiceCommand.Execute(); if (startServiceCommand.ExitStatus != 0) { throw new Exception($"Failed to start {serviceName}."); } //备份数据库 WinformLog($"开始备份数据库{dbName}..."); string databaseBackupPath = $"{backupFolderPath}\\db.bak"; var sqlcommand = client.CreateCommand($"sqlcmd -S . -U \"{dbUser}\" -P \"{dbPwd}\" -Q \"BACKUP DATABASE [{dbName}] TO DISK='{databaseBackupPath}' WITH INIT\""); sqlcommand.Execute(); if (sqlcommand.ExitStatus != 0) { throw new Exception("Failed to backup database."); } WinformLog($"备份操作执行结束..."); } catch (Exception ex) { WinformLog($"{ex.Message}", Color.Red); } } } }); } #endregion #region 服务的创建与删除 private void createService_Btn_Click(object sender, EventArgs e) { } private async void deleteService_Btn_Click(object sender, EventArgs e) { var serviceName = serviceNameTBox.Text; DialogResult dr = MessageBox.Show($"{EnvName}环境删除服务:{serviceName}?", "删除提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning); if (dr == DialogResult.OK) { await Task.Run(() => { if (rb_local.Checked) { ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = "cmd.exe"; startInfo.Arguments = $"/c sc query {serviceName} | find \"STATE\" | find /i \"RUNNING\" && net stop {serviceName} & sc delete {serviceName}"; // 在后台运行命令行窗口 startInfo.WindowStyle = ProcessWindowStyle.Hidden; startInfo.CreateNoWindow = true; using (Process process = new Process()) { process.StartInfo = startInfo; process.Start(); process.WaitForExit(); if (process.ExitCode == 0) { WinformLog($"{serviceName} 服务已经成功删除!"); } else { WinformLog($"尝试停止并删除 {serviceName} 服务失败,请检查是否拥有管理员权限或服务是否存在。", Color.Red); } } } else { using (var client = new SshClient(Host, UserName, Password)) { // 连接到远程服务器 client.Connect(); // 停止服务 string stopCommand = $"sc stop {serviceName}"; using (var stopCmd = client.CreateCommand(stopCommand)) { WinformLog(stopCommand); var stopOutput = stopCmd.Execute(); WinformLog(stopOutput); } // 删除服务 string deleteCommand = $"sc delete {serviceName}"; using (var deleteCmd = client.CreateCommand(deleteCommand)) { WinformLog(deleteCommand); var deleteOutput = deleteCmd.Execute(); WinformLog(deleteOutput); } // 断开SSH连接 client.Disconnect(); } } }); } } private void selectPathBtn_Click(object sender, EventArgs e) { if (rb_local.Checked) { OpenFileDialog dialog = new OpenFileDialog(); if (dialog.ShowDialog() == DialogResult.OK) { exePathTbox.Text = dialog.FileName; WinformLog($"部署启动文件选择成功", Color.Green); } } else { WinformLog("远程环境不支持直接选择目录", Color.Red); } } #endregion #region 测试环境发布 private async void vuePublishBtn_Click(object sender, EventArgs e) { vuePublishBtn.Enabled = false; await Task.Run(() => { using (var client = new SshClient("123.56.94.154", "Administrator", "WHxckj2019")) { // 连接到远程服务器 client.Connect(); //&& ./IRaCIS_Vue_Web.bat string command = $@"cd C:\Users\Administrator\VueSourceCode && npm i && npm run build"; using (var cmd = client.CreateCommand(command)) { WinformLog("测试环境:开始执行前端发布"); WinformLog(command); var output = cmd.Execute(); WinformLog(output); var output3 = cmd.Execute($@"xcopy /Y /Q ""C:\Users\Administrator\VueSourceCode\dist\index.html"" ""D:\Develop\PublishSite\IRaCIS.Vue.Web\dist\"""); WinformLog(output); WinformLog("测试环境:前端发布成功"); } // 断开SSH连接 client.Disconnect(); } }); vuePublishBtn.Enabled = true; } private async void netCorePublishBtn_Click(object sender, EventArgs e) { netCorePublishBtn.Enabled = false; await Task.Run(() => { using (var client = new SshClient("123.56.94.154", "Administrator", "WHxckj2019")) { // 连接到远程服务器 client.Connect(); string command = $@"C:\Users\Administrator\bat\IRaCIS_Core_API.bat"; using (var cmd = client.CreateCommand(command)) { WinformLog("测试环境:开始执行后端发布"); WinformLog(command); var output = cmd.Execute(); WinformLog(output); WinformLog("测试环境:后端发布成功"); } // 断开SSH连接 client.Disconnect(); } }); netCorePublishBtn.Enabled = true; } #endregion #region 服务的启动与停止 private async void startServiceBtn_Click(object sender, EventArgs e) { startServiceBtn.Enabled = false; await Task.Run(() => { if (rb_local.Checked) { ServiceController controller = new ServiceController($"{startOrStopServiceTbox.Text}"); if (controller?.Status == ServiceControllerStatus.Running) { controller.Stop(); controller.WaitForStatus(ServiceControllerStatus.Stopped); } else { WinformLog("服务不是停止状态", Color.Red); } return; } using (var client = new SshClient(Host, UserName, Password)) { // 连接到远程服务器 client.Connect(); string command = $@"sc start {startOrStopServiceTbox.Text}"; using (var cmd = client.CreateCommand(command)) { WinformLog(command); var output = cmd.Execute(); WinformLog(output); } // 断开SSH连接 client.Disconnect(); } }); startServiceBtn.Enabled = true; } private async void stopServiceBtn_Click(object sender, EventArgs e) { startServiceBtn.Enabled = false; await Task.Run(() => { if (rb_local.Checked) { ServiceController controller = new ServiceController($"{startOrStopServiceTbox.Text}"); if (controller?.Status == ServiceControllerStatus.Running) { controller.Stop(); controller.WaitForStatus(ServiceControllerStatus.Stopped); } else { WinformLog("服务不是启动状态", Color.Red); } return; } using (var client = new SshClient(Host, UserName, Password)) { // 连接到远程服务器 client.Connect(); string command = $@"sc stop {startOrStopServiceTbox.Text}"; using (var cmd = client.CreateCommand(command)) { WinformLog(command); var output = cmd.Execute(); WinformLog(output); } // 断开SSH连接 client.Disconnect(); } }); startServiceBtn.Enabled = true; } #endregion #region 上传文件到远程服务器发布 private void selectPublishFilePathBtn_Click(object sender, EventArgs e) { OpenFileDialog dialog = new OpenFileDialog(); if (dialog.ShowDialog() == DialogResult.OK) { publishFileTBox.Text = dialog.FileName; WinformLog($"远程部署文件选择成功", Color.Green); } } private void selectPublishFolderPathBtn_Click(object sender, EventArgs e) { FolderBrowserDialog dialog = new FolderBrowserDialog(); dialog.Description = "选择目录"; if (dialog.ShowDialog() == DialogResult.OK) { publishFolderTBox.Text = dialog.SelectedPath; WinformLog($"远程部署后端发布文件夹选择成功", Color.Green); } } private void sshVuePublishBtn_Click(object sender, EventArgs e) { } private void sshNetCorePublishBtn_Click(object sender, EventArgs e) { } private void sshNetCorePublishBtn2_Click(object sender, EventArgs e) { } #endregion } }