diff --git a/imgs/bowl.jpeg b/imgs/bowl.jpeg
new file mode 100644
index 00000000..b099e216
Binary files /dev/null and b/imgs/bowl.jpeg differ
diff --git a/src/c#/GeneralUpdate.Bowl/Applications/Windows/export.bat b/src/c#/GeneralUpdate.Bowl/Applications/Windows/export.bat
new file mode 100644
index 00000000..80921e8e
--- /dev/null
+++ b/src/c#/GeneralUpdate.Bowl/Applications/Windows/export.bat
@@ -0,0 +1,40 @@
+@echo off
+setlocal
+
+if "%~1"=="" (
+ echo Please provide the export path as the first parameter.
+ exit /b 1
+)
+
+set exportDir=%~1
+
+if not exist "%exportDir%" (
+ mkdir "%exportDir%"
+)
+
+set outputFile=%exportDir%\driverInfo.txt
+
+:: 导出驱动信息
+driverquery /v /fo table > "%outputFile%"
+echo %outputFile% Export successfully.
+
+:: 导出系统信息
+set systemInfoFile=%exportDir%\systeminfo.txt
+systeminfo > "%systemInfoFile%"
+echo %systemInfoFile% Export successfully.
+
+:: 获取当前日期
+for /f "tokens=1-4 delims=/- " %%i in ('date /t') do (
+ set yyyy=%%i
+ set mm=%%j
+ set dd=%%k
+)
+
+:: 设置日志文件名
+set logFile=%exportDir%\systemlog.evtx
+
+:: 导出系统日志
+wevtutil epl System "%logFile%" /q:"*[System[TimeCreated[timediff(@SystemTime) <= 86400000]]]"
+echo %logFile% Export successfully.
+
+endlocal
\ No newline at end of file
diff --git a/src/c#/GeneralUpdate.Bowl/Bowl.cs b/src/c#/GeneralUpdate.Bowl/Bowl.cs
index fc828ebb..b745ba18 100644
--- a/src/c#/GeneralUpdate.Bowl/Bowl.cs
+++ b/src/c#/GeneralUpdate.Bowl/Bowl.cs
@@ -1,39 +1,64 @@
using System;
+using System.IO;
using System.Runtime.InteropServices;
+using System.Text.Json;
using GeneralUpdate.Bowl.Strategys;
+using GeneralUpdate.Common.AOT.JsonContext;
+using GeneralUpdate.Common.Shared.Object;
namespace GeneralUpdate.Bowl;
-public class Bowl
+///
+/// Surveillance Main Program.
+///
+public sealed class Bowl
{
- private IStrategy _strategy;
+ private static IStrategy? _strategy;
- public Bowl(MonitorParameter parameter = null)
- {
- CreateStrategy();
- _strategy!.SetParameter(parameter);
- }
+ private Bowl() { }
- private void CreateStrategy()
+ private static void CreateStrategy()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
_strategy = new WindowStrategy();
}
- else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+ /*else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
_strategy = new LinuxStrategy();
- }
+ }*/
+
+ if (_strategy == null)
+ throw new PlatformNotSupportedException("Unsupported operating system");
+ }
+
+ public static void Launch(MonitorParameter? monitorParameter = null)
+ {
+ monitorParameter ??= CreateParameter();
+ CreateStrategy();
+ _strategy?.SetParameter(monitorParameter);
+ _strategy?.Launch();
}
- public Bowl SetParameter(MonitorParameter parameter)
+ private static MonitorParameter CreateParameter()
{
- if(parameter.Verify())
- throw new ArgumentException("Parameter contains illegal values");
+ var json = Environment.GetEnvironmentVariable("ProcessInfo", EnvironmentVariableTarget.User);
+ if(string.IsNullOrWhiteSpace(json))
+ throw new ArgumentNullException("ProcessInfo environment variable not set !");
+
+ var processInfo = JsonSerializer.Deserialize(json, ProcessInfoJsonContext.Default.ProcessInfo);
+ if(processInfo == null)
+ throw new ArgumentNullException("ProcessInfo json deserialize fail!");
- _strategy.SetParameter(parameter);
- return this;
+ return new MonitorParameter
+ {
+ ProcessNameOrId = processInfo.AppName,
+ DumpFileName = $"{processInfo.LastVersion}_fail.dmp",
+ FailFileName = $"{processInfo.LastVersion}_fail.json",
+ TargetPath = processInfo.InstallPath,
+ FailDirectory = Path.Combine(processInfo.InstallPath, "fail", processInfo.LastVersion),
+ BackupDirectory = Path.Combine(processInfo.InstallPath, processInfo.LastVersion),
+ ExtendedField = processInfo.LastVersion
+ };
}
-
- public void Launch() => _strategy.Launch();
}
\ No newline at end of file
diff --git a/src/c#/GeneralUpdate.Bowl/GeneralUpdate.Bowl.csproj b/src/c#/GeneralUpdate.Bowl/GeneralUpdate.Bowl.csproj
index 3c0d6140..0c47f789 100644
--- a/src/c#/GeneralUpdate.Bowl/GeneralUpdate.Bowl.csproj
+++ b/src/c#/GeneralUpdate.Bowl/GeneralUpdate.Bowl.csproj
@@ -25,6 +25,17 @@
PreserveNewest
+
+ PreserveNewest
+
+
+
+
+
+
+
+
+
diff --git a/src/c#/GeneralUpdate.Bowl/Strategys/AbstractStrategy.cs b/src/c#/GeneralUpdate.Bowl/Strategys/AbstractStrategy.cs
index dcf8f275..4feb140a 100644
--- a/src/c#/GeneralUpdate.Bowl/Strategys/AbstractStrategy.cs
+++ b/src/c#/GeneralUpdate.Bowl/Strategys/AbstractStrategy.cs
@@ -1,32 +1,37 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
+using GeneralUpdate.Common.FileBasic;
namespace GeneralUpdate.Bowl.Strategys;
public abstract class AbstractStrategy : IStrategy
{
protected MonitorParameter _parameter;
-
- private readonly IReadOnlyList _sensitiveCharacter = new List
- {
- "Exit",
- "exit"
- };
+ protected List OutputList = new ();
+
+ public void SetParameter(MonitorParameter parameter) => _parameter = parameter;
public virtual void Launch()
{
- Backup();
- Startup(_parameter.ProcessNameOrId, _parameter.InnerArguments);
+ Startup(_parameter.InnerApp, _parameter.InnerArguments);
}
private void Startup(string appName, string arguments)
{
+ if (Directory.Exists(_parameter.FailDirectory))
+ {
+ Directory.Delete(_parameter.FailDirectory, true);
+ }
+ Directory.CreateDirectory(_parameter.FailDirectory);
+
var startInfo = new ProcessStartInfo
{
FileName = appName,
Arguments = arguments,
RedirectStandardOutput = true,
+ RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};
@@ -35,71 +40,15 @@ private void Startup(string appName, string arguments)
process.OutputDataReceived += OutputHandler;
process.ErrorDataReceived += OutputHandler;
process.Start();
- process.StandardOutput.ReadToEnd();
- process.WaitForExit();
+ process.BeginOutputReadLine();
+ process.BeginErrorReadLine();
+ process.WaitForExit(1000 * 10);
}
private void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
var data = outLine.Data;
if (!string.IsNullOrEmpty(data))
- {
- foreach (var sensitive in _sensitiveCharacter)
- {
- if (data.Contains(sensitive)){
- Restore();
- Process.Start(_parameter.ProcessNameOrId, _parameter.Arguments);
- break;
- }
- }
- }
+ OutputList.Add(data);
}
-
- private void Backup()
- {
- var backupPath = _parameter.Target;
- var sourcePath = _parameter.Source;
-
- if (Directory.Exists(backupPath))
- {
- Directory.Delete(backupPath, true);
- }
-
- Directory.CreateDirectory(backupPath);
-
- foreach (string dirPath in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories))
- {
- Directory.CreateDirectory(dirPath.Replace(sourcePath, backupPath));
- }
-
- foreach (string newPath in Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories))
- {
- File.Copy(newPath, newPath.Replace(sourcePath, backupPath), true);
- }
- }
-
- private void Restore()
- {
- var restorePath = _parameter.Target;
- var backupPath = _parameter.Source;
-
- if (Directory.Exists(restorePath))
- {
- Directory.Delete(restorePath, true);
- }
-
- Directory.CreateDirectory(restorePath);
-
- foreach (string dirPath in Directory.GetDirectories(backupPath, "*", SearchOption.AllDirectories))
- {
- Directory.CreateDirectory(dirPath.Replace(backupPath, restorePath));
- }
-
- foreach (string newPath in Directory.GetFiles(backupPath, "*.*", SearchOption.AllDirectories))
- {
- File.Copy(newPath, newPath.Replace(backupPath, restorePath), true);
- }
- }
-
- public void SetParameter(MonitorParameter parameter) => _parameter = parameter;
}
\ No newline at end of file
diff --git a/src/c#/GeneralUpdate.Bowl/Strategys/Crash.cs b/src/c#/GeneralUpdate.Bowl/Strategys/Crash.cs
new file mode 100644
index 00000000..3982504d
--- /dev/null
+++ b/src/c#/GeneralUpdate.Bowl/Strategys/Crash.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+
+namespace GeneralUpdate.Bowl.Strategys;
+
+public class Crash
+{
+ public MonitorParameter Parameter { get; set; }
+
+ public List ProcdumpOutPutLines { get; set; }
+}
\ No newline at end of file
diff --git a/src/c#/GeneralUpdate.Bowl/Strategys/LinuxStrategy.cs b/src/c#/GeneralUpdate.Bowl/Strategys/LinuxStrategy.cs
index 64f300c5..bb1c93bf 100644
--- a/src/c#/GeneralUpdate.Bowl/Strategys/LinuxStrategy.cs
+++ b/src/c#/GeneralUpdate.Bowl/Strategys/LinuxStrategy.cs
@@ -8,14 +8,16 @@ namespace GeneralUpdate.Bowl.Strategys;
public class LinuxStrategy : AbstractStrategy
{
- /*procdump-3.3.0-0.cm2.x86_64.rpm:
- 适合系统:此RPM包可能适用于基于CentOS或RHEL的某些派生版本,具体来说是CM2版本。CM2通常指的是ClearOS 7.x或类似的社区维护版本。
- procdump-3.3.0-0.el8.x86_64.rpm:
- 适合系统:此RPM包适用于Red Hat Enterprise Linux 8 (RHEL 8)、CentOS 8及其他基于RHEL 8的发行版。
- procdump_3.3.0_amd64.deb:
- 适合系统:此DEB包适用于Debian及其衍生发行版,如Ubuntu,适用于64位系统(amd64架构)。*/
+ /*procdump-3.3.0-0.cm2.x86_64.rpm:
+ Compatible Systems: This RPM package may be suitable for certain CentOS or RHEL-based derivatives, specifically the CM2 version. CM2 typically refers to ClearOS 7.x or similar community-maintained versions.
+
+ procdump-3.3.0-0.el8.x86_64.rpm:
+ Compatible Systems: This RPM package is suitable for Red Hat Enterprise Linux 8 (RHEL 8), CentOS 8, and other RHEL 8-based distributions.
+
+ procdump_3.3.0_amd64.deb:
+ Compatible Systems: This DEB package is suitable for Debian and its derivatives, such as Ubuntu, for 64-bit systems (amd64 architecture).*/
- private IReadOnlyList procdump_amd64 = new List { "Ubuntu", "Debian" };
+ private IReadOnlyList _rocdumpAmd64 = new List { "Ubuntu", "Debian" };
private IReadOnlyList procdump_el8_x86_64 = new List { "Red Hat", "CentOS", "Fedora" };
private IReadOnlyList procdump_cm2_x86_64 = new List { "ClearOS" };
@@ -64,9 +66,9 @@ private void Install()
private string GetPacketName()
{
- string packageFileName = string.Empty;
- LinuxSystem system = GetSystem();
- if (procdump_amd64.Contains(system.Name))
+ var packageFileName = string.Empty;
+ var system = GetSystem();
+ if (_rocdumpAmd64.Contains(system.Name))
{
packageFileName = $"procdump_3.3.0_amd64.deb";
}
@@ -105,9 +107,7 @@ private LinuxSystem GetSystem()
return new LinuxSystem(distro, version);
}
- else
- {
- throw new FileNotFoundException("Cannot determine the Linux distribution. The /etc/os-release file does not exist.");
- }
+
+ throw new FileNotFoundException("Cannot determine the Linux distribution. The /etc/os-release file does not exist.");
}
}
\ No newline at end of file
diff --git a/src/c#/GeneralUpdate.Bowl/Strategys/MonitorParameter.cs b/src/c#/GeneralUpdate.Bowl/Strategys/MonitorParameter.cs
index 53d49e61..d53d2f30 100644
--- a/src/c#/GeneralUpdate.Bowl/Strategys/MonitorParameter.cs
+++ b/src/c#/GeneralUpdate.Bowl/Strategys/MonitorParameter.cs
@@ -2,29 +2,29 @@
public class MonitorParameter
{
- public string Target { get; set; }
-
- public string Source { get; set; }
+ public MonitorParameter() { }
- public string ProcessNameOrId { get; set; }
+ public string TargetPath { get; set; }
- public string DumpPath { get; set; }
+ public string FailDirectory { get; set; }
+ public string BackupDirectory { get; set; }
+
+ public string ProcessNameOrId { get; set; }
+
public string DumpFileName { get; set; }
- public string Arguments { get; set; }
+ public string FailFileName { get; set; }
- internal string InnerArguments => $"-e -ma {ProcessNameOrId} {DumpPath}";
+ internal string InnerArguments { get; set; }
- internal string InnerAppName { get; set; }
-
- public bool Verify()
- {
- return string.IsNullOrEmpty(Target) &&
- string.IsNullOrEmpty(Source) &&
- string.IsNullOrEmpty(ProcessNameOrId) &&
- string.IsNullOrEmpty(DumpPath) &&
- string.IsNullOrEmpty(DumpFileName) &&
- string.IsNullOrEmpty(Arguments);
- }
+ internal string InnerApp { get; set; }
+
+ ///
+ /// Upgrade: upgrade mode. This mode is primarily used in conjunction with GeneralUpdate for internal use. Please do not modify it arbitrarily when the default mode is activated.
+ /// Normal: Normal mode,This mode can be used independently to monitor a single program. If the program crashes, it will export the crash information.
+ ///
+ public string WorkModel { get; set; } = "Upgrade";
+
+ public string ExtendedField { get; set; }
}
\ No newline at end of file
diff --git a/src/c#/GeneralUpdate.Bowl/Strategys/WindowStrategy.cs b/src/c#/GeneralUpdate.Bowl/Strategys/WindowStrategy.cs
index da32bcd6..abc23fa1 100644
--- a/src/c#/GeneralUpdate.Bowl/Strategys/WindowStrategy.cs
+++ b/src/c#/GeneralUpdate.Bowl/Strategys/WindowStrategy.cs
@@ -1,23 +1,104 @@
-using System.Runtime.InteropServices;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using GeneralUpdate.Common.FileBasic;
namespace GeneralUpdate.Bowl.Strategys;
public class WindowStrategy : AbstractStrategy
{
+ private const string WorkModel = "Upgrade";
+ private string? _applicationsDirectory;
+ private List _actions = new();
+
public override void Launch()
{
- _parameter.InnerAppName = GetAppName();
+ InitializeActions();
+ _applicationsDirectory = Path.Combine(_parameter.TargetPath, "Applications", "Windows");
+ _parameter.InnerApp = Path.Combine(_applicationsDirectory, GetAppName());
+ var dmpFullName = Path.Combine(_parameter.FailDirectory, _parameter.DumpFileName);
+ _parameter.InnerArguments = $"-e -ma {_parameter.ProcessNameOrId} {dmpFullName}";
base.Launch();
+ ExecuteFinalTreatment();
}
- private string GetAppName()
+ private string GetAppName() => RuntimeInformation.OSArchitecture switch
{
- string appName = RuntimeInformation.OSArchitecture switch
+ Architecture.X86 => "procdump.exe",
+ Architecture.X64 => "procdump64.exe",
+ _ => "procdump64a.exe"
+ };
+
+ private void ExecuteFinalTreatment()
+ {
+ var dumpFile = Path.Combine(_parameter.FailDirectory, _parameter.DumpFileName);
+ if (File.Exists(dumpFile))
+ {
+ foreach (var action in _actions)
+ {
+ action.Invoke();
+ }
+ }
+ }
+
+ private void InitializeActions()
+ {
+ _actions.Add(CreateCrash);
+ _actions.Add(Export);
+ _actions.Add(Restore);
+ _actions.Add(SetEnvironment);
+ }
+
+ ///
+ /// Export the crash output information from procdump.exe and the monitoring parameters of Bowl.
+ ///
+ private void CreateCrash()
+ {
+ var crash = new Crash
{
- Architecture.X86 => "procdump.exe",
- Architecture.X64 => "procdump64.exe",
- _ => "procdump64a.exe"
+ Parameter = _parameter,
+ ProcdumpOutPutLines = OutputList
};
- return appName;
+ var failJsonPath = Path.Combine(_parameter.FailDirectory, _parameter.FailFileName);
+ GeneralFileManager.CreateJson(failJsonPath, crash);
+ }
+
+ ///
+ /// Export operating system information, system logs, and system driver information.
+ ///
+ private void Export()
+ {
+ var batPath = Path.Combine(_applicationsDirectory, "export.bat");
+ if(!File.Exists(batPath))
+ throw new FileNotFoundException("export.bat not found!");
+
+ Process.Start(batPath, _parameter.FailDirectory);
+ }
+
+ ///
+ /// Within the GeneralUpdate upgrade system, restore the specified backup version files to the current working directory.
+ ///
+ private void Restore()
+ {
+ if (string.Equals(_parameter.WorkModel, WorkModel))
+ GeneralFileManager.Restore(_parameter.BackupDirectory, _parameter.TargetPath);
+ }
+
+ ///
+ /// Write the failed update version number to the local environment variable.
+ ///
+ private void SetEnvironment()
+ {
+ if (!string.Equals(_parameter.WorkModel, WorkModel))
+ return;
+
+ /*
+ * The `UpgradeFail` environment variable is used to mark an exception version number during updates.
+ * If the latest version number obtained via an HTTP request is less than or equal to the exception version number, the update is skipped.
+ * Once this version number is set, it will not be removed, and updates will not proceed until a version greater than the exception version number is obtained through the HTTP request.
+ */
+ Environment.SetEnvironmentVariable("UpgradeFail", _parameter.ExtendedField, EnvironmentVariableTarget.User);
}
}
\ No newline at end of file
diff --git a/src/c#/GeneralUpdate.Client/GeneralUpdate.Client.csproj b/src/c#/GeneralUpdate.Client/GeneralUpdate.Client.csproj
index 94ea81d5..af3ba8f7 100644
--- a/src/c#/GeneralUpdate.Client/GeneralUpdate.Client.csproj
+++ b/src/c#/GeneralUpdate.Client/GeneralUpdate.Client.csproj
@@ -2,12 +2,20 @@
Exe
- net8.0
+ net9.0
enable
enable
+
+
+
+
+
+
+
diff --git a/src/c#/GeneralUpdate.Client/MySample.cs b/src/c#/GeneralUpdate.Client/MySample.cs
deleted file mode 100644
index d602edbc..00000000
--- a/src/c#/GeneralUpdate.Client/MySample.cs
+++ /dev/null
@@ -1,322 +0,0 @@
-using GeneralUpdate.ClientCore;
-using GeneralUpdate.Core.Bootstrap;
-using GeneralUpdate.Core.Domain.Entity;
-using GeneralUpdate.Core.Domain.Enum;
-using GeneralUpdate.Core.Driver;
-using GeneralUpdate.Core.Events.CommonArgs;
-using GeneralUpdate.Core.Events.MultiEventArgs;
-using GeneralUpdate.Core.Strategys.PlatformWindows;
-using GeneralUpdate.Differential;
-using System.Diagnostics;
-using System.Text;
-
-namespace GeneralUpdate.Client
-{
- internal class MySample
- {
- #region 推送功能
-
- private const string baseUrl = @"http://127.0.0.1:5000";
- private const string hubName = "versionhub";
-
- internal MySample()
- {
- //Receive sample code pushed by the server
- //VersionHub.Instance.Subscribe($"{baseUrl}/{hubName}", "TESTNAME", new Action(GetMessage));
- }
-
- //Receive sample code pushed by the server
- private async void GetMessage(string msg)
- {
- var isUpdate = true;
- if (isUpdate) Upgrade();
- }
-
- #endregion 推送功能
-
- #region 常规更新
-
- public async Task Upgrade()
- {
- //Task.Run(async () =>
- //{
- // var url = "http://192.168.50.203";
- // var appName = "GeneralUpdate.Client";
- // var version = "1.0.0.0";
- // var versionFileName = "version.json";
- // ParamsOSS @params = new ParamsOSS(url, appName, version, versionFileName);
- // await GeneralClientOSS.Start(@params);
- //});
-
- //ClientStrategy该更新策略将完成1.自动升级组件自更新 2.启动更新组件 3.配置好ClientParameter无需再像之前的版本写args数组进程通讯了。
- //generalClientBootstrap.Config(baseUrl, "B8A7FADD-386C-46B0-B283-C9F963420C7C").
- var configinfo = GetWindowsConfigInfo();
- var generalClientBootstrap = await new GeneralClientBootstrap()
- //单个或多个更新包下载通知事件
- .AddListenerMultiDownloadProgress(OnMultiDownloadProgressChanged)
- //单个或多个更新包下载速度、剩余下载事件、当前下载版本信息通知事件
- .AddListenerMultiDownloadStatistics(OnMultiDownloadStatistics)
- //单个或多个更新包下载完成
- .AddListenerMultiDownloadCompleted(OnMultiDownloadCompleted)
- //完成所有的下载任务通知
- .AddListenerMultiAllDownloadCompleted(OnMultiAllDownloadCompleted)
- //下载过程出现的异常通知
- .AddListenerMultiDownloadError(OnMultiDownloadError)
- //整个更新过程出现的任何问题都会通过这个事件通知
- .AddListenerException(OnException)
- .Config(configinfo)
- .Option(UpdateOption.DownloadTimeOut, 60)
- .Option(UpdateOption.Encoding, Encoding.Default)
- .Option(UpdateOption.Format, Format.ZIP)
- //开启驱动更新
- //.Option(UpdateOption.Drive, true)
- //开启遗言功能,需要部署GeneralUpdate.SystemService Windows服务。
- .Option(UpdateOption.WillMessage, true)
- .Strategy()
- //注入一个func让用户决定是否跳过本次更新,如果是强制更新则不生效
- //.SetCustomSkipOption(ShowCustomOption)
- //注入一个自定义方法集合,该集合会在更新启动前执行。执行自定义方法列表如果出现任何异常,将通过异常订阅通知。(推荐在更新之前检查当前软件环境)
- //.AddCustomOption(new List>() { () => Check1(), () => Check2() })
- //默认黑名单文件: { "Newtonsoft.Json.dll" } 默认黑名单文件扩展名: { ".patch", ".7z", ".zip", ".rar", ".tar" , ".json" }
- //如果不需要扩展,需要重新传入黑名单集合来覆盖。
- //.SetBlacklist(GetBlackFiles(), GetBlackFormats())
- .LaunchTaskAsync();
- }
-
- private bool Check1() => true;
-
- private bool Check2() => true;
-
- private List GetBlackFiles()
- {
- var blackFiles = new List();
- blackFiles.Add("MainApp");
- return blackFiles;
- }
-
- private List GetBlackFormats()
- {
- var blackFormats = new List();
- blackFormats.Add(".zip");
- return blackFormats;
- }
-
- ///
- /// 获取Windows平台所需的配置参数
- ///
- ///
- private Configinfo GetWindowsConfigInfo()
- {
- //该对象用于主程序客户端与更新组件进程之间交互用的对象
- var config = new Configinfo();
- //本机的客户端程序应用地址
- config.InstallPath = @"D:\packet\source";
- //更新公告网页
- config.UpdateLogUrl = "https://www.baidu.com/";
- //客户端当前版本号
- config.ClientVersion = "1.1.1.1";
- //客户端类型:1.主程序客户端 2.更新组件
- config.AppType = AppType.UpgradeApp;
- //指定应用密钥,用于区分客户端应用
- config.AppSecretKey = "B8A7FADD-386C-46B0-B283-C9F963420C7C";
- //更新组件更新包下载地址
- config.UpdateUrl = $"{baseUrl}/versions/{config.AppType}/{config.ClientVersion}/{config.AppSecretKey}";
- //更新程序exe名称
- config.AppName = "GeneralUpdate.Core";
- //主程序客户端exe名称
- config.MainAppName = "GeneralUpdate.ClientCore";
- //主程序信息
- var mainVersion = "1.1.1.1";
- //主程序客户端更新包下载地址
- config.MainUpdateUrl = $"{baseUrl}/versions/{AppType.ClientApp}/{mainVersion}/{config.AppSecretKey}";
- return config;
- }
-
- ///
- /// 获取Android平台所需要的参数
- ///
- ///
- private Configinfo GetAndroidConfigInfo()
- {
- var config = new Configinfo();
- config.InstallPath = System.Threading.Thread.GetDomain().BaseDirectory;
- //主程序客户端当前版本号
- config.ClientVersion = "1.0.0.0"; //VersionTracking.Default.CurrentVersion.ToString();
- config.AppType = AppType.ClientApp;
- config.AppSecretKey = "41A54379-C7D6-4920-8768-21A3468572E5";
- //主程序客户端exe名称
- config.MainAppName = "GeneralUpdate.ClientCore";
- //主程序信息
- var mainVersion = "1.1.1.1";
- config.MainUpdateUrl = $"{baseUrl}/versions/{AppType.ClientApp}/{mainVersion}/{config.AppSecretKey}";
- return config;
- }
-
- ///
- /// 让用户决定是否跳过本次更新
- ///
- ///
- private async Task ShowCustomOption()
- {
- return await Task.FromResult(true);
- }
-
- private void OnMultiDownloadStatistics(object sender, MultiDownloadStatisticsEventArgs e)
- {
- //e.Remaining 剩余下载时间
- //e.Speed 下载速度
- //e.Version 当前下载的版本信息
- }
-
- private void OnMultiDownloadProgressChanged(object sender, MultiDownloadProgressChangedEventArgs e)
- {
- //e.TotalBytesToReceive 当前更新包需要下载的总大小
- //e.ProgressValue 当前进度值
- //e.ProgressPercentage 当前进度的百分比
- //e.Version 当前下载的版本信息
- //e.Type 当前正在执行的操作 1.ProgressType.Check 检查版本信息中 2.ProgressType.Donwload 正在下载当前版本 3. ProgressType.Updatefile 更新当前版本 4. ProgressType.Done更新完成 5.ProgressType.Fail 更新失败
- //e.BytesReceived 已下载大小
- DispatchMessage($"{e.ProgressPercentage}%");
- //MyProgressBar.ProgressTo(e.ProgressValue, 100, Easing.Default);
- }
-
- private void OnException(object sender, ExceptionEventArgs e)
- {
- //DispatchMessage(e.Exception.Message);
- }
-
- private void OnMultiAllDownloadCompleted(object sender, MultiAllDownloadCompletedEventArgs e)
- {
- //e.FailedVersions; 如果出现下载失败则会把下载错误的版本、错误原因统计到该集合当中。
- DispatchMessage($"Is all download completed {e.IsAllDownloadCompleted}.");
- }
-
- private void OnMultiDownloadCompleted(object sender, MultiDownloadCompletedEventArgs e)
- {
- var info = e.Version as VersionInfo;
- DispatchMessage($"{info.Name} download completed.");
- }
-
- private void OnMultiDownloadError(object sender, MultiDownloadErrorEventArgs e)
- {
- var info = e.Version as VersionInfo;
- DispatchMessage($"{info.Name} error!");
- }
-
- private void DispatchMessage(string message)
- {
- }
-
- #endregion 常规更新
-
- #region 测试二进制更新包整理
-
- public async Task TestDifferentialClean()
- {
- var path1 = "D:\\packet\\source";
- var path2 = "D:\\packet\\target";
- var path3 = "D:\\packet\\patchs";
- await DifferentialCore.Instance.Clean(path1, path2, path3);
- }
-
- public async Task TestDifferentialDirty()
- {
- var path1 = "D:\\packet\\source";
- var path2 = "D:\\packet\\patchs";
- await DifferentialCore.Instance.Dirty(path1, path2);
- }
-
- #endregion 测试二进制更新包整理
-
- #region 测试驱动功能
-
- public void TestDrive()
- {
- var path1 = "D:\\packet\\source";
- var path2 = "D:\\packet\\target";
-
- var drivers = GetAllDriverDirectories(path1);
-
- var information = new DriverInformation.Builder()
- .SetInstallDirectory(path1)
- .SetOutPutDirectory(path2)
- .SetDriverNames(drivers)
- .Build();
-
- var processor = new DriverProcessor();
- processor.AddCommand(new BackupDriverCommand(information));
- processor.AddCommand(new DeleteDriverCommand(information));
- processor.AddCommand(new InstallDriverCommand(information));
- processor.ProcessCommands();
- }
-
- ///
- /// Identifies all folders containing driver files in the specified directory and returns the directory collection.
- ///
- ///
- ///
- private List GetAllDriverDirectories(string path)
- {
- var driverDirectories = new HashSet();
- try
- {
- foreach (string filePath in Directory.GetFiles(path))
- {
- if (IsDriverFile(filePath))
- driverDirectories.Add(filePath);
- }
-
- foreach (string directory in Directory.GetDirectories(path))
- {
- driverDirectories.UnionWith(GetAllDriverDirectories(directory));
- }
- }
- catch (UnauthorizedAccessException)
- {
- Trace.WriteLine("No access directory:" + path);
- }
- catch (PathTooLongException)
- {
- Trace.WriteLine("Path overlength:" + path);
- }
-
- return new List(driverDirectories);
- }
-
- ///
- /// Match the driver installation boot file.
- ///
- ///
- ///
- private bool IsDriverFile(string filePath) =>
- string.Equals(Path.GetExtension(filePath), ".inf", StringComparison.OrdinalIgnoreCase);
-
- #endregion 测试驱动功能
-
- #region 文件管理测试
-
- public void TestFileProvider()
- {
- var sourcePath = "D:\\packet\\source";
- var targetPath = "D:\\packet\\target";
- var resultPath = "D:\\packet\\patchs";
-
- //FileProvider fileProvider = new FileProvider();
- //var list = fileProvider.ExecuteOperation(sourcePath, targetPath,new List(), new List());
- //foreach (var item in list) {
- // Console.WriteLine(item);
- //}
- //Console.WriteLine("total" + list.Count());
- //Console.WriteLine("--------------------------------------");
- //FileProvider fileProvider1 = new FileProvider();
- //var list1 = fileProvider1.ExecuteOperation(targetPath, sourcePath, new List(), new List());
- //foreach (var item in list1)
- //{
- // Console.WriteLine(item);
- //}
- //Console.WriteLine("total" + list1.Count());
- }
-
- #endregion 文件管理测试
- }
-}
\ No newline at end of file
diff --git a/src/c#/GeneralUpdate.Client/Program.cs b/src/c#/GeneralUpdate.Client/Program.cs
index 1b9dd51c..5bb23a66 100644
--- a/src/c#/GeneralUpdate.Client/Program.cs
+++ b/src/c#/GeneralUpdate.Client/Program.cs
@@ -1,28 +1,124 @@
-namespace GeneralUpdate.Client
+using System.Diagnostics;
+using System.Text;
+using GeneralUpdate.ClientCore;
+using GeneralUpdate.ClientCore.Hubs;
+using GeneralUpdate.Common.Download;
+using GeneralUpdate.Common.Internal;
+using GeneralUpdate.Common.Internal.Bootstrap;
+using GeneralUpdate.Common.Shared.Object;
+
+namespace GeneralUpdate.Client
{
internal class Program
{
private static void Main(string[] args)
{
- MySample sample = new MySample();
- sample.TestFileProvider();
- //Task.Run(async() =>
- //{
- // //415eed05eb310f480d1e4d15516fa00e484ddb9f416908b217f17b782ded2030
- // //var zip1 = @"D:\github_project\WpfClient\WebApi\UpdateFiles\WpfClient_1_24.1.5.1218.zip";
- // //94bd3d806d39cd1b8813298ec0637c7f377658e766845a06cc50917306cb4ad9
- // //var zip2 = @"D:\github_project\WpfClient\WebApi\UpdateFiles\WpfClient_1_24.1.5.1224.zip";
-
- // //var hashAlgorithm = new Sha256HashAlgorithm();
- // //var hashSha256 = hashAlgorithm.ComputeHash(zip1);
- // //var hashSha2561 = hashAlgorithm.ComputeHash(zip2);
-
- // MySample sample = new MySample();
- // //await sample.TestDifferentialClean();
- // //await sample.TestDifferentialDirty();
- // await sample.Upgrade();
- //});
+ /*Task.Run(async () =>
+ {
+ var source = @"D:\packet\app";
+ var target = @"D:\packet\release";
+ var patch = @"D:\packet\patch";
+
+ await DifferentialCore.Instance?.Clean(source, target, patch);
+ await DifferentialCore.Instance?.Dirty(source, patch);
+ });*/
+
+ /*Task.Run(() =>
+ {
+ //Console.WriteLine("主程序启动辣!!!!");
+ //await Task.Delay(3000);
+
+ var configinfo = new Configinfo();
+ //configinfo.UpdateLogUrl = "https://www.baidu.com";
+ configinfo.ReportUrl = "http://127.0.0.1:5008/Upgrade/Report";
+ configinfo.UpdateUrl = "http://127.0.0.1:5008/Upgrade/Verification";
+
+ configinfo.AppName = "GeneralUpdate.Upgrad.exe";
+ configinfo.MainAppName = "GeneralUpdate.Client.exe";
+ configinfo.InstallPath = Thread.GetDomain().BaseDirectory;
+ configinfo.Bowl = "Generalupdate.CatBowl.exe";
+
+ //当前客户端的版本号
+ configinfo.ClientVersion = "1.0.0.0";
+ //当前升级端的版本号
+ configinfo.UpgradeClientVersion = "1.0.0.0";
+
+ //平台
+ configinfo.Platform = 1;
+ //产品id
+ configinfo.ProductId = "a77c9df5-45f8-4ee9-b3ad-b9431ce0b51c";
+ //应用密钥
+ configinfo.AppSecretKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ _ = new GeneralClientBootstrap()//单个或多个更新包下载通知事件
+ .AddListenerMultiDownloadProgress(OnMultiDownloadProgressChanged)
+ //单个或多个更新包下载速度、剩余下载事件、当前下载版本信息通知事件
+ .AddListenerMultiDownloadStatistics(OnMultiDownloadStatistics)
+ //单个或多个更新包下载完成
+ .AddListenerMultiDownloadCompleted(OnMultiDownloadCompleted)
+ //完成所有的下载任务通知
+ .AddListenerMultiAllDownloadCompleted(OnMultiAllDownloadCompleted)
+ //下载过程出现的异常通知
+ .AddListenerMultiDownloadError(OnMultiDownloadError)
+ //整个更新过程出现的任何问题都会通过这个事件通知
+ .AddListenerException(OnException)
+ .SetConfig(configinfo)
+ .Option(UpdateOption.DownloadTimeOut, 60)
+ .Option(UpdateOption.Encoding, Encoding.UTF8)
+ .Option(UpdateOption.Format, Format.ZIP)
+ .LaunchAsync();
+ });*/
+
+ /*var paramsOSS = new GlobalConfigInfoOSS();
+ paramsOSS.Url = "http://192.168.50.203/versions.json";
+ paramsOSS.CurrentVersion = "1.0.0.0";
+ paramsOSS.VersionFileName = "versions.json";
+ paramsOSS.AppName = "GeneralUpdate.Client.exe";
+ paramsOSS.Encoding = Encoding.UTF8.WebName;
+ GeneralClientOSS.Start(paramsOSS);*/
+
+
+ /*IUpgradeHubService hub = new UpgradeHubService("http://localhost:5008/UpgradeHub", null, "GeneralUpdate");
+ hub.AddListenerReceive(Receive);
+ hub.StartAsync().Wait();*/
+
Console.Read();
}
+
+ private static void Receive(string arg1, string arg2)
+ {
+ throw new NotImplementedException();
+ }
+
+
+ private static void OnMultiDownloadError(object arg1, MultiDownloadErrorEventArgs arg2)
+ {
+ Debug.WriteLine(arg2.Exception);
+ }
+
+ private static void OnMultiAllDownloadCompleted(object arg1, MultiAllDownloadCompletedEventArgs arg2)
+ {
+ Debug.WriteLine(arg2.IsAllDownloadCompleted);
+ }
+
+ private static void OnMultiDownloadCompleted(object arg1, MultiDownloadCompletedEventArgs arg2)
+ {
+ var v = arg2.Version;
+ }
+
+ private static void OnMultiDownloadStatistics(object arg1, MultiDownloadStatisticsEventArgs arg2)
+ {
+ Debug.WriteLine(arg2.Speed);
+ }
+
+ private static void OnMultiDownloadProgressChanged(object arg1, MultiDownloadProgressChangedEventArgs arg2)
+ {
+ Debug.WriteLine(arg2.ProgressValue);
+ }
+
+ private static void OnException(object arg1, ExceptionEventArgs arg2)
+ {
+ Debug.WriteLine(arg2.Exception);
+ }
}
}
\ No newline at end of file
diff --git a/src/c#/GeneralUpdate.ClientCore/Bootstrap/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Bootstrap/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/CustomAwaiter/.gitkeep b/src/c#/GeneralUpdate.ClientCore/CustomAwaiter/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Differential/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Differential/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Differential/Binary/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Differential/Binary/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Differential/ContentProvider/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Differential/ContentProvider/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Differential/GStream/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Differential/GStream/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Domain/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Domain/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Domain/DTO/Assembler/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Domain/DTO/Assembler/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Domain/Entity/Assembler/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Domain/Entity/Assembler/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Domain/Enum/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Domain/Enum/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Domain/PO/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Domain/PO/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Domain/PO/Assembler/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Domain/PO/Assembler/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Domain/Service/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Domain/Service/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Domain/VO/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Domain/VO/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Download/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Download/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Driver/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Driver/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Events/CommonArgs/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Events/CommonArgs/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Events/MultiEventArgs/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Events/MultiEventArgs/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Exceptions/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Exceptions/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Exceptions/CustomArgs/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Exceptions/CustomArgs/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/Exceptions/CustomException/.gitkeep b/src/c#/GeneralUpdate.ClientCore/Exceptions/CustomException/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/c#/GeneralUpdate.ClientCore/GeneralClientBootstrap.cs b/src/c#/GeneralUpdate.ClientCore/GeneralClientBootstrap.cs
index 11bded52..804fd6e9 100644
--- a/src/c#/GeneralUpdate.ClientCore/GeneralClientBootstrap.cs
+++ b/src/c#/GeneralUpdate.ClientCore/GeneralClientBootstrap.cs
@@ -1,271 +1,381 @@
-using GeneralUpdate.Core.Bootstrap;
-using GeneralUpdate.Core.Domain.DTO.Assembler;
-using GeneralUpdate.Core.Domain.Entity;
-using GeneralUpdate.Core.Domain.Entity.Assembler;
-using GeneralUpdate.Core.Domain.Enum;
-using GeneralUpdate.Core.Domain.Service;
-using GeneralUpdate.Core.Exceptions.CustomArgs;
-using GeneralUpdate.Core.Exceptions.CustomException;
-using GeneralUpdate.Core.Strategys;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
-using System.Reflection;
-using System.Security;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Text.Json;
using System.Threading.Tasks;
+using GeneralUpdate.ClientCore.Strategys;
+using GeneralUpdate.Common.AOT.JsonContext;
+using GeneralUpdate.Common.FileBasic;
+using GeneralUpdate.Common.Download;
+using GeneralUpdate.Common.Internal;
+using GeneralUpdate.Common.Internal.Bootstrap;
+using GeneralUpdate.Common.Internal.Event;
+using GeneralUpdate.Common.Internal.Strategy;
+using GeneralUpdate.Common.Shared.Object;
+using GeneralUpdate.Common.Shared.Service;
-namespace GeneralUpdate.ClientCore
+namespace GeneralUpdate.ClientCore;
+
+///
+/// This component is used only for client application bootstrapping classes.
+///
+public class GeneralClientBootstrap : AbstractBootstrap
{
///
- /// This component is used only for client application bootstrapping classes.
+ /// All update actions of the core object for automatic upgrades will be related to the packet object.
///
- public class GeneralClientBootstrap : AbstractBootstrap
- {
- private Func _customSkipOption;
- private Func> _customSkipTaskOption;
+ private GlobalConfigInfo? _configinfo;
+ private IStrategy? _strategy;
+ private Func? _customSkipOption;
+ private readonly List> _customOptions = new();
+ private const string DirectoryName = "app-";
+ private readonly List _notBackupDirectory = ["fail", DirectoryName];
+
+ #region Public Methods
- private List> _customOptions;
- private List>> _customTaskOptions;
+ ///
+ /// Main function for booting the update startup.
+ ///
+ ///
+ public override async Task LaunchAsync()
+ {
+ ExecuteCustomOptions();
+ ClearEnvironmentVariable();
+ await ExecuteWorkflowAsync();
+ return this;
+ }
- public GeneralClientBootstrap() : base()
+ ///
+ /// Configure server address (Recommended Windows,Linux,Mac).
+ ///
+ /// Remote server address.
+ /// The updater name does not need to contain an extension.
+ ///
+ /// Parameter initialization is abnormal.
+ public GeneralClientBootstrap SetConfig(Configinfo configInfo)
+ {
+ Debug.Assert(configInfo != null, "configInfo should not be null");
+ configInfo?.Validate();
+ _configinfo = new GlobalConfigInfo
{
- _customOptions = new List>();
- _customTaskOptions = new List>>();
- }
+ AppName = configInfo.AppName,
+ MainAppName = configInfo.MainAppName,
+ ClientVersion = configInfo.ClientVersion,
+ InstallPath = configInfo.InstallPath,
+ UpdateLogUrl = configInfo.UpdateLogUrl,
+ UpdateUrl = configInfo.UpdateUrl,
+ ReportUrl = configInfo.ReportUrl,
+ AppSecretKey = configInfo.AppSecretKey,
+ BlackFormats = configInfo.BlackFormats,
+ BlackFiles = configInfo.BlackFiles,
+ Platform = configInfo.Platform,
+ ProductId = configInfo.ProductId,
+ UpgradeClientVersion = configInfo.UpgradeClientVersion,
+ Bowl = configInfo.Bowl
+ };
+ return this;
+ }
- #region Public Methods
+ ///
+ /// Let the user decide whether to update in the state of non-mandatory update.
+ ///
+ ///
+ /// Custom function ,Custom actions to let users decide whether to update. true update false do not
+ /// update .
+ ///
+ ///
+ public GeneralClientBootstrap SetCustomSkipOption(Func func)
+ {
+ Debug.Assert(func != null);
+ _customSkipOption = func;
+ return this;
+ }
- ///
- /// Start the update.
- ///
- ///
- public override GeneralClientBootstrap LaunchAsync()
- {
- Task.Run(() => BaseLaunch());
- return this;
- }
+ ///
+ /// Add an asynchronous custom operation.
+ /// In theory, any custom operation can be done. It is recommended to register the environment check method to ensure
+ /// that there are normal dependencies and environments after the update is completed.
+ ///
+ ///
+ ///
+ ///
+ public GeneralClientBootstrap AddCustomOption(List> funcs)
+ {
+ Debug.Assert(funcs != null && funcs.Any());
+ _customOptions.AddRange(funcs);
+ return this;
+ }
- ///
- /// Start the update.
- ///
- ///
- public Task LaunchTaskAsync() => BaseLaunch();
+ public GeneralClientBootstrap AddListenerMultiAllDownloadCompleted(
+ Action