using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; using System.Text.Json; using Common; namespace RemoteServer; public abstract class StateHelpBase( RemoteSyncServer context, SyncProcessStep step = SyncProcessStep.Connect ) { protected readonly RemoteSyncServer Context = context; public readonly SyncProcessStep Step = step; public SyncMsg CreateErrMsg(string Body) { return new SyncMsg { Body = Body, Type = SyncMsgType.Error, Step = Step }; } public SyncMsg CreateMsg(string body, SyncMsgType type = SyncMsgType.General) { return new SyncMsg { Body = body, Type = type, Step = Step }; } public bool ReceiveMsg(byte[] bytes) { var msg = Encoding.UTF8.GetString(bytes); var syncMsg = JsonSerializer.Deserialize(msg) ?? throw new NullReferenceException("msg is null"); if (syncMsg.Step != Step && syncMsg.Step != SyncProcessStep.Close) { throw new Exception("Sync step error!"); } HandleMsg(syncMsg); return true; } protected abstract void HandleMsg(SyncMsg msg); } /// /// 0. 链接验证 /// /// public class ConnectAuthorityHelper(RemoteSyncServer context) : StateHelpBase(context, SyncProcessStep.Connect) { protected override void HandleMsg(SyncMsg msg) { if (msg.Body == Context.Pwd) { var h = new DiffFileHelper(Context); Context.SetStateHelpBase(h); Context.Pipe.SendMsg(CreateMsg("RemoteServer: 密码验证成功!")); } else { throw new Exception("密码错误!"); } } } public class DiffFileHelper(RemoteSyncServer context) : StateHelpBase(context, SyncProcessStep.DiffFileAndPack) { protected override void HandleMsg(SyncMsg msg) { Context.SyncConfig = JsonSerializer.Deserialize(msg.Body); var diffConfigs = new List(); //文件对比 Context.NotNullSyncConfig.DirFileConfigs.ForEach(e => { if (e.LocalDirInfo == null) { throw new NullReferenceException("RemoteServer: 发布的文件为空!--这个异常应该永远不会发生~"); } else { var nd = new Dir { Path = Context.NotNullSyncConfig.RemoteRootPath + e.DirPath, Children = [] }; nd.ExtractInfo(e.CherryPicks, e.Excludes); var nl = e.LocalDirInfo.Clone(); nl.ResetRootPath( Context.NotNullSyncConfig.LocalRootPath, Context.NotNullSyncConfig.RemoteRootPath ); //var x = JsonSerializer.Serialize(nd); //var x2 = JsonSerializer.Serialize(nl); e.DiffDirInfo = e.LocalDirInfo.Diff(nd); e.RemoteDirInfo = nd; diffConfigs.Add( new DirFileConfig { DiffDirInfo = e.DiffDirInfo, DirPath = e.DirPath } ); } }); var h = new UnPackAndReleaseHelper(Context); Context.SetStateHelpBase(h); //将对比结果发送到Local Context.Pipe.SendMsg(CreateMsg(JsonSerializer.Serialize(diffConfigs))); } } public class UnPackAndReleaseHelper(RemoteSyncServer context) : StateHelpBase(context, SyncProcessStep.UploadAndUnpack) { public void UnPack() { FileDirOpForUnpack.FirstUnComparess( Path.Combine(RemoteSyncServer.TempRootFile), Context.NotNullSyncConfig.Id.ToString() ); Context.Pipe.SendMsg(CreateMsg("解压完成!")).Wait(); var h = new FinallyPublishHelper(Context); Context.SetStateHelpBase(h); Context.Pipe.SendMsg(h.CreateMsg("将要发布数据库,可能时间会较长!")).Wait(); Task.Run(() => { try { h.FinallyPublish(); } catch (Exception e) { Context.Close(e.Message); } }); } protected override void HandleMsg(SyncMsg msg) { } } public class FinallyPublishHelper(RemoteSyncServer context) : StateHelpBase(context, SyncProcessStep.Publish) { public void FinallyPublish() { // 发布数据库 if (Context.NotNullSyncConfig.IsDeployDb) { var arguments = $" /Action:Publish /SourceFile:{RemoteSyncServer.TempRootFile}/{Context.NotNullSyncConfig.Id.ToString()}/{Context.NotNullSyncConfig.Id}.dacpac" + $" /TargetServerName:{Context.NotNullSyncConfig.DstDb.ServerName} /TargetDatabaseName:{Context.NotNullSyncConfig.DstDb.DatabaseName}" + $" /TargetUser:{Context.NotNullSyncConfig.DstDb.User} /TargetPassword:{Context.NotNullSyncConfig.DstDb.Password} /TargetTrustServerCertificate:True"; //Context // .Pipe.SendMsg(CreateMsg($"发布脚本为: {RemoteSyncServer.SqlPackageAbPath} {arguments}")) // .Wait(); ProcessStartInfo startInfo = new() { // StandardOutputEncoding = System.Text.Encoding.UTF8, Arguments = arguments, FileName = RemoteSyncServer.SqlPackageAbPath, // The command to execute (can be any command line tool) // The arguments to pass to the command (e.g., list directory contents) RedirectStandardOutput = true, // Redirect the standard output to a string UseShellExecute = false, // Do not use the shell to execute the command CreateNoWindow = true // Do not create a new window for the command }; using Process process = new() { StartInfo = startInfo }; // Start the process process.Start(); // Read the output from the process string output = process.StandardOutput.ReadToEnd(); // Wait for the process to exit process.WaitForExit(); if (process.ExitCode == 0) { Context.Pipe.SendMsg(CreateMsg("数据库发布成功!")).Wait(); } else { Context.Pipe.SendMsg(CreateErrMsg(output)).Wait(); throw new Exception("执行发布错误,错误信息参考上一条消息!"); } } else { Context.Pipe.SendMsg(CreateMsg("跳过数据库发布!")).Wait(); } var DirFileOp = new FileDirOpForUnpack( Path.Combine(RemoteSyncServer.TempRootFile, Context.NotNullSyncConfig.Id.ToString()), Context.NotNullSyncConfig.RemoteRootPath ); Context.NotNullSyncConfig.DirFileConfigs.ForEach(e => { if (e.RemoteDirInfo != null && e.DiffDirInfo != null) { e.RemoteDirInfo.Combine(DirFileOp, e.DiffDirInfo, false, true); } }); Context.SetStateHelpBase(new NormalCloseHelper(Context)); Context.Pipe.SendMsg(CreateMsg("发布完成!")).Wait(); } protected override void HandleMsg(SyncMsg msg) { } } public class NormalCloseHelper(RemoteSyncServer context) : StateHelpBase(context, SyncProcessStep.Close) { protected override void HandleMsg(SyncMsg msg) { } }