From 0e32d8c64b7d04076a6130ab9ba7cca8673c1720 Mon Sep 17 00:00:00 2001 From: zerlei <1445089819@qq.com> Date: Fri, 27 Sep 2024 15:02:55 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E4=BA=86=E4=B8=80?= =?UTF-8?q?=E5=A0=86=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. msdepoly 删除 2. 修改删除的文件做一个备份 3. websocket 测试 --- README.md | 4 + Server/Common/DirExtension.cs | 4 +- Server/Common/FileDirOp.cs | 18 ++--- Server/LocalServer/LocalSyncServer.cs | 45 +++++++++++ Server/LocalServer/Program.cs | 11 ++- Server/LocalServer/StateHelper.cs | 78 +++++++++++++++---- Server/LocalServer/appsettings.json | 5 +- .../Controllers/RemoteServerController.cs | 2 +- Server/RemoteServer/Program.cs | 5 +- Server/RemoteServer/RemoteSyncServer.cs | 13 +++- Server/RemoteServer/StateHelper.cs | 17 ++-- Server/RemoteServer/appsettings.json | 3 +- Server/ServerTest/PipeTest.cs | 6 ++ Server/ServerTest/TestPipe.cs | 2 +- 14 files changed, 174 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index c828db1..3b92baf 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,10 @@ msbuild .\HMES-H7-HNFYMF.WEB\HMES_H7_HNFYMF.WEB.csproj /t:ResolveReferences /t:Compile /t:_CopyWebApplication /p:Configuration=Release /p:WebProjectOutputDir=C:\publish /p:OutputPath=C:\publish\bin + +& "C:\Program Files\Microsoft Visual Studio\2022\Community\\MSBuild\Current\Bin\amd64\MSBuild.exe" D:/git/HMES-H7-HNFY/HMES-H7-HNFYMF/HMES-H7-HNFYMF.WEB/HMES_H7_HNFYMF.WEB.csproj /t:ResolveReferences /t:Compile /p:Configuration=Release /t:_CopyWebApplication /p:OutputPath=D:/FileSyncTest/src/bin /p:WebProjectOutputDir=D:/FileSyncTest/src + + # 此命令是一个完整的发布命令 msdeploy.exe -verb:sync -source:contentPath=D:\git\HMES-H7-HNFY\HMES-H7-HNFYMF\HMES-H7-HNFYMF.WEB -dest:contentPath=D:\git\HMES-H7-HNFY\HMES-H7-HNFYMF\release -disablerule:BackupRule diff --git a/Server/Common/DirExtension.cs b/Server/Common/DirExtension.cs index b528408..8e429df 100644 --- a/Server/Common/DirExtension.cs +++ b/Server/Common/DirExtension.cs @@ -140,7 +140,9 @@ public static class DirExtension { lIndex_f++; rIndex_f++; - if (l.MTime != r.MTime) + // 如果最新版的时间大于旧版时间超过5s才更新,文件时间在传输过程中产生了精度损失。 + // Warrning 如果旧版文件的最后修改时间大于新版文件,将不会更新 + if ((l.MTime - r.MTime).TotalSeconds > 5) { cDir.Children.Add( new File diff --git a/Server/Common/FileDirOp.cs b/Server/Common/FileDirOp.cs index 75fcea5..d4dcb07 100644 --- a/Server/Common/FileDirOp.cs +++ b/Server/Common/FileDirOp.cs @@ -27,8 +27,7 @@ public abstract class FileDirOpStra /// 文件目录打包 /// /// -public class FileDirOpForPack(string srcRootPath, string dstRootPath) - : FileDirOpStra +public class FileDirOpForPack(string srcRootPath, string dstRootPath) : FileDirOpStra { /// /// 目标根目录 @@ -166,8 +165,7 @@ public class FileDirOpForPack(string srcRootPath, string dstRootPath) public override void DirDel(Dir dir, bool IsRecursion = true) { } } -public class FileDirOpForUnpack(string srcRootPath, string dstRootPath) - : FileDirOpStra +public class FileDirOpForUnpack(string srcRootPath, string dstRootPath) : FileDirOpStra { /// /// 解压缩,必须首先调用 @@ -196,11 +194,8 @@ public class FileDirOpForUnpack(string srcRootPath, string dstRootPath) } if (fileName != String.Empty) { - using ( - FileStream streamWriter = System.IO.File.Create( - directoryName + "/" + fileName - ) - ) + string fullFilePath = Path.Combine(directoryName, fileName); + using (FileStream streamWriter = System.IO.File.Create(fullFilePath)) { int size = 2048; byte[] data = new byte[2048]; @@ -217,6 +212,7 @@ public class FileDirOpForUnpack(string srcRootPath, string dstRootPath) } } } + System.IO.File.SetLastWriteTime(fullFilePath, theEntry.DateTime); } } } @@ -277,7 +273,7 @@ public class FileDirOpForUnpack(string srcRootPath, string dstRootPath) public override void FileModify(string absolutePath, DateTime mtime) { - this.FileCreate(absolutePath,mtime); + this.FileCreate(absolutePath, mtime); } public override void FileDel(string absolutePath) @@ -287,7 +283,7 @@ public class FileDirOpForUnpack(string srcRootPath, string dstRootPath) public override void DirDel(Dir dir, bool IsRecursion = true) { - System.IO.Directory.Delete(dir.FormatedPath,IsRecursion); + System.IO.Directory.Delete(dir.FormatedPath, IsRecursion); } } diff --git a/Server/LocalServer/LocalSyncServer.cs b/Server/LocalServer/LocalSyncServer.cs index dcb961a..d4e524a 100644 --- a/Server/LocalServer/LocalSyncServer.cs +++ b/Server/LocalServer/LocalSyncServer.cs @@ -1,3 +1,4 @@ +using System.Xml.Linq; using Common; namespace LocalServer; @@ -6,6 +7,11 @@ public class LocalSyncServer { #pragma warning disable CA2211 // Non-constant fields should not be visible public static string TempRootFile = "C:/TempPack"; + public static string SqlPackageAbPath = "sqlpackage"; + public static string MsdeployAbPath = "msdeploy"; + + //与visual studio 匹配的Msbuild 路径。在vs 中打开power shell 命令行,使用 `(get-Command -Name msbuild).Source ` + public static string MSBuildAbPath = "MSBuild"; #pragma warning restore CA2211 // Non-constant fields should not be visible private StateHelpBase StateHelper; @@ -14,6 +20,45 @@ public class LocalSyncServer StateHelper = helper; } + public static string GetProjectOutPath(string project) + { + try + { + XDocument xdoc = XDocument.Load(project); + // 获取根元素 + XElement rootElement = xdoc.Root ?? throw new NullReferenceException("Root"); + Console.WriteLine("根元素: " + rootElement.Name); + + // 遍历子节点 + foreach (XElement element in rootElement.Elements()) + { + if (element.Name.LocalName.Contains("PropertyGroup")) + { + var Conditon = element.Attribute("Condition"); + + if (Conditon != null) + { + if (Conditon.Value.Contains("Release")) + { + foreach (XElement element2 in element.Elements()) + { + if (element2.Name.LocalName == "OutputPath") + { + return element2.Value; + } + } + } + } + } + } + return "bin/"; + } + catch (Exception) + { + return "bin/"; + } + } + public StateHelpBase GetStateHelper() { return StateHelper; diff --git a/Server/LocalServer/Program.cs b/Server/LocalServer/Program.cs index 94106d7..e3840d5 100644 --- a/Server/LocalServer/Program.cs +++ b/Server/LocalServer/Program.cs @@ -1,14 +1,20 @@ using LocalServer; var builder = WebApplication.CreateBuilder(args); -ConfigurationBuilder configurationBuilder = new (); +ConfigurationBuilder configurationBuilder = new(); //添加配置文件路径 configurationBuilder.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json"); //加载文件 IConfiguration _configuration = configurationBuilder.Build(); -LocalSyncServer.TempRootFile = _configuration["TempDir"]??"C:/TempPack";; +LocalSyncServer.TempRootFile = _configuration["TempDir"] ?? "C:/TempPack"; +LocalSyncServer.SqlPackageAbPath = + _configuration["SqlPackageAbPath"] ?? "C:\\Users\\ZHAOLEI\\.dotnet\\tools\\sqlpackage.exe"; +LocalSyncServer.MsdeployAbPath = + _configuration["MsdeployAbPath"] + ?? "C:\\Program Files\\IIS\\Microsoft Web Deploy V3\\msdeploy.exe"; + // Add services to the container. builder.Services.AddControllers(); @@ -19,6 +25,7 @@ builder.Services.AddSwaggerGen(); builder.Services.AddSingleton(); var app = builder.Build(); + // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { diff --git a/Server/LocalServer/StateHelper.cs b/Server/LocalServer/StateHelper.cs index 374143e..b5895cd 100644 --- a/Server/LocalServer/StateHelper.cs +++ b/Server/LocalServer/StateHelper.cs @@ -150,39 +150,88 @@ public class DeployHelper(LocalSyncServer context) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - ProcessStartInfo startInfo = + //构建 + + //var OutputPath = LocalSyncServer.GetProjectOutPath( + // Context.NotNullSyncConfig.LocalProjectAbsolutePath + //); + //var AbOutPath = Path.Combine( + // Context.NotNullSyncConfig.LocalProjectAbsolutePath, + // OutputPath + //); + ProcessStartInfo startbuildInfo = new() { - FileName = "C:\\Program Files\\IIS\\Microsoft Web Deploy V3\\msdeploy.exe", // The command to execute (can be any command line tool) + FileName = LocalSyncServer.MSBuildAbPath, // The command to execute (can be any command line tool) Arguments = - $" -verb:sync -source:contentPath={Context.NotNullSyncConfig.LocalProjectAbsolutePath} -dest:contentPath={Context.NotNullSyncConfig.LocalRootPath} -disablerule:BackupRule", + $" {Context.NotNullSyncConfig.LocalProjectAbsolutePath} /t:ResolveReferences" + + $" /t:Compile /p:Configuration=Release /t:_CopyWebApplication /p:OutputPath={LocalSyncServer.TempRootFile}/bin" + + $" /p:WebProjectOutputDir={LocalSyncServer.TempRootFile}", // The arguments to pass to the command (e.g., list directory contents) RedirectStandardOutput = true, // Redirect the standard output to a string + RedirectStandardError = true, + StandardOutputEncoding = System.Text.Encoding.UTF8, 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 }; + using Process bprocess = new() { StartInfo = startbuildInfo }; // Start the process - process.Start(); + bprocess.Start(); // Read the output from the process - string output = process.StandardOutput.ReadToEnd(); + string boutput = bprocess.StandardOutput.ReadToEnd(); // Wait for the process to exit - process.WaitForExit(); + bprocess.WaitForExit(); - if (process.ExitCode == 0) + if (bprocess.ExitCode == 0) { Context.LocalPipe.SendMsg(CreateMsg("本地编译成功!")).Wait(); - var h = new DiffFileAndPackHelper(Context); - Context.SetStateHelper(h); - h.DiffProcess(); } else { - Context.LocalPipe.SendMsg(CreateErrMsg(output)).Wait(); - throw new Exception("执行发布错误,错误信息参考上一条消息!"); + var aTexts = boutput.Split('\n'); + if (aTexts.Length > 10) + { + boutput = string.Join('\n', aTexts.Skip(aTexts.Length - 10)); + } + Context.LocalPipe.SendMsg(CreateErrMsg(boutput)).Wait(); + throw new Exception("执行编译错误,错误信息参考上一条消息!"); } + //发布 + //ProcessStartInfo startInfo = + // new() + // { + // FileName = LocalSyncServer.MsdeployAbPath, // The command to execute (can be any command line tool) + // Arguments = + // $" -verb:sync -source:contentPath={Context.NotNullSyncConfig.LocalProjectAbsolutePath} -dest:contentPath={Context.NotNullSyncConfig.LocalRootPath} -disablerule:BackupRule", + // // 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.LocalPipe.SendMsg(CreateMsg("本地发布成功!")).Wait(); + // var h = new DiffFileAndPackHelper(Context); + // Context.SetStateHelper(h); + // h.DiffProcess(); + //} + //else + //{ + // Context.LocalPipe.SendMsg(CreateErrMsg(output)).Wait(); + // throw new Exception("执行发布错误,错误信息参考上一条消息!"); + //} } else { @@ -298,8 +347,9 @@ public class DeployMSSqlHelper(LocalSyncServer context) ProcessStartInfo startInfo = new() { - FileName = "C:\\Users\\ZHAOLEI\\.dotnet\\tools\\sqlpackage.exe", // The command to execute (can be any command line tool) + FileName = LocalSyncServer.SqlPackageAbPath, // The command to execute (can be any command line tool) Arguments = arguments, + StandardOutputEncoding = System.Text.Encoding.UTF8, // 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 diff --git a/Server/LocalServer/appsettings.json b/Server/LocalServer/appsettings.json index 234a3a5..19d036b 100644 --- a/Server/LocalServer/appsettings.json +++ b/Server/LocalServer/appsettings.json @@ -6,5 +6,8 @@ } }, "AllowedHosts": "*", - "TempDir":"D:/TempPack" + "TempDir": "D:/TempPack", + "SqlPackageAbPath": "C:\\Users\\ZHAOLEI\\.dotnet\\tools\\sqlpackage.exe", + "MsdeployAbPath": "C:\\Program Files\\IIS\\Microsoft Web Deploy V3\\msdeploy.exe", + "MSBuildAbPath": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\amd64\\MSBuild.exe" } diff --git a/Server/RemoteServer/Controllers/RemoteServerController.cs b/Server/RemoteServer/Controllers/RemoteServerController.cs index e948860..880df31 100644 --- a/Server/RemoteServer/Controllers/RemoteServerController.cs +++ b/Server/RemoteServer/Controllers/RemoteServerController.cs @@ -187,7 +187,7 @@ public class SyncFilesController(RemoteSyncServerFactory factory, SqliteDbContex else { var h = new UnPackAndReleaseHelper(server); - server.StateHelper = h; + server.SetStateHelpBase(h); h.UnPack(); } diff --git a/Server/RemoteServer/Program.cs b/Server/RemoteServer/Program.cs index bde5190..e5cfcd6 100644 --- a/Server/RemoteServer/Program.cs +++ b/Server/RemoteServer/Program.cs @@ -14,6 +14,9 @@ RemoteSyncServerFactory.NamePwd = [ .. (builder.Configuration.GetSection("NamePwds").Get[]>() ?? []) ]; +RemoteSyncServer.SqlPackageAbPath = + builder.Configuration["SqlPackageAbPath"] + ?? "C:\\Users\\ZHAOLEI\\.dotnet\\tools\\sqlpackage.exe"; RemoteSyncServer.TempRootFile = builder.Configuration["TempDir"] ?? "C:/TempPack"; builder.Services.AddControllers(); builder.Services.AddDbContext(opions => @@ -37,4 +40,4 @@ app.UseWebSockets(); app.Urls.Clear(); app.Urls.Add("http://0.0.0.0:6818"); app.MapControllers(); -app.Run(); \ No newline at end of file +app.Run(); diff --git a/Server/RemoteServer/RemoteSyncServer.cs b/Server/RemoteServer/RemoteSyncServer.cs index 79cce13..925f737 100644 --- a/Server/RemoteServer/RemoteSyncServer.cs +++ b/Server/RemoteServer/RemoteSyncServer.cs @@ -7,8 +7,19 @@ public class RemoteSyncServer { #pragma warning disable CA2211 // Non-constant fields should not be visible public static string TempRootFile = "C:/TempPack"; + public static string SqlPackageAbPath = "SqlPackageAbPath"; #pragma warning restore CA2211 // Non-constant fields should not be visible - public StateHelpBase StateHelper; + private StateHelpBase StateHelper; + + public void SetStateHelpBase(StateHelpBase stateHelper) + { + StateHelper = stateHelper; + } + + public StateHelpBase GetStateHelpBase() + { + return StateHelper; + } public Config? SyncConfig; diff --git a/Server/RemoteServer/StateHelper.cs b/Server/RemoteServer/StateHelper.cs index a9e8327..3f025cd 100644 --- a/Server/RemoteServer/StateHelper.cs +++ b/Server/RemoteServer/StateHelper.cs @@ -73,7 +73,7 @@ public class ConnectAuthorityHelper(RemoteSyncServer context) if (msg.Body == Context.Pwd) { var h = new DiffFileHelper(Context); - Context.StateHelper = h; + Context.SetStateHelpBase(h); Context.Pipe.SendMsg(CreateMsg("RemoteServer: 密码验证成功!")); } else @@ -106,6 +106,13 @@ public class DiffFileHelper(RemoteSyncServer context) 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( @@ -114,7 +121,7 @@ public class DiffFileHelper(RemoteSyncServer context) } }); var h = new UnPackAndReleaseHelper(Context); - Context.StateHelper = h; + Context.SetStateHelpBase(h); //将对比结果发送到Local Context.Pipe.SendMsg(CreateMsg(JsonSerializer.Serialize(diffConfigs))); } @@ -131,7 +138,7 @@ public class UnPackAndReleaseHelper(RemoteSyncServer context) ); Context.Pipe.SendMsg(CreateMsg("解压完成!")).Wait(); var h = new FinallyPublishHelper(Context); - Context.StateHelper = h; + Context.SetStateHelpBase(h); h.FinallyPublish(); } @@ -156,8 +163,8 @@ public class FinallyPublishHelper(RemoteSyncServer context) ProcessStartInfo startInfo = new() { - FileName = "C:\\Users\\ZHAOLEI\\.dotnet\\tools\\sqlpackage.exe", // The command to execute (can be any command line tool) - Arguments = arguments, + StandardOutputEncoding = System.Text.Encoding.UTF8, + 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 diff --git a/Server/RemoteServer/appsettings.json b/Server/RemoteServer/appsettings.json index 39282a4..70b1de0 100644 --- a/Server/RemoteServer/appsettings.json +++ b/Server/RemoteServer/appsettings.json @@ -12,5 +12,6 @@ "TempDir":"D:/TempPack2", "NamePwds":[ ["test","testpwd"] - ] + ], + "SqlPackageAbPath": "C:\\Users\\ZHAOLEI\\.dotnet\\tools\\sqlpackage.exe", } diff --git a/Server/ServerTest/PipeTest.cs b/Server/ServerTest/PipeTest.cs index 9ed63db..c209ab6 100644 --- a/Server/ServerTest/PipeTest.cs +++ b/Server/ServerTest/PipeTest.cs @@ -43,6 +43,12 @@ public class PipeTest p3.Other = p4; p4.Other = p3; LocalSyncServer.TempRootFile = "D:/FileSyncTest/stemp"; + RemoteSyncServer.SqlPackageAbPath = "C:\\Users\\ZHAOLEI\\.dotnet\\tools\\sqlpackage.exe"; + LocalSyncServer.MsdeployAbPath = + "C:\\Program Files\\IIS\\Microsoft Web Deploy V3\\msdeploy.exe"; + LocalSyncServer.SqlPackageAbPath = "C:\\Users\\ZHAOLEI\\.dotnet\\tools\\sqlpackage.exe"; + LocalSyncServer.MSBuildAbPath = + "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\amd64\\MSBuild.exe"; RemoteSyncServer.TempRootFile = "D:/FileSyncTest/dtemp"; RemoteSyncServerFactory.NamePwd = [new Tuple("Test", "t123")]; var lf = new LocalSyncServerFactory(); diff --git a/Server/ServerTest/TestPipe.cs b/Server/ServerTest/TestPipe.cs index c277780..f96897f 100644 --- a/Server/ServerTest/TestPipe.cs +++ b/Server/ServerTest/TestPipe.cs @@ -46,7 +46,7 @@ namespace ServerTest { var it = syncServerFactory.GetServerByName("Test"); var h = new UnPackAndReleaseHelper(it); - it.StateHelper = h; + it.SetStateHelpBase(h); h.UnPack(); }); });