├── .gitattributes ├── .github └── workflows │ └── dotnet-ci.yaml ├── .gitignore ├── LICENSE ├── NuGet.Config ├── README.md ├── README_ZHCN.md ├── git_push.bat ├── imgs ├── GeneralUpdate.ico ├── GeneralUpdate.png ├── GeneralUpdate128.png ├── GeneralUpdate_h.png ├── GeneralUpdate_h2.png ├── WPFPage_16x.png ├── Windows.png ├── bowl.jpeg ├── contact.png ├── dot-net-plain-wordmark.png ├── gitcode.jpg ├── gitee.png ├── github.png ├── linux.png ├── purple-border-gradient-icon.png ├── toolkit.png ├── ubuntu.png ├── ui.png ├── winui.png ├── 统信UOS.png ├── 麒麟.png └── 龙芯.png └── src └── c# ├── GeneralUpdate.Bowl ├── Applications │ ├── Linux │ │ ├── install.sh │ │ ├── procdump-3.3.0-0.cm2.x86_64.rpm │ │ ├── procdump-3.3.0-0.el8.x86_64.rpm │ │ └── procdump_3.3.0_amd64.deb │ └── Windows │ │ ├── export.bat │ │ ├── procdump.exe │ │ ├── procdump64.exe │ │ └── procdump64a.exe ├── Bowl.cs ├── Common │ └── git.keep ├── GeneralUpdate.Bowl.csproj ├── Internal │ ├── Crash.cs │ ├── CrashJsonContext.cs │ └── LinuxSystem.cs ├── Strategys │ ├── AbstractStrategy.cs │ ├── IStrategy.cs │ ├── LinuxStrategy.cs │ ├── MonitorParameter.cs │ └── WindowStrategy.cs └── bowl.jpeg ├── GeneralUpdate.Client ├── GeneralUpdate.Client.csproj └── Program.cs ├── GeneralUpdate.ClientCore ├── Common │ └── git.keep ├── GeneralClientBootstrap.cs ├── GeneralClientOSS.cs ├── GeneralUpdate.ClientCore.csproj ├── GeneralUpdate.ico ├── GeneralUpdate.png ├── Hubs │ ├── IUpgradeHubService.cs │ ├── RandomRetryPolicy.cs │ └── UpgradeHubService.cs ├── Pipeline │ ├── CompressMiddleware.cs │ ├── HashMiddleware.cs │ └── PatchMiddleware.cs ├── Properties │ └── launchSettings.json └── Strategys │ ├── LinuxStrategy.cs │ └── WindowsStrategy.cs ├── GeneralUpdate.Common ├── Compress │ ├── CompressProvider.cs │ ├── ICompressionStrategy.cs │ └── ZipCompressionStrategy.cs ├── Download │ ├── DownloadManager.cs │ ├── DownloadTask.cs │ └── MultiEventArgs │ │ ├── MutiAllDownloadCompletedEventArgs.cs │ │ ├── MutiDownloadCompletedEventArgs.cs │ │ ├── MutiDownloadErrorEventArgs.cs │ │ └── MutiDownloadStatisticsEventArgs.cs ├── FileBasic │ ├── BlackListManager.cs │ ├── ComparisonResult.cs │ ├── FileNode.cs │ ├── FileTree.cs │ └── StorageManager.cs ├── GeneralUpdate.Common.csproj ├── GeneralUpdate128.png ├── HashAlgorithms │ ├── HashAlgorithmBase.cs │ ├── Md5HashAlgorithm.cs │ ├── Sha1HashAlgorithm.cs │ └── Sha256HashAlgorithm.cs ├── Internal │ ├── Bootstrap │ │ ├── AbstractBootstrap.cs │ │ ├── Environments.cs │ │ ├── UpdateOption.cs │ │ └── UpdateOptionValue.cs │ ├── Event │ │ ├── EventManager.cs │ │ └── IEventManager.cs │ ├── Exception │ │ └── ExceptionEventArgs.cs │ ├── JsonContext │ │ ├── FileNodesJsonContext.cs │ │ ├── GlobalConfigInfoOSSJsonContext.cs │ │ ├── HttpParameterJsonContext.cs │ │ ├── PacketJsonContext.cs │ │ ├── ProcessInfoJsonContext.cs │ │ ├── ReportRespJsonContext.cs │ │ ├── VersionOSSJsonContext.cs │ │ └── VersionRespJsonContext.cs │ ├── Pipeline │ │ ├── IMiddleware.cs │ │ ├── PipelineBuilder.cs │ │ └── PipelineContext.cs │ └── Strategy │ │ ├── AbstractStrategy.cs │ │ └── IStrategy.cs └── Shared │ ├── Object │ ├── Configinfo.cs │ ├── DTO │ │ ├── BaseResponseDTO.cs │ │ └── VersionRespDTO.cs │ ├── Enum │ │ ├── AppType.cs │ │ ├── Format.cs │ │ ├── PlatformType.cs │ │ └── ReportType.cs │ ├── GlobalConfigInfo.cs │ ├── GlobalConfigInfoOSS.cs │ ├── Packet.cs │ ├── ProcessInfo.cs │ ├── VersionInfo.cs │ └── VersionOSS.cs │ └── Service │ └── VersionService.cs ├── GeneralUpdate.Core ├── Common │ └── git.keep ├── Driver │ ├── BackupDriverCommand.cs │ ├── CommandExecutor.cs │ ├── DeleteDriverCommand.cs │ ├── DriverCommand.cs │ ├── DriverInfo.cs │ ├── DriverInformation.cs │ ├── DriverProcessor.cs │ ├── InstallDriverCommand.cs │ └── RestoreDriverCommand.cs ├── GeneralUpdate.Core.csproj ├── GeneralUpdate.ico ├── GeneralUpdate.png ├── GeneralUpdateBootstrap.cs ├── GeneralUpdateOSS.cs ├── Pipeline │ ├── CompressMiddleware.cs │ ├── DriverMiddleware.cs │ ├── HashMiddleware.cs │ └── PatchMiddleware.cs ├── Properties │ ├── AssemblyInfo.cs │ └── launchSettings.json └── Strategys │ ├── LinuxStrategy.cs │ ├── OSSStrategy.cs │ └── WindowsStrategy.cs ├── GeneralUpdate.Differential ├── Binary │ ├── BZip2Constants.cs │ ├── BZip2InputStream.cs │ ├── BZip2OutputStream.cs │ ├── BinaryHandler.cs │ ├── IChecksum.cs │ └── StrangeCRC.cs ├── DifferentialCore.cs ├── GeneralUpdate.Differential.csproj ├── GeneralUpdate.ico ├── GeneralUpdate.png └── Properties │ └── launchSettings.json ├── GeneralUpdate.Upgrad ├── GeneralUpdate.Upgrad.csproj └── Program.cs ├── GeneralUpdate.sln └── Generalupdate.CatBowl ├── Generalupdate.CatBowl.csproj └── Program.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/workflows/dotnet-ci.yaml: -------------------------------------------------------------------------------- 1 | name: dotnet-ci 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: windows-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v3 11 | - name: Setup .NET SDK 12 | uses: actions/setup-dotnet@v2 13 | with: 14 | dotnet-version: '9.0.x' 15 | - name: Restore dependencies 16 | run: dotnet restore ./src/c#/GeneralUpdate.sln 17 | - name: build 18 | run: dotnet build ./src/c#/GeneralUpdate.sln -c Release -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | [Dd]ebug/ 11 | [Dd]ebugPublic/ 12 | [Rr]elease/ 13 | [Rr]eleases/ 14 | x64/ 15 | x86/ 16 | build/ 17 | bld/ 18 | [Bb]in/ 19 | [Oo]bj/ 20 | *.vs/ 21 | 22 | # Roslyn cache directories 23 | *.ide/ 24 | 25 | # MSTest test Results 26 | [Tt]est[Rr]esult*/ 27 | [Bb]uild[Ll]og.* 28 | 29 | #NUNIT 30 | *.VisualState.xml 31 | TestResult.xml 32 | 33 | # Build Results of an ATL Project 34 | [Dd]ebugPS/ 35 | [Rr]eleasePS/ 36 | dlldata.c 37 | 38 | *_i.c 39 | *_p.c 40 | *_i.h 41 | *.ilk 42 | *.meta 43 | *.obj 44 | *.pch 45 | *.pdb 46 | *.pgc 47 | *.pgd 48 | *.rsp 49 | *.sbr 50 | *.tlb 51 | *.tli 52 | *.tlh 53 | *.tmp 54 | *.tmp_proj 55 | *.log 56 | *.vspscc 57 | *.vssscc 58 | .builds 59 | *.pidb 60 | *.svclog 61 | *.scc 62 | 63 | # Chutzpah Test files 64 | _Chutzpah* 65 | 66 | # Visual C++ cache files 67 | ipch/ 68 | *.aps 69 | *.ncb 70 | *.opensdf 71 | *.sdf 72 | *.cachefile 73 | 74 | # Visual Studio profiler 75 | *.psess 76 | *.vsp 77 | *.vspx 78 | 79 | # TFS 2012 Local Workspace 80 | $tf/ 81 | 82 | # Guidance Automation Toolkit 83 | *.gpState 84 | 85 | # ReSharper is a .NET coding add-in 86 | _ReSharper*/ 87 | *.[Rr]e[Ss]harper 88 | *.DotSettings.user 89 | 90 | # JustCode is a .NET coding addin-in 91 | .JustCode 92 | 93 | # TeamCity is a build add-in 94 | _TeamCity* 95 | 96 | # DotCover is a Code Coverage Tool 97 | *.dotCover 98 | 99 | # NCrunch 100 | _NCrunch_* 101 | .*crunch*.local.xml 102 | 103 | # MightyMoose 104 | *.mm.* 105 | AutoTest.Net/ 106 | 107 | # Web workbench (sass) 108 | .sass-cache/ 109 | 110 | # Installshield output folder 111 | [Ee]xpress/ 112 | 113 | # DocProject is a documentation generator add-in 114 | DocProject/buildhelp/ 115 | DocProject/Help/*.HxT 116 | DocProject/Help/*.HxC 117 | DocProject/Help/*.hhc 118 | DocProject/Help/*.hhk 119 | DocProject/Help/*.hhp 120 | DocProject/Help/Html2 121 | DocProject/Help/html 122 | 123 | # Click-Once directory 124 | publish/ 125 | 126 | # Publish Web Output 127 | *.[Pp]ublish.xml 128 | *.azurePubxml 129 | # TODO: Comment the next line if you want to checkin your web deploy settings 130 | # but database connection strings (with potential passwords) will be unencrypted 131 | *.pubxml 132 | *.publishproj 133 | 134 | # NuGet Packages 135 | *.nupkg 136 | # The packages folder can be ignored because of Package Restore 137 | **/packages/* 138 | # except build/, which is used as an MSBuild target. 139 | !**/packages/build/ 140 | # If using the old MSBuild-Integrated Package Restore, uncomment this: 141 | #!**/packages/repositories.config 142 | 143 | # Windows Azure Build Output 144 | csx/ 145 | *.build.csdef 146 | 147 | # Windows Store app package directory 148 | AppPackages/ 149 | 150 | # Others 151 | sql/ 152 | *.Cache 153 | ClientBin/ 154 | [Ss]tyle[Cc]op.* 155 | ~$* 156 | *~ 157 | *.dbmdl 158 | *.dbproj.schemaview 159 | *.pfx 160 | *.publishsettings 161 | node_modules/ 162 | 163 | # RIA/Silverlight projects 164 | Generated_Code/ 165 | 166 | # Backup & report files from converting an old project file 167 | # to a newer Visual Studio version. Backup files are not needed, 168 | # because we have git ;-) 169 | _UpgradeReport_Files/ 170 | Backup*/ 171 | UpgradeLog*.XML 172 | UpgradeLog*.htm 173 | 174 | # SQL Server files 175 | *.mdf 176 | *.ldf 177 | 178 | # Business Intelligence projects 179 | *.rdl.data 180 | *.bim.layout 181 | *.bim_*.settings 182 | 183 | # Microsoft Fakes 184 | FakesAssemblies/ 185 | 186 | # SVN Repo 187 | .svn/ 188 | *.vsidx 189 | *.v2 190 | *.lock 191 | *.txt 192 | *.v3 193 | *.v5 194 | src/c\#/.vs 195 | src/c\#/.idea 196 | src/c\#/global.json 197 | -------------------------------------------------------------------------------- /NuGet.Config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /git_push.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | git remote -v 4 | 5 | set /p commitmessage=Git commit message: 6 | 7 | git add . 8 | 9 | git commit -m "%commitMessage%" 10 | 11 | echo Pushing to default remote repository... 12 | git push 13 | if %errorlevel% neq 0 ( 14 | echo Failed to push to default remote repository. 15 | pause 16 | exit /b %errorlevel% 17 | ) 18 | 19 | echo Pushing to upstream remote on 'master' branch... 20 | git push upstream master 21 | if %errorlevel% neq 0 ( 22 | echo Failed to push to upstream remote on 'main' branch. 23 | pause 24 | exit /b %errorlevel% 25 | ) 26 | 27 | echo Pushing to 'upstream_gitcode' remote on 'master' branch... 28 | git push upstream_gitcode master 29 | if %errorlevel% neq 0 ( 30 | echo Failed to push to 'upstream_gitcode' remote on 'main' branch. 31 | pause 32 | exit /b %errorlevel% 33 | ) 34 | 35 | echo All pushes completed successfully. 36 | pause -------------------------------------------------------------------------------- /imgs/GeneralUpdate.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/GeneralUpdate.ico -------------------------------------------------------------------------------- /imgs/GeneralUpdate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/GeneralUpdate.png -------------------------------------------------------------------------------- /imgs/GeneralUpdate128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/GeneralUpdate128.png -------------------------------------------------------------------------------- /imgs/GeneralUpdate_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/GeneralUpdate_h.png -------------------------------------------------------------------------------- /imgs/GeneralUpdate_h2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/GeneralUpdate_h2.png -------------------------------------------------------------------------------- /imgs/WPFPage_16x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/WPFPage_16x.png -------------------------------------------------------------------------------- /imgs/Windows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/Windows.png -------------------------------------------------------------------------------- /imgs/bowl.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/bowl.jpeg -------------------------------------------------------------------------------- /imgs/contact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/contact.png -------------------------------------------------------------------------------- /imgs/dot-net-plain-wordmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/dot-net-plain-wordmark.png -------------------------------------------------------------------------------- /imgs/gitcode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/gitcode.jpg -------------------------------------------------------------------------------- /imgs/gitee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/gitee.png -------------------------------------------------------------------------------- /imgs/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/github.png -------------------------------------------------------------------------------- /imgs/linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/linux.png -------------------------------------------------------------------------------- /imgs/purple-border-gradient-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/purple-border-gradient-icon.png -------------------------------------------------------------------------------- /imgs/toolkit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/toolkit.png -------------------------------------------------------------------------------- /imgs/ubuntu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/ubuntu.png -------------------------------------------------------------------------------- /imgs/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/ui.png -------------------------------------------------------------------------------- /imgs/winui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/winui.png -------------------------------------------------------------------------------- /imgs/统信UOS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/统信UOS.png -------------------------------------------------------------------------------- /imgs/麒麟.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/麒麟.png -------------------------------------------------------------------------------- /imgs/龙芯.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/imgs/龙芯.png -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/Applications/Linux/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 获取脚本的实际名称 4 | SCRIPT_NAME=$(basename "\$0") 5 | 6 | # 检查是否提供了参数 7 | if [ "$#" -ne 1 ]; then 8 | echo "Usage: $SCRIPT_NAME " 9 | exit 1 10 | fi 11 | 12 | PACKAGE_FILE=\$1 13 | 14 | # 检查文件类型并安装 15 | if [[ "$PACKAGE_FILE" == *.rpm ]]; then 16 | if command -v rpm &> /dev/null; then 17 | sudo rpm -ivh "$PACKAGE_FILE" || { echo "Failed to install $PACKAGE_FILE using rpm"; exit 1; } 18 | elif command -v dnf &> /dev/null; then 19 | sudo dnf install -y "$PACKAGE_FILE" || { echo "Failed to install $PACKAGE_FILE using dnf"; exit 1; } 20 | elif command -v yum &> /dev/null; then 21 | sudo yum install -y "$PACKAGE_FILE" || { echo "Failed to install $PACKAGE_FILE using yum"; exit 1; } 22 | else 23 | echo "RPM package manager not found." 24 | exit 1 25 | fi 26 | elif [[ "$PACKAGE_FILE" == *.deb ]]; then 27 | if command -v dpkg &> /dev/null; then 28 | sudo dpkg -i "$PACKAGE_FILE" || { echo "Failed to install $PACKAGE_FILE using dpkg"; exit 1; } 29 | sudo apt-get install -f -y || { echo "Failed to fix dependencies"; exit 1; } 30 | else 31 | echo "DEB package manager not found." 32 | exit 1 33 | fi 34 | else 35 | echo "Unsupported package format." 36 | exit 1 37 | fi 38 | 39 | echo "Installation of $PACKAGE_FILE completed." -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/Applications/Linux/procdump-3.3.0-0.cm2.x86_64.rpm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/src/c#/GeneralUpdate.Bowl/Applications/Linux/procdump-3.3.0-0.cm2.x86_64.rpm -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/Applications/Linux/procdump-3.3.0-0.el8.x86_64.rpm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/src/c#/GeneralUpdate.Bowl/Applications/Linux/procdump-3.3.0-0.el8.x86_64.rpm -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/Applications/Linux/procdump_3.3.0_amd64.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/src/c#/GeneralUpdate.Bowl/Applications/Linux/procdump_3.3.0_amd64.deb -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/Applications/Windows/export.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal 3 | 4 | if "%~1"=="" ( 5 | echo Please provide the export path as the first parameter. 6 | exit /b 1 7 | ) 8 | 9 | set exportDir=%~1 10 | 11 | if not exist "%exportDir%" ( 12 | mkdir "%exportDir%" 13 | ) 14 | 15 | set outputFile=%exportDir%\driverInfo.txt 16 | 17 | :: 导出驱动信息 18 | driverquery /v /fo table > "%outputFile%" 19 | echo %outputFile% Export successfully. 20 | 21 | :: 导出系统信息 22 | set systemInfoFile=%exportDir%\systeminfo.txt 23 | systeminfo > "%systemInfoFile%" 24 | echo %systemInfoFile% Export successfully. 25 | 26 | :: 获取当前日期 27 | for /f "tokens=1-4 delims=/- " %%i in ('date /t') do ( 28 | set yyyy=%%i 29 | set mm=%%j 30 | set dd=%%k 31 | ) 32 | 33 | :: 设置日志文件名 34 | set logFile=%exportDir%\systemlog.evtx 35 | 36 | :: 导出系统日志 37 | wevtutil epl System "%logFile%" /q:"*[System[TimeCreated[timediff(@SystemTime) <= 86400000]]]" 38 | echo %logFile% Export successfully. 39 | 40 | endlocal -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/Applications/Windows/procdump.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/src/c#/GeneralUpdate.Bowl/Applications/Windows/procdump.exe -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/Applications/Windows/procdump64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/src/c#/GeneralUpdate.Bowl/Applications/Windows/procdump64.exe -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/Applications/Windows/procdump64a.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/src/c#/GeneralUpdate.Bowl/Applications/Windows/procdump64a.exe -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/Bowl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Runtime.InteropServices; 4 | using System.Text.Json; 5 | using GeneralUpdate.Bowl.Strategys; 6 | using GeneralUpdate.Common.Internal.Bootstrap; 7 | using GeneralUpdate.Common.Internal.JsonContext; 8 | using GeneralUpdate.Common.Shared.Object; 9 | 10 | namespace GeneralUpdate.Bowl; 11 | 12 | /// 13 | /// Surveillance Main Program. 14 | /// 15 | public sealed class Bowl 16 | { 17 | private static IStrategy? _strategy; 18 | 19 | private Bowl() { } 20 | 21 | private static void CreateStrategy() 22 | { 23 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 24 | _strategy = new WindowStrategy(); 25 | 26 | if (_strategy == null) 27 | throw new PlatformNotSupportedException("Unsupported operating system"); 28 | } 29 | 30 | public static void Launch(MonitorParameter? monitorParameter = null) 31 | { 32 | monitorParameter ??= CreateParameter(); 33 | CreateStrategy(); 34 | _strategy?.SetParameter(monitorParameter); 35 | _strategy?.Launch(); 36 | } 37 | 38 | private static MonitorParameter CreateParameter() 39 | { 40 | var json = Environments.GetEnvironmentVariable("ProcessInfo"); 41 | if(string.IsNullOrWhiteSpace(json)) 42 | throw new ArgumentNullException("ProcessInfo environment variable not set !"); 43 | 44 | var processInfo = JsonSerializer.Deserialize(json, ProcessInfoJsonContext.Default.ProcessInfo); 45 | if(processInfo == null) 46 | throw new ArgumentNullException("ProcessInfo json deserialize fail!"); 47 | 48 | return new MonitorParameter 49 | { 50 | ProcessNameOrId = processInfo.AppName, 51 | DumpFileName = $"{processInfo.LastVersion}_fail.dmp", 52 | FailFileName = $"{processInfo.LastVersion}_fail.json", 53 | TargetPath = processInfo.InstallPath, 54 | FailDirectory = Path.Combine(processInfo.InstallPath, "fail", processInfo.LastVersion), 55 | BackupDirectory = Path.Combine(processInfo.InstallPath, processInfo.LastVersion), 56 | ExtendedField = processInfo.LastVersion 57 | }; 58 | } 59 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/Common/git.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/src/c#/GeneralUpdate.Bowl/Common/git.keep -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/Internal/Crash.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using GeneralUpdate.Bowl.Strategys; 3 | 4 | namespace GeneralUpdate.Bowl.Internal; 5 | 6 | internal class Crash 7 | { 8 | public MonitorParameter Parameter { get; set; } 9 | 10 | public List ProcdumpOutPutLines { get; set; } 11 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/Internal/CrashJsonContext.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace GeneralUpdate.Bowl.Internal; 4 | 5 | [JsonSerializable(typeof(Crash))] 6 | internal partial class CrashJsonContext : JsonSerializerContext; -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/Internal/LinuxSystem.cs: -------------------------------------------------------------------------------- 1 | namespace GeneralUpdate.Bowl.Internal; 2 | 3 | internal class LinuxSystem 4 | { 5 | internal string Name { get; set; } 6 | 7 | internal string Version { get; set; } 8 | 9 | internal LinuxSystem(string name, string version) 10 | { 11 | Name = name; 12 | Version = version; 13 | } 14 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/Strategys/AbstractStrategy.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using GeneralUpdate.Common.FileBasic; 5 | 6 | namespace GeneralUpdate.Bowl.Strategys; 7 | 8 | internal abstract class AbstractStrategy : IStrategy 9 | { 10 | protected MonitorParameter _parameter; 11 | protected List OutputList = new (); 12 | 13 | public void SetParameter(MonitorParameter parameter) => _parameter = parameter; 14 | 15 | public virtual void Launch() 16 | { 17 | Startup(_parameter.InnerApp, _parameter.InnerArguments); 18 | } 19 | 20 | private void Startup(string appName, string arguments) 21 | { 22 | if (Directory.Exists(_parameter.FailDirectory)) 23 | { 24 | StorageManager.DeleteDirectory(_parameter.FailDirectory); 25 | } 26 | Directory.CreateDirectory(_parameter.FailDirectory); 27 | 28 | var startInfo = new ProcessStartInfo 29 | { 30 | FileName = appName, 31 | Arguments = arguments, 32 | RedirectStandardOutput = true, 33 | RedirectStandardError = true, 34 | UseShellExecute = false, 35 | CreateNoWindow = true 36 | }; 37 | 38 | var process = new Process { StartInfo = startInfo }; 39 | process.OutputDataReceived += OutputHandler; 40 | process.ErrorDataReceived += OutputHandler; 41 | process.Start(); 42 | process.BeginOutputReadLine(); 43 | process.BeginErrorReadLine(); 44 | process.WaitForExit(1000 * 10); 45 | } 46 | 47 | private void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine) 48 | { 49 | var data = outLine.Data; 50 | if (!string.IsNullOrEmpty(data)) 51 | OutputList.Add(data); 52 | } 53 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/Strategys/IStrategy.cs: -------------------------------------------------------------------------------- 1 | using GeneralUpdate.Bowl.Internal; 2 | 3 | namespace GeneralUpdate.Bowl.Strategys; 4 | 5 | internal interface IStrategy 6 | { 7 | void Launch(); 8 | 9 | void SetParameter(MonitorParameter parameter); 10 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/Strategys/LinuxStrategy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using GeneralUpdate.Bowl.Internal; 7 | 8 | namespace GeneralUpdate.Bowl.Strategys; 9 | 10 | internal class LinuxStrategy : AbstractStrategy 11 | { 12 | /*procdump-3.3.0-0.cm2.x86_64.rpm: 13 | 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. 14 | 15 | procdump-3.3.0-0.el8.x86_64.rpm: 16 | Compatible Systems: This RPM package is suitable for Red Hat Enterprise Linux 8 (RHEL 8), CentOS 8, and other RHEL 8-based distributions. 17 | 18 | procdump_3.3.0_amd64.deb: 19 | Compatible Systems: This DEB package is suitable for Debian and its derivatives, such as Ubuntu, for 64-bit systems (amd64 architecture).*/ 20 | 21 | private IReadOnlyList _rocdumpAmd64 = new List { "Ubuntu", "Debian" }; 22 | private IReadOnlyList procdump_el8_x86_64 = new List { "Red Hat", "CentOS", "Fedora" }; 23 | private IReadOnlyList procdump_cm2_x86_64 = new List { "ClearOS" }; 24 | 25 | public override void Launch() 26 | { 27 | Install(); 28 | base.Launch(); 29 | } 30 | 31 | private void Install() 32 | { 33 | string scriptPath = "./install.sh"; 34 | string packageFile = GetPacketName(); 35 | 36 | ProcessStartInfo processStartInfo = new ProcessStartInfo() 37 | { 38 | FileName = "/bin/bash", 39 | Arguments = $"{scriptPath} {packageFile}", 40 | RedirectStandardOutput = true, 41 | RedirectStandardError = true, 42 | UseShellExecute = false, 43 | CreateNoWindow = true 44 | }; 45 | 46 | try 47 | { 48 | using Process process = Process.Start(processStartInfo); 49 | string output = process.StandardOutput.ReadToEnd(); 50 | string error = process.StandardError.ReadToEnd(); 51 | process.WaitForExit(); 52 | 53 | Console.WriteLine("Output:"); 54 | Console.WriteLine(output); 55 | 56 | if (!string.IsNullOrEmpty(error)) 57 | { 58 | Console.WriteLine("Error:"); 59 | Console.WriteLine(error); 60 | } 61 | } 62 | catch (Exception e) 63 | { 64 | Console.WriteLine($"An error occurred: {e.Message}"); 65 | } 66 | } 67 | 68 | private string GetPacketName() 69 | { 70 | var packageFileName = string.Empty; 71 | var system = GetSystem(); 72 | if (_rocdumpAmd64.Contains(system.Name)) 73 | { 74 | packageFileName = $"procdump_3.3.0_amd64.deb"; 75 | } 76 | else if (procdump_el8_x86_64.Contains(system.Name)) 77 | { 78 | packageFileName = $"procdump-3.3.0-0.el8.x86_64.rpm"; 79 | } 80 | else if (procdump_cm2_x86_64.Contains(system.Name)) 81 | { 82 | packageFileName = $"procdump-3.3.0-0.cm2.x86_64.rpm"; 83 | } 84 | 85 | return packageFileName; 86 | } 87 | 88 | private LinuxSystem GetSystem() 89 | { 90 | string osReleaseFile = "/etc/os-release"; 91 | if (File.Exists(osReleaseFile)) 92 | { 93 | var lines = File.ReadAllLines(osReleaseFile); 94 | string distro = string.Empty; 95 | string version = string.Empty; 96 | 97 | foreach (var line in lines) 98 | { 99 | if (line.StartsWith("ID=")) 100 | { 101 | distro = line.Substring(3).Trim('\"'); 102 | } 103 | else if (line.StartsWith("VERSION_ID=")) 104 | { 105 | version = line.Substring(11).Trim('\"'); 106 | } 107 | } 108 | 109 | return new LinuxSystem(distro, version); 110 | } 111 | 112 | throw new FileNotFoundException("Cannot determine the Linux distribution. The /etc/os-release file does not exist."); 113 | } 114 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/Strategys/MonitorParameter.cs: -------------------------------------------------------------------------------- 1 | namespace GeneralUpdate.Bowl.Strategys; 2 | 3 | public class MonitorParameter 4 | { 5 | public MonitorParameter() { } 6 | 7 | public string TargetPath { get; set; } 8 | 9 | public string FailDirectory { get; set; } 10 | 11 | public string BackupDirectory { get; set; } 12 | 13 | public string ProcessNameOrId { get; set; } 14 | 15 | public string DumpFileName { get; set; } 16 | 17 | public string FailFileName { get; set; } 18 | 19 | internal string InnerArguments { get; set; } 20 | 21 | internal string InnerApp { get; set; } 22 | 23 | /// 24 | /// 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. 25 | /// Normal: Normal mode,This mode can be used independently to monitor a single program. If the program crashes, it will export the crash information. 26 | /// 27 | public string WorkModel { get; set; } = "Upgrade"; 28 | 29 | public string ExtendedField { get; set; } 30 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/Strategys/WindowStrategy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Runtime.InteropServices; 6 | using GeneralUpdate.Bowl.Internal; 7 | using GeneralUpdate.Common.FileBasic; 8 | using GeneralUpdate.Common.Internal.Bootstrap; 9 | 10 | namespace GeneralUpdate.Bowl.Strategys; 11 | 12 | internal class WindowStrategy : AbstractStrategy 13 | { 14 | private const string WorkModel = "Upgrade"; 15 | private string? _applicationsDirectory; 16 | private List _actions = new(); 17 | 18 | public override void Launch() 19 | { 20 | InitializeActions(); 21 | _applicationsDirectory = Path.Combine(_parameter.TargetPath, "Applications", "Windows"); 22 | _parameter.InnerApp = Path.Combine(_applicationsDirectory, GetAppName()); 23 | var dmpFullName = Path.Combine(_parameter.FailDirectory, _parameter.DumpFileName); 24 | _parameter.InnerArguments = $"-e -ma {_parameter.ProcessNameOrId} {dmpFullName}"; 25 | //This method is used to launch scripts in applications. 26 | base.Launch(); 27 | ExecuteFinalTreatment(); 28 | } 29 | 30 | private string GetAppName() => RuntimeInformation.OSArchitecture switch 31 | { 32 | Architecture.X86 => "procdump.exe", 33 | Architecture.X64 => "procdump64.exe", 34 | _ => "procdump64a.exe" 35 | }; 36 | 37 | private void ExecuteFinalTreatment() 38 | { 39 | var dumpFile = Path.Combine(_parameter.FailDirectory, _parameter.DumpFileName); 40 | if (File.Exists(dumpFile)) 41 | { 42 | foreach (var action in _actions) 43 | { 44 | action.Invoke(); 45 | } 46 | } 47 | } 48 | 49 | private void InitializeActions() 50 | { 51 | _actions.Add(CreateCrash); 52 | _actions.Add(Export); 53 | _actions.Add(Restore); 54 | _actions.Add(SetEnvironment); 55 | } 56 | 57 | /// 58 | /// Export the crash output information from procdump.exe and the monitoring parameters of Bowl. 59 | /// 60 | private void CreateCrash() 61 | { 62 | var crash = new Crash 63 | { 64 | Parameter = _parameter, 65 | ProcdumpOutPutLines = OutputList 66 | }; 67 | var failJsonPath = Path.Combine(_parameter.FailDirectory, _parameter.FailFileName); 68 | StorageManager.CreateJson(failJsonPath, crash, CrashJsonContext.Default.Crash); 69 | } 70 | 71 | /// 72 | /// Export operating system information, system logs, and system driver information. 73 | /// 74 | private void Export() 75 | { 76 | var batPath = Path.Combine(_applicationsDirectory, "export.bat"); 77 | if(!File.Exists(batPath)) 78 | throw new FileNotFoundException("export.bat not found!"); 79 | 80 | Process.Start(batPath, _parameter.FailDirectory); 81 | } 82 | 83 | /// 84 | /// Within the GeneralUpdate upgrade system, restore the specified backup version files to the current working directory. 85 | /// 86 | private void Restore() 87 | { 88 | if (string.Equals(_parameter.WorkModel, WorkModel)) 89 | StorageManager.Restore(_parameter.BackupDirectory, _parameter.TargetPath); 90 | } 91 | 92 | /// 93 | /// Write the failed update version number to the local environment variable. 94 | /// 95 | private void SetEnvironment() 96 | { 97 | if (!string.Equals(_parameter.WorkModel, WorkModel)) 98 | return; 99 | 100 | /* 101 | * The `UpgradeFail` environment variable is used to mark an exception version number during updates. 102 | * If the latest version number obtained via an HTTP request is less than or equal to the exception version number, the update is skipped. 103 | * 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. 104 | */ 105 | Environments.SetEnvironmentVariable("UpgradeFail", _parameter.ExtendedField); 106 | } 107 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Bowl/bowl.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/src/c#/GeneralUpdate.Bowl/bowl.jpeg -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Client/GeneralUpdate.Client.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | default 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Client/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Text; 3 | using GeneralUpdate.ClientCore; 4 | using GeneralUpdate.ClientCore.Hubs; 5 | using GeneralUpdate.Common.Download; 6 | using GeneralUpdate.Common.Internal; 7 | using GeneralUpdate.Common.Internal.Bootstrap; 8 | using GeneralUpdate.Common.Shared.Object; 9 | using GeneralUpdate.Common.Shared.Object.Enum; 10 | 11 | namespace GeneralUpdate.Client 12 | { 13 | internal class Program 14 | { 15 | static async Task Main(string[] args) 16 | { 17 | try 18 | { 19 | Console.WriteLine($"主程序初始化,{DateTime.Now}!"); 20 | Console.WriteLine("当前运行目录:" + Thread.GetDomain().BaseDirectory); 21 | await Task.Delay(2000); 22 | var configinfo = new Configinfo 23 | { 24 | //configinfo.UpdateLogUrl = "https://www.baidu.com"; 25 | ReportUrl = "http://127.0.0.1:5000/Upgrade/Report", 26 | UpdateUrl = "http://127.0.0.1:5000/Upgrade/Verification", 27 | AppName = "GeneralUpdate.Upgrad.exe", 28 | MainAppName = "GeneralUpdate.Client.exe", 29 | InstallPath = Thread.GetDomain().BaseDirectory, 30 | //configinfo.Bowl = "Generalupdate.CatBowl.exe"; 31 | //当前客户端的版本号 32 | ClientVersion = "1.0.0.0", 33 | //当前升级端的版本号 34 | UpgradeClientVersion = "1.0.0.0", 35 | //产品id 36 | ProductId = "2d974e2a-31e6-4887-9bb1-b4689e98c77a", 37 | //应用密钥 38 | AppSecretKey = "dfeb5833-975e-4afb-88f1-6278ee9aeff6" 39 | }; 40 | _ = await new GeneralClientBootstrap() //单个或多个更新包下载通知事件 41 | //单个或多个更新包下载速度、剩余下载事件、当前下载版本信息通知事件 42 | .AddListenerMultiDownloadStatistics(OnMultiDownloadStatistics) 43 | //单个或多个更新包下载完成 44 | .AddListenerMultiDownloadCompleted(OnMultiDownloadCompleted) 45 | //完成所有的下载任务通知 46 | .AddListenerMultiAllDownloadCompleted(OnMultiAllDownloadCompleted) 47 | //下载过程出现的异常通知 48 | .AddListenerMultiDownloadError(OnMultiDownloadError) 49 | //整个更新过程出现的任何问题都会通过这个事件通知 50 | .AddListenerException(OnException) 51 | .SetConfig(configinfo) 52 | .Option(UpdateOption.DownloadTimeOut, 60) 53 | .Option(UpdateOption.Encoding, Encoding.UTF8) 54 | .LaunchAsync(); 55 | Console.WriteLine($"主程序已启动,{DateTime.Now}!"); 56 | } 57 | catch (Exception e) 58 | { 59 | Console.WriteLine(e.Message + "\n" + e.StackTrace); 60 | } 61 | 62 | /*var paramsOSS = new GlobalConfigInfoOSS 63 | { 64 | Url = @"http://localhost:5000/packages/versions.json", 65 | CurrentVersion = "1.0.0.0", 66 | VersionFileName = "versions.json", 67 | AppName = "GeneralUpdate.Client.exe", 68 | Encoding = Encoding.UTF8.WebName 69 | }; 70 | await GeneralClientOSS.Start(paramsOSS, "GeneralUpdate.Upgrad.exe");*/ 71 | 72 | /*var hub = new UpgradeHubService("http://localhost:5000/UpgradeHub" 73 | , null,"dfeb5833-975e-4afb-88f1-6278ee9aeff6"); 74 | hub.AddListenerReceive((message) => 75 | { 76 | Debug.WriteLine(message); 77 | }); 78 | await hub.StartAsync();*/ 79 | 80 | /*Task.Run(async () => 81 | { 82 | var source = @"D:\packet\app"; 83 | var target = @"D:\packet\release"; 84 | var patch = @"D:\packet\patch"; 85 | 86 | await DifferentialCore.Instance?.Clean(source, target, patch); 87 | await DifferentialCore.Instance?.Dirty(source, patch); 88 | });*/ 89 | 90 | while (true) 91 | { 92 | var content = Console.ReadLine(); 93 | if (content == "exit") break; 94 | } 95 | } 96 | 97 | private static void OnMultiDownloadError(object arg1, MultiDownloadErrorEventArgs arg2) 98 | { 99 | var version = arg2.Version as VersionInfo; 100 | Console.WriteLine($"{version.Version} {arg2.Exception}"); 101 | } 102 | 103 | private static void OnMultiAllDownloadCompleted(object arg1, MultiAllDownloadCompletedEventArgs arg2) 104 | { 105 | Console.WriteLine(arg2.IsAllDownloadCompleted ? "所有的下载任务已完成!" : $"下载任务已失败!{arg2.FailedVersions.Count}"); 106 | } 107 | 108 | private static void OnMultiDownloadCompleted(object arg1, MultiDownloadCompletedEventArgs arg2) 109 | { 110 | var version = arg2.Version as VersionInfo; 111 | Console.WriteLine(arg2.IsComplated ? $"当前下载版本:{version.Version}, 下载完成!" : $"当前下载版本:{version.Version}, 下载失败!"); 112 | } 113 | 114 | private static void OnMultiDownloadStatistics(object arg1, MultiDownloadStatisticsEventArgs arg2) 115 | { 116 | var version = arg2.Version as VersionInfo; 117 | Console.WriteLine($"当前下载版本:{version.Version},下载速度:{arg2.Speed},剩余下载时间:{arg2.Remaining},已下载大小:{arg2.BytesReceived},总大小:{arg2.TotalBytesToReceive}, 进度百分比:{arg2.ProgressPercentage}%"); 118 | } 119 | 120 | private static void OnException(object arg1, ExceptionEventArgs arg2) 121 | { 122 | Console.WriteLine($"{arg2.Exception}"); 123 | } 124 | } 125 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.ClientCore/Common/git.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/src/c#/GeneralUpdate.ClientCore/Common/git.keep -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.ClientCore/GeneralClientOSS.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Text.Json; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | using GeneralUpdate.Common.FileBasic; 11 | using GeneralUpdate.Common.Internal.Bootstrap; 12 | using GeneralUpdate.Common.Internal.JsonContext; 13 | using GeneralUpdate.Common.Shared.Object; 14 | 15 | namespace GeneralUpdate.ClientCore; 16 | 17 | public sealed class GeneralClientOSS 18 | { 19 | private GeneralClientOSS() { } 20 | 21 | /// 22 | /// Starting an OSS update for windows platform. 23 | /// 24 | public static async Task Start(GlobalConfigInfoOSS configGlobalConfigInfo, string upgradeAppName = "GeneralUpdate.Upgrade.exe") 25 | { 26 | await Task.Run(() => 27 | { 28 | try 29 | { 30 | var basePath = Thread.GetDomain().BaseDirectory; 31 | //Download the version information file from OSS to be updated.(JSON) 32 | var versionsFilePath = Path.Combine(basePath, configGlobalConfigInfo.VersionFileName); 33 | DownloadFile(configGlobalConfigInfo.Url, versionsFilePath); 34 | if (!File.Exists(versionsFilePath)) return; 35 | var versions = StorageManager.GetJson>(versionsFilePath, VersionOSSJsonContext.Default.ListVersionOSS); 36 | if (versions == null || versions.Count == 0) return; 37 | versions = versions.OrderByDescending(x => x.PubTime).ToList(); 38 | var newVersion = versions.First(); 39 | //Determine whether the current client version needs to be upgraded. 40 | if (!IsUpgrade(configGlobalConfigInfo.CurrentVersion, newVersion.Version)) 41 | return; 42 | 43 | //If you confirm that an update is required, start the upgrade application. 44 | var appPath = Path.Combine(basePath, $"{upgradeAppName}"); 45 | if (!File.Exists(appPath)) 46 | throw new Exception($"The application does not exist {upgradeAppName} !"); 47 | 48 | var json = JsonSerializer.Serialize(configGlobalConfigInfo, GlobalConfigInfoOSSJsonContext.Default.GlobalConfigInfoOSS); 49 | Environments.SetEnvironmentVariable("GlobalConfigInfoOSS", json); 50 | Process.Start(appPath); 51 | Process.GetCurrentProcess().Kill(); 52 | } 53 | catch (Exception ex) 54 | { 55 | var error = ex.Message + "\n" + ex.StackTrace; 56 | Trace.WriteLine(error); 57 | throw new Exception(error); 58 | } 59 | }); 60 | } 61 | 62 | /// 63 | /// Determine whether the current client version needs to be upgraded. 64 | /// 65 | /// 66 | /// 67 | /// true: Upgrade required , false: No upgrade is required 68 | private static bool IsUpgrade(string clientVersion, string serverVersion) 69 | { 70 | if (string.IsNullOrWhiteSpace(clientVersion) || string.IsNullOrWhiteSpace(serverVersion)) 71 | return false; 72 | 73 | var isParseClientVersion = Version.TryParse(clientVersion, out var currentClientVersion); 74 | var isParseServerVersion = Version.TryParse(serverVersion, out var currentServerVersion); 75 | if (!isParseClientVersion || !isParseServerVersion) return false; 76 | if (currentClientVersion < currentServerVersion) return true; 77 | return false; 78 | } 79 | 80 | private static void DownloadFile(string url, string path) 81 | { 82 | if (File.Exists(path)) 83 | { 84 | File.SetAttributes(path, FileAttributes.Normal); 85 | File.Delete(path); 86 | } 87 | 88 | using var webClient = new WebClient(); 89 | webClient.DownloadFile(new Uri(url), path); 90 | } 91 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.ClientCore/GeneralUpdate.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/src/c#/GeneralUpdate.ClientCore/GeneralUpdate.ico -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.ClientCore/GeneralUpdate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/src/c#/GeneralUpdate.ClientCore/GeneralUpdate.png -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.ClientCore/Hubs/IUpgradeHubService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace GeneralUpdate.ClientCore.Hubs; 5 | 6 | public interface IUpgradeHubService 7 | { 8 | /// 9 | /// Add a listener to receive upgrade information pushed from the server. 10 | /// 11 | /// string : group name , string : received message content. 12 | public void AddListenerReceive(Action receiveMessageCallback); 13 | 14 | /// 15 | /// Add a listener to receive online and offline notifications. 16 | /// 17 | /// string : Offline or online information. 18 | public void AddListenerOnline(Action onlineMessageCallback); 19 | 20 | /// 21 | /// Add a listener to receive reconnection notifications. 22 | /// 23 | /// string? : Reconnection information. 24 | public void AddListenerReconnected(Func? reconnectedCallback); 25 | 26 | /// 27 | /// Add a listener to receive disconnection notifications. 28 | /// 29 | /// Exception? : Offline exception information. 30 | public void AddListenerClosed(Func closeCallback); 31 | 32 | /// 33 | /// Start subscribing to upgrade push notifications, and the content of the notifications should be agreed upon independently (it is recommended to use JSON data format). 34 | /// 35 | public Task StartAsync(); 36 | 37 | /// 38 | /// When closing the connection, any ongoing message processing will be completed, but no new messages will be accepted. 39 | /// This should be called before the application closes or goes to sleep, so it can reconnect when it resumes next time. 40 | /// 41 | public Task StopAsync(); 42 | 43 | /// 44 | /// The Hub instance will be completely disposed of and cannot be used for reconnection. 45 | /// 46 | public Task DisposeAsync(); 47 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.ClientCore/Hubs/RandomRetryPolicy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.SignalR.Client; 3 | 4 | namespace GeneralUpdate.ClientCore.Hubs; 5 | 6 | public class RandomRetryPolicy : IRetryPolicy 7 | { 8 | private readonly Random _random = new(); 9 | 10 | public TimeSpan? NextRetryDelay(RetryContext retryContext) 11 | { 12 | // If we've been reconnecting for less than 60 seconds so far, 13 | // wait between 0 and 10 seconds before the next reconnect attempt. 14 | if (retryContext.ElapsedTime < TimeSpan.FromSeconds(60)) 15 | return TimeSpan.FromSeconds(_random.NextDouble() * 10); 16 | // If we've been reconnecting for more than 60 seconds so far, stop reconnecting. 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.ClientCore/Hubs/UpgradeHubService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Threading.Tasks; 4 | using GeneralUpdate.Common.Internal.JsonContext; 5 | using Microsoft.AspNetCore.SignalR; 6 | using Microsoft.AspNetCore.SignalR.Client; 7 | using Microsoft.Extensions.DependencyInjection; 8 | 9 | namespace GeneralUpdate.ClientCore.Hubs; 10 | 11 | /// 12 | /// Upgrade the push notification service. 13 | /// 14 | /// Subscription address, for example: http://127.0.0.1/UpgradeHub 15 | /// ID4 authentication token string. 16 | /// Parameters to be sent to the server upon connection (recommended as a JSON string). 17 | public class UpgradeHubService : IUpgradeHubService 18 | { 19 | private const string Onlineflag = "Online"; 20 | private const string ReceiveMessageflag = "ReceiveMessage"; 21 | private HubConnection? _connection; 22 | 23 | public UpgradeHubService(string url, string? token = null, string? appkey = null) 24 | => _connection = BuildHubConnection(url, token, appkey); 25 | 26 | private HubConnection BuildHubConnection(string url, string? token = null, string? appkey = null) 27 | { 28 | var builder = new HubConnectionBuilder() 29 | .WithUrl(url, config => 30 | { 31 | if (!string.IsNullOrWhiteSpace(token)) 32 | config.AccessTokenProvider = () => Task.FromResult(token); 33 | 34 | if (!string.IsNullOrWhiteSpace(appkey)) 35 | config.Headers.Add("appkey", appkey); 36 | }).WithAutomaticReconnect(new RandomRetryPolicy()); 37 | builder.Services.Configure(o => 38 | { 39 | o.PayloadSerializerOptions.TypeInfoResolverChain.Insert(0, PacketJsonContext.Default); 40 | }); 41 | return builder.Build(); 42 | } 43 | 44 | public void AddListenerReceive(Action receiveMessageCallback) 45 | => _connection?.On(ReceiveMessageflag, receiveMessageCallback); 46 | 47 | public void AddListenerOnline(Action onlineMessageCallback) 48 | => _connection?.On(Onlineflag, onlineMessageCallback); 49 | 50 | public void AddListenerReconnected(Func? reconnectedCallback) 51 | => _connection!.Reconnected += reconnectedCallback; 52 | 53 | public void AddListenerClosed(Func closeCallback) 54 | => _connection!.Closed += closeCallback; 55 | 56 | public async Task StartAsync() 57 | { 58 | try 59 | { 60 | await _connection!.StartAsync(); 61 | } 62 | catch (Exception e) 63 | { 64 | Debug.WriteLine(e); 65 | } 66 | } 67 | 68 | public async Task StopAsync() 69 | { 70 | try 71 | { 72 | await _connection!.StopAsync(); 73 | } 74 | catch (Exception e) 75 | { 76 | Debug.WriteLine(e); 77 | } 78 | } 79 | 80 | public async Task DisposeAsync() 81 | { 82 | try 83 | { 84 | await _connection!.DisposeAsync(); 85 | } 86 | catch (Exception e) 87 | { 88 | Debug.WriteLine(e); 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.ClientCore/Pipeline/CompressMiddleware.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using GeneralUpdate.Common.Compress; 7 | using GeneralUpdate.Common.Internal; 8 | using GeneralUpdate.Common.Internal.Event; 9 | using GeneralUpdate.Common.Internal.Pipeline; 10 | 11 | namespace GeneralUpdate.ClientCore.Pipeline; 12 | 13 | public class CompressMiddleware : IMiddleware 14 | { 15 | public Task InvokeAsync(PipelineContext? context) 16 | { 17 | return Task.Run(() => 18 | { 19 | var format = context.Get("Format"); 20 | var sourcePath = context.Get("ZipFilePath"); 21 | var patchPath = context.Get("PatchPath"); 22 | var encoding = context.Get("Encoding"); 23 | CompressProvider.Decompress(format,sourcePath,patchPath, encoding); 24 | }); 25 | } 26 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.ClientCore/Pipeline/HashMiddleware.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Security.Cryptography; 4 | using System.Threading.Tasks; 5 | using GeneralUpdate.Common.HashAlgorithms; 6 | using GeneralUpdate.Common.Internal; 7 | using GeneralUpdate.Common.Internal.Event; 8 | using GeneralUpdate.Common.Internal.Pipeline; 9 | 10 | namespace GeneralUpdate.ClientCore.Pipeline; 11 | 12 | public class HashMiddleware : IMiddleware 13 | { 14 | public async Task InvokeAsync(PipelineContext context) 15 | { 16 | var path = context.Get("ZipFilePath"); 17 | var hash = context.Get("Hash"); 18 | var isVerify = await VerifyFileHash(path, hash); 19 | if (!isVerify) throw new CryptographicException("Hash verification failed ."); 20 | } 21 | 22 | private Task VerifyFileHash(string path, string hash) 23 | { 24 | return Task.Run(() => 25 | { 26 | try 27 | { 28 | var hashAlgorithm = new Sha256HashAlgorithm(); 29 | var hashSha256 = hashAlgorithm.ComputeHash(path); 30 | return string.Equals(hash, hashSha256, StringComparison.OrdinalIgnoreCase); 31 | } 32 | catch (Exception exception) 33 | { 34 | Debug.WriteLine(exception.Message); 35 | EventManager.Instance.Dispatch(this, new ExceptionEventArgs(exception, exception.Message)); 36 | } 37 | return false; 38 | }); 39 | } 40 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.ClientCore/Pipeline/PatchMiddleware.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Threading.Tasks; 5 | using GeneralUpdate.Common.FileBasic; 6 | using GeneralUpdate.Common.Internal; 7 | using GeneralUpdate.Common.Internal.Event; 8 | using GeneralUpdate.Common.Internal.Pipeline; 9 | using GeneralUpdate.Differential; 10 | 11 | namespace GeneralUpdate.ClientCore.Pipeline; 12 | 13 | public class PatchMiddleware : IMiddleware 14 | { 15 | public async Task InvokeAsync(PipelineContext context) 16 | { 17 | var sourcePath = context.Get("SourcePath"); 18 | var targetPath = context.Get("PatchPath"); 19 | await DifferentialCore.Instance.Dirty(sourcePath, targetPath); 20 | } 21 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.ClientCore/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "GeneralUpdate.ClientCore": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "environmentVariables": { 7 | "ASPNETCORE_ENVIRONMENT": "Development" 8 | }, 9 | "applicationUrl": "https://localhost:65352;http://localhost:65362" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.ClientCore/Strategys/LinuxStrategy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using GeneralUpdate.ClientCore.Pipeline; 7 | using GeneralUpdate.Common.FileBasic; 8 | using GeneralUpdate.Common.Internal; 9 | using GeneralUpdate.Common.Internal.Event; 10 | using GeneralUpdate.Common.Internal.Pipeline; 11 | using GeneralUpdate.Common.Internal.Strategy; 12 | using GeneralUpdate.Common.Shared.Object; 13 | using GeneralUpdate.Common.Shared.Object.Enum; 14 | using GeneralUpdate.Common.Shared.Service; 15 | 16 | namespace GeneralUpdate.ClientCore.Strategys; 17 | 18 | /// 19 | /// Update policy based on the linux platform. 20 | /// 21 | public class LinuxStrategy : AbstractStrategy 22 | { 23 | private GlobalConfigInfo _configinfo = new(); 24 | private const string ProcessInfoFileName = "ProcessInfo.json"; 25 | 26 | public override void Create(GlobalConfigInfo parameter) => _configinfo = parameter; 27 | 28 | public override async Task ExecuteAsync() 29 | { 30 | try 31 | { 32 | var status = ReportType.None; 33 | var patchPath = StorageManager.GetTempDirectory(Patchs); 34 | foreach (var version in _configinfo.UpdateVersions) 35 | { 36 | try 37 | { 38 | var context = new PipelineContext(); 39 | //Common 40 | context.Add("ZipFilePath", 41 | Path.Combine(_configinfo.TempPath, $"{version.Name}{_configinfo.Format}")); 42 | //hash middleware 43 | context.Add("Hash", version.Hash); 44 | //zip middleware 45 | context.Add("Format", _configinfo.Format); 46 | context.Add("Name", version.Name); 47 | context.Add("Encoding", _configinfo.Encoding); 48 | //patch middleware 49 | context.Add("SourcePath", _configinfo.InstallPath); 50 | context.Add("PatchPath", patchPath); 51 | context.Add("BlackFiles", _configinfo.BlackFiles); 52 | context.Add("BlackFileFormats", _configinfo.BlackFormats); 53 | context.Add("SkipDirectorys", _configinfo.SkipDirectorys); 54 | 55 | var pipelineBuilder = new PipelineBuilder(context) 56 | .UseMiddleware() 57 | .UseMiddleware() 58 | .UseMiddleware(); 59 | await pipelineBuilder.Build(); 60 | status = ReportType.Success; 61 | } 62 | catch (Exception e) 63 | { 64 | status = ReportType.Failure; 65 | EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); 66 | } 67 | finally 68 | { 69 | await VersionService.Report(_configinfo.ReportUrl 70 | , version.RecordId 71 | , status 72 | , version.AppType 73 | , _configinfo.Scheme 74 | , _configinfo.Token); 75 | } 76 | } 77 | 78 | if (!string.IsNullOrEmpty(_configinfo.UpdateLogUrl)) 79 | { 80 | OpenBrowser(_configinfo.UpdateLogUrl); 81 | } 82 | 83 | Clear(patchPath); 84 | Clear(_configinfo.TempPath); 85 | } 86 | catch (Exception e) 87 | { 88 | Debug.WriteLine(e); 89 | EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); 90 | } 91 | } 92 | 93 | public override void StartApp() 94 | { 95 | try 96 | { 97 | var appPath = Path.Combine(_configinfo.InstallPath, _configinfo.AppName); 98 | if (File.Exists(appPath)) 99 | { 100 | if (File.Exists(ProcessInfoFileName)) 101 | { 102 | File.SetAttributes(ProcessInfoFileName, FileAttributes.Normal); 103 | File.Delete(ProcessInfoFileName); 104 | } 105 | 106 | File.WriteAllText(ProcessInfoFileName, _configinfo.ProcessInfo); 107 | Process.Start(appPath); 108 | } 109 | } 110 | catch (Exception e) 111 | { 112 | Debug.WriteLine(e); 113 | EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); 114 | } 115 | finally 116 | { 117 | Process.GetCurrentProcess().Kill(); 118 | } 119 | } 120 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.ClientCore/Strategys/WindowsStrategy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Threading.Tasks; 5 | using GeneralUpdate.ClientCore.Pipeline; 6 | using GeneralUpdate.Common.FileBasic; 7 | using GeneralUpdate.Common.Internal; 8 | using GeneralUpdate.Common.Internal.Bootstrap; 9 | using GeneralUpdate.Common.Internal.Event; 10 | using GeneralUpdate.Common.Internal.Pipeline; 11 | using GeneralUpdate.Common.Internal.Strategy; 12 | using GeneralUpdate.Common.Shared.Object; 13 | using GeneralUpdate.Common.Shared.Object.Enum; 14 | using GeneralUpdate.Common.Shared.Service; 15 | 16 | namespace GeneralUpdate.ClientCore.Strategys; 17 | 18 | /// 19 | /// Update policy based on the Windows platform. 20 | /// 21 | public class WindowsStrategy : AbstractStrategy 22 | { 23 | private GlobalConfigInfo _configinfo = new(); 24 | 25 | public override void Create(GlobalConfigInfo parameter) => _configinfo = parameter; 26 | 27 | public override async Task ExecuteAsync() 28 | { 29 | try 30 | { 31 | var status = ReportType.None; 32 | var patchPath = StorageManager.GetTempDirectory(Patchs); 33 | foreach (var version in _configinfo.UpdateVersions) 34 | { 35 | try 36 | { 37 | var context = new PipelineContext(); 38 | //Common 39 | context.Add("ZipFilePath", 40 | Path.Combine(_configinfo.TempPath, $"{version.Name}{_configinfo.Format}")); 41 | //hash middleware 42 | context.Add("Hash", version.Hash); 43 | //zip middleware 44 | context.Add("Format", _configinfo.Format); 45 | context.Add("Name", version.Name); 46 | context.Add("Encoding", _configinfo.Encoding); 47 | //patch middleware 48 | context.Add("SourcePath", _configinfo.InstallPath); 49 | context.Add("PatchPath", patchPath); 50 | 51 | var pipelineBuilder = new PipelineBuilder(context) 52 | .UseMiddleware() 53 | .UseMiddleware() 54 | .UseMiddleware(); 55 | await pipelineBuilder.Build(); 56 | status = ReportType.Success; 57 | } 58 | catch (Exception e) 59 | { 60 | status = ReportType.Failure; 61 | EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); 62 | } 63 | finally 64 | { 65 | await VersionService.Report(_configinfo.ReportUrl 66 | , version.RecordId 67 | , status 68 | , version.AppType 69 | , _configinfo.Scheme 70 | , _configinfo.Token); 71 | } 72 | } 73 | 74 | if (!string.IsNullOrEmpty(_configinfo.UpdateLogUrl)) 75 | { 76 | OpenBrowser(_configinfo.UpdateLogUrl); 77 | } 78 | 79 | Clear(patchPath); 80 | Clear(_configinfo.TempPath); 81 | } 82 | catch (Exception e) 83 | { 84 | Debug.WriteLine(e); 85 | EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); 86 | } 87 | } 88 | 89 | public override void StartApp() 90 | { 91 | try 92 | { 93 | Environments.SetEnvironmentVariable("ProcessInfo", _configinfo.ProcessInfo); 94 | var appPath = Path.Combine(_configinfo.InstallPath, _configinfo.AppName); 95 | if (File.Exists(appPath)) 96 | { 97 | Environments.SetEnvironmentVariable("ProcessInfo", _configinfo.ProcessInfo); 98 | Process.Start(new ProcessStartInfo 99 | { 100 | UseShellExecute = true, 101 | FileName = appPath 102 | }); 103 | } 104 | } 105 | catch (Exception e) 106 | { 107 | Debug.WriteLine(e); 108 | EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); 109 | } 110 | finally 111 | { 112 | Process.GetCurrentProcess().Kill(); 113 | } 114 | } 115 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Compress/CompressProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using GeneralUpdate.Common.Shared.Object; 4 | 5 | namespace GeneralUpdate.Common.Compress; 6 | 7 | public class CompressProvider 8 | { 9 | private static ICompressionStrategy _compressionStrategy; 10 | 11 | private CompressProvider() { } 12 | 13 | public static void Compress(string compressType,string sourcePath, string destinationPath, bool includeRootDirectory, Encoding encoding) 14 | { 15 | _compressionStrategy = GetCompressionStrategy(compressType); 16 | _compressionStrategy.Compress(sourcePath, destinationPath, includeRootDirectory, encoding); 17 | } 18 | 19 | public static void Decompress(string compressType, string archivePath, string destinationPath, Encoding encoding) 20 | { 21 | _compressionStrategy = GetCompressionStrategy(compressType); 22 | _compressionStrategy.Decompress(archivePath, destinationPath, encoding); 23 | } 24 | 25 | private static ICompressionStrategy GetCompressionStrategy(string compressType) => compressType switch 26 | { 27 | Format.ZIP => new ZipCompressionStrategy(), 28 | _ => throw new ArgumentException("Compression format is not supported!") 29 | }; 30 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Compress/ICompressionStrategy.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace GeneralUpdate.Common.Compress; 4 | 5 | public interface ICompressionStrategy 6 | { 7 | void Compress(string sourcePath, string destinationPath, bool includeRootDirectory, Encoding encoding); 8 | void Decompress(string archivePath, string destinationPath, Encoding encoding); 9 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Download/DownloadManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using System.Collections.Immutable; 5 | using System.Diagnostics; 6 | using System.Linq; 7 | 8 | namespace GeneralUpdate.Common.Download 9 | { 10 | public class DownloadManager(string path, string format, int timeOut) 11 | { 12 | #region Private Members 13 | 14 | private readonly ImmutableList.Builder _downloadTasksBuilder = ImmutableList.Create().ToBuilder(); 15 | private ImmutableList _downloadTasks; 16 | 17 | #endregion Private Members 18 | 19 | #region Public Properties 20 | 21 | public List<(object, string)> FailedVersions { get; } = new(); 22 | 23 | public string Path => path; 24 | 25 | public string Format => format; 26 | 27 | public int TimeOut => timeOut; 28 | 29 | private ImmutableList DownloadTasks => _downloadTasks ?? _downloadTasksBuilder.ToImmutable(); 30 | 31 | public event EventHandler MultiAllDownloadCompleted; 32 | public event EventHandler MultiDownloadCompleted; 33 | public event EventHandler MultiDownloadError; 34 | public event EventHandler MultiDownloadStatistics; 35 | 36 | #endregion Public Properties 37 | 38 | #region Public Methods 39 | 40 | public async Task LaunchTasksAsync() 41 | { 42 | try 43 | { 44 | var downloadTasks = DownloadTasks.Select(task => task.LaunchAsync()).ToList(); 45 | await Task.WhenAll(downloadTasks); 46 | MultiAllDownloadCompleted?.Invoke(this, new MultiAllDownloadCompletedEventArgs(true, FailedVersions)); 47 | } 48 | catch (Exception ex) 49 | { 50 | MultiAllDownloadCompleted?.Invoke(this, new MultiAllDownloadCompletedEventArgs(false, FailedVersions)); 51 | throw new Exception($"Download manager error: {ex.Message}", ex); 52 | } 53 | } 54 | 55 | public void OnMultiDownloadStatistics(object sender, MultiDownloadStatisticsEventArgs e) 56 | => MultiDownloadStatistics?.Invoke(this, e); 57 | 58 | public void OnMultiAsyncCompleted(object sender, MultiDownloadCompletedEventArgs e) 59 | => MultiDownloadCompleted?.Invoke(this, e); 60 | 61 | public void OnMultiDownloadError(object sender, MultiDownloadErrorEventArgs e) 62 | { 63 | MultiDownloadError?.Invoke(this, e); 64 | FailedVersions.Add((e.Version, e.Exception.Message)); 65 | } 66 | 67 | public void Add(DownloadTask task) 68 | { 69 | Debug.Assert(task != null); 70 | if (!_downloadTasksBuilder.Contains(task)) 71 | { 72 | _downloadTasksBuilder.Add(task); 73 | } 74 | } 75 | 76 | #endregion Public Methods 77 | } 78 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Download/MultiEventArgs/MutiAllDownloadCompletedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace GeneralUpdate.Common.Download 5 | { 6 | public class MultiAllDownloadCompletedEventArgs : EventArgs 7 | { 8 | public MultiAllDownloadCompletedEventArgs(bool isAllDownloadCompleted, IList<(object, string)> failedVersions) 9 | { 10 | IsAllDownloadCompleted = isAllDownloadCompleted; 11 | FailedVersions = failedVersions; 12 | } 13 | 14 | public bool IsAllDownloadCompleted { get; set; } 15 | 16 | public IList> FailedVersions { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Download/MultiEventArgs/MutiDownloadCompletedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GeneralUpdate.Common.Download 4 | { 5 | public class MultiDownloadCompletedEventArgs(object version, bool isComplated) : EventArgs 6 | { 7 | public object Version { get; private set; } = version; 8 | 9 | public bool IsComplated { get; private set; } = isComplated; 10 | } 11 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Download/MultiEventArgs/MutiDownloadErrorEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GeneralUpdate.Common.Download 4 | { 5 | public class MultiDownloadErrorEventArgs : EventArgs 6 | { 7 | public MultiDownloadErrorEventArgs(Exception exception, object version) 8 | { 9 | Exception = exception; 10 | Version = version; 11 | } 12 | 13 | public Exception Exception { get; set; } 14 | 15 | public object Version { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Download/MultiEventArgs/MutiDownloadStatisticsEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GeneralUpdate.Common.Download; 4 | 5 | public class MultiDownloadStatisticsEventArgs(object version 6 | , TimeSpan remaining 7 | , string speed 8 | , long totalBytes 9 | , long bytesReceived 10 | , double progressPercentage) : EventArgs 11 | { 12 | public object Version { get; private set; } = version; 13 | 14 | public TimeSpan Remaining { get; private set; } = remaining; 15 | 16 | public string Speed { get; private set; } = speed; 17 | 18 | public long TotalBytesToReceive { get; private set; } = totalBytes; 19 | 20 | public long BytesReceived { get; private set; } = bytesReceived; 21 | 22 | public double ProgressPercentage { get; private set; } = progressPercentage; 23 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/FileBasic/BlackListManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Linq; 4 | using GeneralUpdate.Common.Shared.Object; 5 | 6 | namespace GeneralUpdate.Common.FileBasic; 7 | 8 | public class BlackListManager 9 | { 10 | private static readonly object LockObject = new object(); 11 | private static BlackListManager? _instance; 12 | 13 | private static readonly List _blackFileFormats = 14 | [ 15 | ".patch", 16 | Format.ZIP, 17 | ".rar", 18 | ".tar", 19 | ".json", 20 | ".pdb" 21 | ]; 22 | 23 | private static readonly List _blackFiles = 24 | [ 25 | "Microsoft.Bcl.AsyncInterfaces.dll", 26 | "System.Collections.Immutable.dll", 27 | "System.IO.Pipelines.dll", 28 | "System.Text.Encodings.Web.dll", 29 | "System.Text.Json.dll" 30 | ]; 31 | 32 | private static readonly List _skipDirectorys = ["app-", "fail"]; 33 | 34 | private BlackListManager() { } 35 | 36 | public static BlackListManager? Instance 37 | { 38 | get 39 | { 40 | if (_instance == null) 41 | { 42 | lock (LockObject) 43 | { 44 | if (_instance == null) 45 | { 46 | _instance = new BlackListManager(); 47 | } 48 | } 49 | } 50 | 51 | return _instance; 52 | } 53 | } 54 | 55 | public IReadOnlyList BlackFileFormats => _blackFileFormats.AsReadOnly(); 56 | public IReadOnlyList BlackFiles => _blackFiles.AsReadOnly(); 57 | 58 | public IReadOnlyList SkipDirectorys = _skipDirectorys.AsReadOnly(); 59 | 60 | public void AddBlackFileFormats(List? formats) 61 | { 62 | if (formats == null) 63 | return; 64 | 65 | foreach (var format in formats) 66 | { 67 | AddBlackFileFormat(format); 68 | } 69 | } 70 | 71 | public void AddBlackFileFormat(string format) 72 | { 73 | if (string.IsNullOrWhiteSpace(format)) 74 | return; 75 | 76 | if (!_blackFileFormats.Contains(format)) 77 | { 78 | _blackFileFormats.Add(format); 79 | } 80 | } 81 | 82 | public void AddBlackFiles(List? fileNames) 83 | { 84 | if (fileNames == null) 85 | return; 86 | 87 | foreach (var fileName in fileNames) 88 | { 89 | AddBlackFile(fileName); 90 | } 91 | } 92 | 93 | public void AddBlackFile(string fileName) 94 | { 95 | if (string.IsNullOrWhiteSpace(fileName)) 96 | return; 97 | 98 | if (!_blackFiles.Contains(fileName)) 99 | { 100 | _blackFiles.Add(fileName); 101 | } 102 | } 103 | 104 | public void AddSkipDirectorys(List? directorys) 105 | { 106 | if (directorys == null) 107 | return; 108 | 109 | foreach (var directory in directorys) 110 | { 111 | AddSkipDirectory(directory); 112 | } 113 | } 114 | 115 | public void AddSkipDirectory(string directory) 116 | { 117 | if (string.IsNullOrWhiteSpace(directory)) 118 | return; 119 | 120 | if (!_skipDirectorys.Contains(directory)) 121 | { 122 | _skipDirectorys.Add(directory); 123 | } 124 | } 125 | 126 | public bool IsBlacklisted(string relativeFilePath) 127 | { 128 | var fileName = Path.GetFileName(relativeFilePath); 129 | var fileExtension = Path.GetExtension(relativeFilePath); 130 | 131 | return _blackFiles.Contains(fileName) || _blackFileFormats.Contains(fileExtension); 132 | } 133 | 134 | public bool IsSkipDirectory(string directory) 135 | { 136 | return _skipDirectorys.Any(directory.Contains); 137 | } 138 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/FileBasic/ComparisonResult.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace GeneralUpdate.Common.FileBasic; 4 | 5 | /// 6 | /// Result of a comparison between two directories. 7 | /// 8 | public class ComparisonResult 9 | { 10 | private List _leftNodes; 11 | private List _rightNodes; 12 | private List _differentNodes; 13 | 14 | public ComparisonResult() 15 | { 16 | _leftNodes = new List(); 17 | _rightNodes = new List(); 18 | _differentNodes = new List(); 19 | } 20 | 21 | /// 22 | /// List of files that are unique to A. 23 | /// 24 | public IReadOnlyList LeftNodes => _leftNodes.AsReadOnly(); 25 | 26 | /// 27 | /// List of files that are unique to B. 28 | /// 29 | public IReadOnlyList RightNodes => _rightNodes.AsReadOnly(); 30 | 31 | /// 32 | /// List of files that are different between A and B. 33 | /// 34 | public IReadOnlyList DifferentNodes => _differentNodes.AsReadOnly(); 35 | 36 | public void AddToLeft(IEnumerable files) => _leftNodes.AddRange(files); 37 | 38 | public void AddToRight(IEnumerable files) => _rightNodes.AddRange(files); 39 | 40 | public void AddDifferent(IEnumerable files) => _differentNodes.AddRange(files); 41 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/FileBasic/FileNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GeneralUpdate.Common.FileBasic; 4 | 5 | public class FileNode 6 | { 7 | #region Public Properties 8 | 9 | public long Id { get; set; } 10 | 11 | public string Name { get; set; } 12 | 13 | public string FullName { get; set; } 14 | 15 | public string Path { get; set; } 16 | 17 | public string Hash { get; set; } 18 | 19 | public FileNode Left { get; set; } 20 | 21 | public FileNode Right { get; set; } 22 | 23 | public int LeftType { get; set; } 24 | 25 | public int RightType { get; set; } 26 | 27 | public string RelativePath { get; set; } 28 | 29 | #endregion Public Properties 30 | 31 | #region Constructors 32 | 33 | public FileNode() 34 | { 35 | } 36 | 37 | public FileNode(int id) 38 | { 39 | Id = id; 40 | } 41 | 42 | #endregion Constructors 43 | 44 | #region Public Methods 45 | 46 | public void Add(FileNode node) 47 | { 48 | if (node == null) return; 49 | 50 | if (node.Id < Id) 51 | { 52 | if (Left == null) 53 | { 54 | Left = node; 55 | } 56 | else 57 | { 58 | Left.Add(node); 59 | } 60 | } 61 | else 62 | { 63 | if (Right == null) 64 | { 65 | Right = node; 66 | } 67 | else 68 | { 69 | Right.Add(node); 70 | } 71 | } 72 | } 73 | 74 | public void InfixOrder() 75 | { 76 | if (Left != null) 77 | { 78 | Left.InfixOrder(); 79 | } 80 | 81 | if (Right != null) 82 | { 83 | Right.InfixOrder(); 84 | } 85 | } 86 | 87 | public FileNode Search(long id) 88 | { 89 | if (id == Id) 90 | { 91 | return this; 92 | } 93 | else if (id < Id) 94 | { 95 | if (Left == null) return null; 96 | return Left.Search(id); 97 | } 98 | else 99 | { 100 | if (Right == null) return null; 101 | return Right.Search(id); 102 | } 103 | } 104 | 105 | /// 106 | /// Find the parent node of the node that you want to delete. 107 | /// 108 | /// 109 | /// 110 | public FileNode SearchParent(long id) 111 | { 112 | if (Left != null && Left.Id == id || Right != null && Right.Id == id) 113 | { 114 | return this; 115 | } 116 | else 117 | { 118 | if (id < Id && Left != null) 119 | { 120 | return Left.SearchParent(id); 121 | } 122 | else if (id >= Id && Right != null) 123 | { 124 | return Right.SearchParent(id); 125 | } 126 | else 127 | { 128 | return null; 129 | } 130 | } 131 | } 132 | 133 | /// 134 | /// Compare tree nodes equally by Hash and file names. 135 | /// 136 | /// 137 | /// 138 | public override bool Equals(object obj) 139 | { 140 | if (obj == null) return false; 141 | var tempNode = obj as FileNode; 142 | if (tempNode == null) throw new ArgumentException(nameof(tempNode)); 143 | return string.Equals(Hash, tempNode.Hash, StringComparison.OrdinalIgnoreCase) && 144 | string.Equals(Name, tempNode.Name, StringComparison.OrdinalIgnoreCase); 145 | } 146 | 147 | public override int GetHashCode() => base.GetHashCode(); 148 | 149 | #endregion Public Methods 150 | } 151 | -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/FileBasic/FileTree.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Diagnostics; 3 | 4 | namespace GeneralUpdate.Common.FileBasic; 5 | 6 | /// 7 | /// Simple file binary tree. 8 | /// 9 | public class FileTree 10 | { 11 | #region Private Members 12 | 13 | private FileNode _root; 14 | 15 | #endregion Private Members 16 | 17 | #region Constructors 18 | 19 | public FileTree() 20 | { } 21 | 22 | public FileTree(IEnumerable nodes) 23 | { 24 | foreach (var node in nodes) Add(node); 25 | } 26 | 27 | #endregion Constructors 28 | 29 | #region Public Methods 30 | 31 | public void Add(FileNode node) 32 | { 33 | if (_root == null) 34 | { 35 | _root = node; 36 | } 37 | else 38 | { 39 | _root.Add(node); 40 | } 41 | } 42 | 43 | public void InfixOrder() 44 | { 45 | if (_root != null) 46 | { 47 | _root.InfixOrder(); 48 | } 49 | else 50 | { 51 | Debug.WriteLine("The binary sort tree is empty and cannot be traversed!"); 52 | } 53 | } 54 | 55 | public FileNode Search(long id) => _root == null ? null : _root.Search(id); 56 | 57 | public FileNode SearchParent(long id) => _root == null ? null : _root.SearchParent(id); 58 | 59 | public long DelRightTreeMin(FileNode node) 60 | { 61 | FileNode target = node; 62 | while (target.Left != null) 63 | { 64 | target = target.Left; 65 | } 66 | DelNode(target.Id); 67 | return target.Id; 68 | } 69 | 70 | public void DelNode(long id) 71 | { 72 | if (_root == null) 73 | { 74 | return; 75 | } 76 | else 77 | { 78 | FileNode targetNode = Search(id); 79 | if (targetNode == null) 80 | { 81 | return; 82 | } 83 | if (_root.Left == null && _root.Right == null) 84 | { 85 | _root = null; 86 | return; 87 | } 88 | 89 | FileNode parent = SearchParent(id); 90 | if (targetNode.Left == null && targetNode.Right == null) 91 | { 92 | if (parent.Left != null && parent.Left.Id == id) 93 | { 94 | parent.Left = null; 95 | } 96 | else if (parent.Right != null && parent.Right.Id == id) 97 | { 98 | parent.Right = null; 99 | } 100 | } 101 | else if (targetNode.Left != null && targetNode.Right != null) 102 | { 103 | long minVal = DelRightTreeMin(targetNode.Right); 104 | targetNode.Id = minVal; 105 | } 106 | else 107 | { 108 | if (targetNode.Left != null) 109 | { 110 | if (parent.Left.Id == id) 111 | { 112 | parent.Left = targetNode.Left; 113 | } 114 | else 115 | { 116 | parent.Right = targetNode.Left; 117 | } 118 | } 119 | else 120 | { 121 | if (parent.Left.Id == id) 122 | { 123 | parent.Left = targetNode.Right; 124 | } 125 | else 126 | { 127 | parent.Right = targetNode.Right; 128 | } 129 | } 130 | } 131 | } 132 | } 133 | 134 | /// 135 | /// Starting from the root node, recursively compares two different child nodes of the binary tree and nodes that are not included. 136 | /// 137 | /// 138 | /// 139 | /// 140 | public void Compare(FileNode node, FileNode node0, ref List nodes) 141 | { 142 | if (node != null && node.Left != null) 143 | { 144 | if (!node.Equals(node0) && node0 != null) nodes.Add(node0); 145 | Compare(node.Left, node0.Left, ref nodes); 146 | } 147 | else if (node0 != null && node0.Left != null) 148 | { 149 | nodes.Add(node0); 150 | Compare(node.Left, node0.Left, ref nodes); 151 | } 152 | 153 | if (node != null && node.Right != null) 154 | { 155 | if (!node.Equals(node0) && node0 != null) nodes.Add(node0); 156 | Compare(node.Right, node0 == null ? null : node0.Right, ref nodes); 157 | } 158 | else if (node0 != null && node0.Right != null) 159 | { 160 | nodes.Add(node0); 161 | Compare(node == null ? null : node.Right, node0.Right, ref nodes); 162 | } 163 | else if (node0 != null) 164 | { 165 | nodes.Add(node0); 166 | } 167 | } 168 | 169 | public FileNode GetRoot() => _root; 170 | 171 | #endregion Public Methods 172 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/GeneralUpdate.Common.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | default 5 | enable 6 | netstandard2.0 7 | GeneralUpdate.Common 8 | JusterZhu 9 | The infrastructure required to support all components is necessary, and this nuget package is essential. 10 | Copyright © 2024 JusterZhu. All rights reserved. 11 | https://github.com/GeneralLibrary/GeneralUpdate 12 | https://github.com/GeneralLibrary/GeneralUpdate?tab=MIT-1-ov-file#readme 13 | GeneralUpdate128.png 14 | https://github.com/GeneralLibrary/GeneralUpdate 15 | public 16 | upgrade,update 17 | The infrastructure required to support all components is necessary, and this nuget package is essential. 18 | true 19 | 9.1.6 20 | true 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | True 32 | 33 | GeneralUpdate.ico 34 | 35 | 36 | True 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/GeneralUpdate128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/src/c#/GeneralUpdate.Common/GeneralUpdate128.png -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/HashAlgorithms/HashAlgorithmBase.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Security.Cryptography; 3 | using System.Text; 4 | 5 | namespace GeneralUpdate.Common.HashAlgorithms 6 | { 7 | public abstract class HashAlgorithmBase 8 | { 9 | public string ComputeHash(string fileName) 10 | { 11 | if (!System.IO.File.Exists(fileName)) 12 | throw new FileNotFoundException(nameof(fileName)); 13 | 14 | using var hashAlgorithm = GetHashAlgorithm(); 15 | using var file = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); 16 | var dataArray = hashAlgorithm.ComputeHash(file); 17 | var stringBuilder = new StringBuilder(); 18 | for (int i = 0; i < dataArray.Length; i++) 19 | { 20 | stringBuilder.Append(dataArray[i].ToString("x2")); 21 | } 22 | return stringBuilder.ToString(); 23 | } 24 | 25 | public byte[] ComputeHashBytes(string fileName) 26 | { 27 | if (!File.Exists(fileName)) 28 | throw new FileNotFoundException(nameof(fileName)); 29 | 30 | using var hashAlgorithm = GetHashAlgorithm(); 31 | using var file = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); 32 | return hashAlgorithm.ComputeHash(file); 33 | } 34 | 35 | protected abstract HashAlgorithm GetHashAlgorithm(); 36 | } 37 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/HashAlgorithms/Md5HashAlgorithm.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Cryptography; 2 | 3 | namespace GeneralUpdate.Common.HashAlgorithms 4 | { 5 | public class Md5HashAlgorithm : HashAlgorithmBase 6 | { 7 | protected override HashAlgorithm GetHashAlgorithm() => MD5.Create(); 8 | } 9 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/HashAlgorithms/Sha1HashAlgorithm.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Cryptography; 2 | 3 | namespace GeneralUpdate.Common.HashAlgorithms 4 | { 5 | public class Sha1HashAlgorithm : HashAlgorithmBase 6 | { 7 | protected override HashAlgorithm GetHashAlgorithm() => new SHA1Managed(); 8 | } 9 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/HashAlgorithms/Sha256HashAlgorithm.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Cryptography; 2 | 3 | namespace GeneralUpdate.Common.HashAlgorithms 4 | { 5 | public class Sha256HashAlgorithm : HashAlgorithmBase 6 | { 7 | protected override HashAlgorithm GetHashAlgorithm() => SHA256.Create(); 8 | } 9 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/Bootstrap/AbstractBootstrap.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | using System.Diagnostics; 3 | using System.Threading.Tasks; 4 | using GeneralUpdate.Common.Internal.Strategy; 5 | 6 | namespace GeneralUpdate.Common.Internal.Bootstrap 7 | { 8 | public abstract class AbstractBootstrap 9 | where TBootstrap : AbstractBootstrap 10 | where TStrategy : IStrategy 11 | { 12 | private readonly ConcurrentDictionary _options; 13 | 14 | protected internal AbstractBootstrap() => 15 | _options = new ConcurrentDictionary(); 16 | 17 | /// 18 | /// Launch async udpate. 19 | /// 20 | /// 21 | public abstract Task LaunchAsync(); 22 | 23 | protected abstract void ExecuteStrategy(); 24 | 25 | protected abstract Task ExecuteStrategyAsync(); 26 | 27 | protected abstract TBootstrap StrategyFactory(); 28 | 29 | /// 30 | /// Setting update configuration. 31 | /// 32 | /// 33 | /// Configuration Action Enumeration. 34 | /// Value 35 | /// 36 | public TBootstrap Option(UpdateOption option, T value) 37 | { 38 | if (value == null) 39 | { 40 | _options.TryRemove(option, out _); 41 | } 42 | else 43 | { 44 | _options[option] = new UpdateOptionValue(option, value); 45 | } 46 | return (TBootstrap)this; 47 | } 48 | 49 | protected T? GetOption(UpdateOption? option) 50 | { 51 | try 52 | { 53 | Debug.Assert(option != null && _options.Count != 0); 54 | var val = _options[option]; 55 | if (val != null) return (T)val.GetValue(); 56 | return default; 57 | } 58 | catch 59 | { 60 | return default; 61 | } 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/Bootstrap/Environments.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace GeneralUpdate.Common.Internal.Bootstrap; 4 | 5 | public static class Environments 6 | { 7 | public static void SetEnvironmentVariable(string key, string value) 8 | { 9 | var filePath = Path.Combine(Path.GetTempPath(), $"{key}.txt"); 10 | File.WriteAllText(filePath, value); 11 | } 12 | 13 | public static string GetEnvironmentVariable(string key) 14 | { 15 | var filePath = Path.Combine(Path.GetTempPath(), $"{key}.txt"); 16 | if (!File.Exists(filePath)) 17 | return string.Empty; 18 | 19 | var content = File.ReadAllText(filePath); 20 | File.SetAttributes(filePath, FileAttributes.Normal); 21 | File.Delete(filePath); 22 | return content; 23 | } 24 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/Bootstrap/UpdateOption.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.Contracts; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | namespace GeneralUpdate.Common.Internal.Bootstrap 8 | { 9 | public abstract class UpdateOption : AbstractConstant 10 | { 11 | private class UpdateOptionPool : ConstantPool 12 | { 13 | protected override IConstant NewConstant(int id, string name) => new UpdateOption(id, name); 14 | } 15 | 16 | private static readonly UpdateOptionPool Pool = new(); 17 | 18 | public static UpdateOption ValueOf(string name) => (UpdateOption)Pool.ValueOf(name); 19 | 20 | /// 21 | /// Update the file format of the package. 22 | /// 23 | public static readonly UpdateOption Format = ValueOf("COMPRESSFORMAT"); 24 | 25 | /// 26 | /// Compress encoding. 27 | /// 28 | public static readonly UpdateOption Encoding = ValueOf("COMPRESSENCODING"); 29 | 30 | /// 31 | /// Timeout period (unit: second). If this parameter is not specified, the default timeout period is 30 seconds. 32 | /// 33 | public static readonly UpdateOption DownloadTimeOut = ValueOf("DOWNLOADTIMEOUT"); 34 | 35 | /// 36 | /// Whether to enable the driver upgrade function. 37 | /// 38 | public static readonly UpdateOption Drive = ValueOf("DRIVE"); 39 | 40 | internal UpdateOption(int id, string name) 41 | : base(id, name) { } 42 | 43 | public abstract bool Set(IUpdateConfiguration configuration, object value); 44 | } 45 | 46 | public sealed class UpdateOption : UpdateOption 47 | { 48 | internal UpdateOption(int id, string name) 49 | : base(id, name) 50 | { 51 | } 52 | 53 | public void Validate(T value) => Contract.Requires(value != null); 54 | 55 | public override bool Set(IUpdateConfiguration configuration, object value) => configuration.SetOption(this, (T)value); 56 | } 57 | 58 | public abstract class ConstantPool 59 | { 60 | private readonly Dictionary constants = new Dictionary(); 61 | private int nextId = 1; 62 | 63 | /// Shortcut of this.ValueOf(firstNameComponent.Name + "#" + secondNameComponent). 64 | public IConstant ValueOf(Type firstNameComponent, string secondNameComponent) 65 | { 66 | Contract.Requires(firstNameComponent != null); 67 | Contract.Requires(secondNameComponent != null); 68 | return this.ValueOf(firstNameComponent.Name + '#' + secondNameComponent); 69 | } 70 | 71 | /// 72 | /// Returns the which is assigned to the specified name. 73 | /// If there's no such , a new one will be created and returned. 74 | /// Once created, the subsequent calls with the same name will always return the previously created one 75 | /// (i.e. singleton.) 76 | /// 77 | /// the name of the 78 | public IConstant ValueOf(string name) 79 | { 80 | IConstant constant; 81 | lock (this.constants) 82 | { 83 | if (this.constants.TryGetValue(name, out constant)) 84 | { 85 | return constant; 86 | } 87 | else 88 | { 89 | constant = this.NewInstance0(name); 90 | } 91 | } 92 | return constant; 93 | } 94 | 95 | /// Returns true if a exists for the given name. 96 | public bool Exists(string name) 97 | { 98 | CheckNotNullAndNotEmpty(name); 99 | lock (this.constants) 100 | return this.constants.ContainsKey(name); 101 | } 102 | 103 | /// 104 | /// Creates a new for the given name or fail with an 105 | /// if a for the given name exists. 106 | /// 107 | public IConstant NewInstance(string name) 108 | { 109 | if (this.Exists(name)) throw new ArgumentException($"'{name}' is already in use"); 110 | IConstant constant = this.NewInstance0(name); 111 | return constant; 112 | } 113 | 114 | // Be careful that this dose not check whether the argument is null or empty. 115 | private IConstant NewInstance0(string name) 116 | { 117 | lock (this.constants) 118 | { 119 | IConstant constant = this.NewConstant(this.nextId, name); 120 | this.constants[name] = constant; 121 | this.nextId++; 122 | return constant; 123 | } 124 | } 125 | 126 | private static void CheckNotNullAndNotEmpty(string name) => Contract.Requires(!string.IsNullOrEmpty(name)); 127 | 128 | protected abstract IConstant NewConstant(int id, string name); 129 | 130 | [Obsolete] 131 | public int NextId() 132 | { 133 | lock (this.constants) 134 | { 135 | int id = this.nextId; 136 | this.nextId++; 137 | return id; 138 | } 139 | } 140 | } 141 | 142 | public interface IConstant 143 | { 144 | /// Returns the unique number assigned to this . 145 | int Id { get; } 146 | 147 | /// Returns the name of this . 148 | string Name { get; } 149 | } 150 | 151 | public interface IUpdateConfiguration 152 | { 153 | T GetOption(UpdateOption option); 154 | 155 | bool SetOption(UpdateOption option, object value); 156 | 157 | bool SetOption(UpdateOption option, T value); 158 | } 159 | 160 | public abstract class AbstractConstant : IConstant 161 | { 162 | private static long nextUniquifier; 163 | private long volatileUniquifier; 164 | 165 | protected AbstractConstant(int id, string name) 166 | { 167 | this.Id = id; 168 | this.Name = name; 169 | } 170 | 171 | public int Id { get; } 172 | 173 | public string Name { get; } 174 | 175 | public override sealed string ToString() => this.Name; 176 | 177 | protected long Uniquifier 178 | { 179 | get 180 | { 181 | long result; 182 | if ((result = Volatile.Read(ref this.volatileUniquifier)) == 0) 183 | { 184 | result = Interlocked.Increment(ref nextUniquifier); 185 | long previousUniquifier = Interlocked.CompareExchange(ref this.volatileUniquifier, result, 0); 186 | if (previousUniquifier != 0) result = previousUniquifier; 187 | } 188 | return result; 189 | } 190 | } 191 | } 192 | 193 | public abstract class AbstractConstant : AbstractConstant, IComparable, IEquatable 194 | where T : AbstractConstant 195 | { 196 | /// Creates a new instance. 197 | protected AbstractConstant(int id, string name) 198 | : base(id, name) { } 199 | 200 | public override sealed int GetHashCode() => base.GetHashCode(); 201 | 202 | public override sealed bool Equals(object obj) => base.Equals(obj); 203 | 204 | public bool Equals(T other) => ReferenceEquals(this, other); 205 | 206 | public int CompareTo(T o) 207 | { 208 | if (ReferenceEquals(this, o)) return 0; 209 | AbstractConstant other = o; 210 | int returnCode = this.GetHashCode() - other.GetHashCode(); 211 | if (returnCode != 0) return returnCode; 212 | long thisUV = this.Uniquifier; 213 | long otherUV = other.Uniquifier; 214 | if (thisUV < otherUV) return -1; 215 | if (thisUV > otherUV) return 1; 216 | throw new System.Exception("failed to compare two different constants"); 217 | } 218 | } 219 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/Bootstrap/UpdateOptionValue.cs: -------------------------------------------------------------------------------- 1 | namespace GeneralUpdate.Common.Internal.Bootstrap 2 | { 3 | public abstract class UpdateOptionValue 4 | { 5 | public abstract UpdateOption Option { get; } 6 | 7 | public abstract bool Set(IUpdateConfiguration config); 8 | 9 | public abstract object GetValue(); 10 | } 11 | 12 | public sealed class UpdateOptionValue : UpdateOptionValue 13 | { 14 | public override UpdateOption Option { get; } 15 | private readonly T value; 16 | 17 | public UpdateOptionValue(UpdateOption option, T value) 18 | { 19 | this.Option = option; 20 | this.value = value; 21 | } 22 | 23 | public override object GetValue() => this.value; 24 | 25 | public override bool Set(IUpdateConfiguration config) => config.SetOption(this.Option, this.value); 26 | 27 | public override string ToString() => this.value.ToString(); 28 | } 29 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/Event/EventManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | 5 | namespace GeneralUpdate.Common.Internal.Event 6 | { 7 | public class EventManager : IDisposable 8 | { 9 | private static readonly object _lockObj = new(); 10 | private static EventManager _instance; 11 | private Dictionary _dicDelegates = new(); 12 | private bool _disposed = false; 13 | 14 | private EventManager() { } 15 | 16 | public static EventManager Instance 17 | { 18 | get 19 | { 20 | if (_instance == null) 21 | { 22 | lock (_lockObj) 23 | { 24 | if (_instance == null) 25 | _instance = new EventManager(); 26 | } 27 | } 28 | return _instance; 29 | } 30 | } 31 | 32 | public void AddListener(Action listener) where TEventArgs : EventArgs 33 | { 34 | try 35 | { 36 | if (listener == null) throw new ArgumentNullException(nameof(listener)); 37 | var delegateType = typeof(Action); 38 | if (_dicDelegates.ContainsKey(delegateType)) 39 | { 40 | _dicDelegates[delegateType] = Delegate.Combine(_dicDelegates[delegateType], listener); 41 | } 42 | else 43 | { 44 | _dicDelegates.Add(delegateType, listener); 45 | } 46 | } 47 | catch (Exception e) 48 | { 49 | Debug.WriteLine(e); 50 | } 51 | } 52 | 53 | public void RemoveListener(Action listener) where TEventArgs : EventArgs 54 | { 55 | try 56 | { 57 | if (listener == null) throw new ArgumentNullException(nameof(listener)); 58 | var delegateType = typeof(Action); 59 | if (_dicDelegates.TryGetValue(delegateType, out var existingDelegate)) 60 | { 61 | _dicDelegates[delegateType] = Delegate.Remove(existingDelegate, listener); 62 | } 63 | } 64 | catch (Exception e) 65 | { 66 | Debug.WriteLine(e); 67 | } 68 | } 69 | 70 | public void Dispatch(object sender, TEventArgs eventArgs) where TEventArgs : EventArgs 71 | { 72 | try 73 | { 74 | if (sender == null) throw new ArgumentNullException(nameof(sender)); 75 | if (eventArgs == null) throw new ArgumentNullException(nameof(eventArgs)); 76 | var delegateType = typeof(Action); 77 | if (_dicDelegates.TryGetValue(delegateType, out var existingDelegate)) 78 | { 79 | ((Action)existingDelegate)?.Invoke(sender, eventArgs); 80 | } 81 | } 82 | catch (Exception e) 83 | { 84 | Debug.WriteLine(e); 85 | } 86 | } 87 | 88 | public void Clear() => _dicDelegates.Clear(); 89 | 90 | public void Dispose() 91 | { 92 | try 93 | { 94 | if (!this._disposed) 95 | { 96 | _dicDelegates.Clear(); 97 | _disposed = true; 98 | } 99 | } 100 | catch (Exception e) 101 | { 102 | Debug.WriteLine(e); 103 | } 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/Event/IEventManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GeneralUpdate.Common.Internal.Event 4 | { 5 | /// 6 | /// Event manager interface. 7 | /// 8 | public interface IEventManager 9 | { 10 | /// 11 | /// Adding Event Listeners. 12 | /// 13 | /// Generic delegate. 14 | /// New delegate that needs to be injected. 15 | void AddListener(TDelegate newDelegate) where TDelegate : Delegate; 16 | 17 | /// 18 | /// Removing Event Listening. 19 | /// 20 | /// Generic delegate. 21 | /// Need to remove an existing delegate. 22 | void RemoveListener(TDelegate oldDelegate) where TDelegate : Delegate; 23 | 24 | /// 25 | /// Triggers notifications of the same event type based on the listening event type. 26 | /// 27 | /// generic delegate. 28 | /// Event handler. 29 | /// Event args. 30 | void Dispatch(object sender, EventArgs eventArgs) where TDelegate : Delegate; 31 | 32 | /// 33 | /// Remove all injected delegates. 34 | /// 35 | void Clear(); 36 | } 37 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/Exception/ExceptionEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GeneralUpdate.Common.Internal; 4 | 5 | public class ExceptionEventArgs(Exception? exception = null, string? message = null) : EventArgs 6 | { 7 | public Exception Exception { get; private set; } = exception; 8 | public string Message { get; private set; } = message; 9 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/JsonContext/FileNodesJsonContext.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.Json.Serialization; 3 | using GeneralUpdate.Common.FileBasic; 4 | 5 | namespace GeneralUpdate.Common.Internal.JsonContext; 6 | 7 | [JsonSerializable(typeof(List))] 8 | public partial class FileNodesJsonContext : JsonSerializerContext; -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/JsonContext/GlobalConfigInfoOSSJsonContext.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | using GeneralUpdate.Common.Shared.Object; 3 | 4 | namespace GeneralUpdate.Common.Internal.JsonContext; 5 | 6 | [JsonSerializable(typeof(GlobalConfigInfoOSS))] 7 | public partial class GlobalConfigInfoOSSJsonContext : JsonSerializerContext; -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/JsonContext/HttpParameterJsonContext.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace GeneralUpdate.Common.Internal.JsonContext; 5 | 6 | [JsonSerializable(typeof(bool))] 7 | [JsonSerializable(typeof(bool?))] 8 | [JsonSerializable(typeof(int))] 9 | [JsonSerializable(typeof(int?))] 10 | [JsonSerializable(typeof(string))] 11 | [JsonSerializable(typeof(Dictionary))] 12 | public partial class HttpParameterJsonContext: JsonSerializerContext; -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/JsonContext/PacketJsonContext.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | using GeneralUpdate.Common.Shared.Object; 3 | 4 | namespace GeneralUpdate.Common.Internal.JsonContext; 5 | 6 | [JsonSerializable(typeof(Packet))] 7 | public partial class PacketJsonContext : JsonSerializerContext; -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/JsonContext/ProcessInfoJsonContext.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | using GeneralUpdate.Common.Shared.Object; 3 | 4 | namespace GeneralUpdate.Common.Internal.JsonContext; 5 | 6 | [JsonSerializable(typeof(ProcessInfo))] 7 | public partial class ProcessInfoJsonContext : JsonSerializerContext; -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/JsonContext/ReportRespJsonContext.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | using GeneralUpdate.Common.Shared.Object; 3 | 4 | namespace GeneralUpdate.Common.Internal.JsonContext; 5 | 6 | [JsonSerializable(typeof(BaseResponseDTO))] 7 | public partial class ReportRespJsonContext : JsonSerializerContext; -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/JsonContext/VersionOSSJsonContext.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.Json.Serialization; 3 | using GeneralUpdate.Common.Shared.Object; 4 | 5 | namespace GeneralUpdate.Common.Internal.JsonContext; 6 | 7 | [JsonSerializable(typeof(List))] 8 | public partial class VersionOSSJsonContext : JsonSerializerContext; -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/JsonContext/VersionRespJsonContext.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | using GeneralUpdate.Common.Shared.Object; 3 | 4 | namespace GeneralUpdate.Common.Internal.JsonContext; 5 | 6 | [JsonSerializable(typeof(VersionRespDTO))] 7 | public partial class VersionRespJsonContext : JsonSerializerContext; -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/Pipeline/IMiddleware.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace GeneralUpdate.Common.Internal.Pipeline 4 | { 5 | /// 6 | /// Pipeline middleware. 7 | /// 8 | public interface IMiddleware 9 | { 10 | Task InvokeAsync(PipelineContext context); 11 | } 12 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/Pipeline/PipelineBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Immutable; 3 | using System.Threading.Tasks; 4 | 5 | namespace GeneralUpdate.Common.Internal.Pipeline 6 | { 7 | /// 8 | /// Pipeline builder. 9 | /// 10 | public sealed class PipelineBuilder(PipelineContext context) 11 | { 12 | /// 13 | /// LIFO,Last In First Out. 14 | /// 15 | private ImmutableStack _middlewareStack = ImmutableStack.Empty; 16 | 17 | public PipelineBuilder UseMiddleware() where TMiddleware : IMiddleware, new() 18 | { 19 | var middleware = new TMiddleware(); 20 | _middlewareStack = _middlewareStack.Push(middleware); 21 | return this; 22 | } 23 | 24 | public PipelineBuilder UseMiddlewareIf(bool? condition) 25 | where TMiddleware : IMiddleware, new() 26 | { 27 | if (condition is null or false) 28 | return this; 29 | 30 | var middleware = new TMiddleware(); 31 | _middlewareStack = _middlewareStack.Push(middleware); 32 | return this; 33 | } 34 | 35 | public async Task Build() 36 | { 37 | foreach (var middleware in _middlewareStack) 38 | { 39 | await middleware.InvokeAsync(context); 40 | } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/Pipeline/PipelineContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | 4 | namespace GeneralUpdate.Common.Internal.Pipeline; 5 | 6 | public class PipelineContext 7 | { 8 | private ConcurrentDictionary _context = new(); 9 | 10 | public TValue? Get(string key) 11 | { 12 | if (_context.TryGetValue(key, out var value)) 13 | { 14 | return value is TValue typedValue ? typedValue : default; 15 | } 16 | return default; 17 | } 18 | 19 | public void Add(string key, TValue? value) 20 | { 21 | if (string.IsNullOrWhiteSpace(key)) 22 | { 23 | throw new ArgumentException("Key cannot be null or whitespace.", nameof(key)); 24 | } 25 | 26 | _context[key] = value; 27 | } 28 | 29 | public bool Remove(string key) => _context.TryRemove(key, out _); 30 | 31 | public bool ContainsKey(string key) => _context.ContainsKey(key); 32 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/Strategy/AbstractStrategy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Runtime.InteropServices; 5 | using System.Threading.Tasks; 6 | using GeneralUpdate.Common.FileBasic; 7 | using GeneralUpdate.Common.Shared.Object; 8 | 9 | namespace GeneralUpdate.Common.Internal.Strategy 10 | { 11 | public abstract class AbstractStrategy : IStrategy 12 | { 13 | protected const string Patchs = "patchs"; 14 | 15 | public virtual void Execute() => throw new NotImplementedException(); 16 | 17 | public virtual void StartApp() => throw new NotImplementedException(); 18 | 19 | public virtual Task ExecuteAsync() => throw new NotImplementedException(); 20 | 21 | public virtual void Create(GlobalConfigInfo parameter) => throw new NotImplementedException(); 22 | 23 | protected static void OpenBrowser(string url) 24 | { 25 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 26 | { 27 | Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") { CreateNoWindow = true }); 28 | return; 29 | } 30 | 31 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) 32 | { 33 | Process.Start("xdg-open", url); 34 | return; 35 | } 36 | 37 | throw new PlatformNotSupportedException("Unsupported OS platform"); 38 | } 39 | 40 | protected static void Clear(string path) 41 | { 42 | if (Directory.Exists(path)) 43 | StorageManager.DeleteDirectory(path); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Internal/Strategy/IStrategy.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using GeneralUpdate.Common.Shared.Object; 3 | 4 | namespace GeneralUpdate.Common.Internal.Strategy 5 | { 6 | /// 7 | /// Update the strategy, if you need to extend it, you need to inherit this interface. 8 | /// 9 | public interface IStrategy 10 | { 11 | /// 12 | /// Execution strategy. 13 | /// 14 | void Execute(); 15 | 16 | /// 17 | /// After the update is complete. 18 | /// 19 | void StartApp(); 20 | 21 | /// 22 | /// Execution strategy. 23 | /// 24 | Task ExecuteAsync(); 25 | 26 | /// 27 | /// Create a strategy. 28 | /// 29 | void Create(GlobalConfigInfo parameter); 30 | } 31 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Shared/Object/Configinfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace GeneralUpdate.Common.Shared.Object 5 | { 6 | /// 7 | /// Global update parameters. 8 | /// 9 | public class Configinfo 10 | { 11 | /// 12 | /// Update check api address. 13 | /// 14 | public string UpdateUrl { get; set; } 15 | 16 | /// 17 | /// API address for reporting update status. 18 | /// 19 | public string ReportUrl { get; set; } 20 | 21 | /// 22 | /// Need to start the name of the app. 23 | /// 24 | public string AppName { get; set; } 25 | 26 | /// 27 | /// The name of the main application, without .exe. 28 | /// 29 | public string MainAppName { get; set; } 30 | 31 | /// 32 | /// Update log web address. 33 | /// 34 | public string UpdateLogUrl { get; set; } 35 | 36 | /// 37 | /// application key 38 | /// 39 | public string AppSecretKey { get; set; } 40 | 41 | /// 42 | /// Client current version. 43 | /// 44 | public string ClientVersion { get; set; } 45 | 46 | /// 47 | /// Upgrade Client current version. 48 | /// 49 | public string UpgradeClientVersion { get; set; } 50 | 51 | /// 52 | /// installation path (for update file logic). 53 | /// 54 | public string InstallPath { get; set; } 55 | 56 | /// 57 | /// Files in the blacklist will skip the update. 58 | /// 59 | public List BlackFiles { get; set; } 60 | 61 | /// 62 | /// File formats in the blacklist will skip the update. 63 | /// 64 | public List BlackFormats { get; set; } 65 | 66 | /// 67 | /// SkipDirectorys 68 | /// 69 | public List SkipDirectorys { get; set; } 70 | 71 | /// 72 | /// Product ID. 73 | /// 74 | public string ProductId { get; set; } 75 | 76 | public string Bowl { get; set; } 77 | 78 | public string Scheme { get; set; } 79 | 80 | public string Token { get; set; } 81 | 82 | public void Validate() 83 | { 84 | if (string.IsNullOrWhiteSpace(UpdateUrl) || !Uri.IsWellFormedUriString(UpdateUrl, UriKind.Absolute)) 85 | throw new ArgumentException("Invalid UpdateUrl"); 86 | 87 | if (!string.IsNullOrWhiteSpace(UpdateLogUrl) && !Uri.IsWellFormedUriString(UpdateLogUrl, UriKind.Absolute)) 88 | throw new ArgumentException("Invalid UpdateLogUrl"); 89 | 90 | if (string.IsNullOrWhiteSpace(AppName)) 91 | throw new ArgumentException("AppName cannot be empty"); 92 | 93 | if (string.IsNullOrWhiteSpace(MainAppName)) 94 | throw new ArgumentException("MainAppName cannot be empty"); 95 | 96 | if (string.IsNullOrWhiteSpace(AppSecretKey)) 97 | throw new ArgumentException("AppSecretKey cannot be empty"); 98 | 99 | if (string.IsNullOrWhiteSpace(ClientVersion)) 100 | throw new ArgumentException("ClientVersion cannot be empty"); 101 | 102 | if (string.IsNullOrWhiteSpace(InstallPath)) 103 | throw new ArgumentException("InstallPath cannot be empty"); 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Shared/Object/DTO/BaseResponseDTO.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace GeneralUpdate.Common.Shared.Object 4 | { 5 | public class BaseResponseDTO 6 | { 7 | [JsonPropertyName("code")] 8 | public int Code { get; set; } 9 | 10 | [JsonPropertyName("body")] 11 | public TBody Body { get; set; } 12 | 13 | [JsonPropertyName("message")] 14 | public string Message { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Shared/Object/DTO/VersionRespDTO.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace GeneralUpdate.Common.Shared.Object; 4 | public class VersionRespDTO : BaseResponseDTO>; -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Shared/Object/Enum/AppType.cs: -------------------------------------------------------------------------------- 1 | namespace GeneralUpdate.Common.Shared.Object 2 | { 3 | public class AppType 4 | { 5 | /// 6 | /// main program 7 | /// 8 | public const int ClientApp = 1; 9 | 10 | /// 11 | /// upgrade program. 12 | /// 13 | public const int UpgradeApp = 2; 14 | } 15 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Shared/Object/Enum/Format.cs: -------------------------------------------------------------------------------- 1 | namespace GeneralUpdate.Common.Shared.Object 2 | { 3 | public class Format 4 | { 5 | public const string ZIP = ".zip"; 6 | } 7 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Shared/Object/Enum/PlatformType.cs: -------------------------------------------------------------------------------- 1 | namespace GeneralUpdate.Common.Shared.Object.Enum; 2 | 3 | public class PlatformType 4 | { 5 | public const int Windows = 1; 6 | 7 | public const int Linux = 2; 8 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Shared/Object/Enum/ReportType.cs: -------------------------------------------------------------------------------- 1 | namespace GeneralUpdate.Common.Shared.Object.Enum; 2 | 3 | public class ReportType 4 | { 5 | public const int None = 0; 6 | 7 | public const int Success = 2; 8 | 9 | public const int Failure = 3; 10 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Shared/Object/GlobalConfigInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text; 3 | 4 | namespace GeneralUpdate.Common.Shared.Object; 5 | 6 | public class GlobalConfigInfo 7 | { 8 | /// 9 | /// Update check api address. 10 | /// 11 | public string UpdateUrl { get; set; } 12 | 13 | /// 14 | /// API address for reporting update status. 15 | /// 16 | public string ReportUrl { get; set; } 17 | 18 | /// 19 | /// Need to start the name of the app. 20 | /// 21 | public string AppName { get; set; } 22 | 23 | /// 24 | /// The name of the main application, without .exe. 25 | /// 26 | public string MainAppName { get; set; } 27 | 28 | /// 29 | /// Update package file format(Defult format is Zip). 30 | /// 31 | public string Format { get; set; } 32 | 33 | /// 34 | /// Whether an update is required to upgrade the application. 35 | /// 36 | public bool IsUpgradeUpdate { get; set; } 37 | 38 | /// 39 | /// Whether the main application needs to be updated. 40 | /// 41 | public bool IsMainUpdate { get; set; } 42 | 43 | /// 44 | /// Update log web address. 45 | /// 46 | public string UpdateLogUrl { get; set; } 47 | 48 | /// 49 | /// Version information that needs to be updated. 50 | /// 51 | public List UpdateVersions { get; set; } 52 | 53 | /// 54 | /// The encoding format for file operations. 55 | /// 56 | public Encoding Encoding { get; set; } 57 | 58 | /// 59 | /// Time-out event for file download. 60 | /// 61 | public int DownloadTimeOut { get; set; } 62 | 63 | /// 64 | /// application key 65 | /// 66 | public string AppSecretKey { get; set; } 67 | 68 | /// 69 | /// Client current version. 70 | /// 71 | public string ClientVersion { get; set; } 72 | 73 | /// 74 | /// Upgrade Client current version. 75 | /// 76 | public string UpgradeClientVersion { get; set; } 77 | 78 | /// 79 | /// The main program latest version. 80 | /// 81 | public string LastVersion { get; set; } 82 | 83 | /// 84 | /// installation path (for update file logic). 85 | /// 86 | public string InstallPath { get; set; } 87 | 88 | /// 89 | /// Download file temporary storage path (for update file logic). 90 | /// 91 | public string TempPath { get; set; } 92 | 93 | /// 94 | /// Configuration parameters for upgrading the terminal program. 95 | /// 96 | public string ProcessInfo { get; set; } 97 | 98 | /// 99 | /// Files in the blacklist will skip the update. 100 | /// 101 | public List BlackFiles { get; set; } 102 | 103 | /// 104 | /// File formats in the blacklist will skip the update. 105 | /// 106 | public List BlackFormats { get; set; } 107 | 108 | /// 109 | /// SkipDirectorys 110 | /// 111 | public List SkipDirectorys { get; set; } 112 | 113 | /// 114 | /// Whether to enable the driver upgrade function. 115 | /// 116 | public bool? DriveEnabled { get; set; } 117 | 118 | public string ProductId { get; set; } 119 | 120 | public Dictionary FieldMappings { get; set; } 121 | 122 | public string BackupDirectory { get; set; } 123 | 124 | public string Bowl { get; set; } 125 | 126 | public string Scheme { get; set; } 127 | 128 | public string Token { get; set; } 129 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Shared/Object/GlobalConfigInfoOSS.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace GeneralUpdate.Common.Shared.Object 5 | { 6 | public class GlobalConfigInfoOSS 7 | { 8 | [JsonPropertyName("Url")] 9 | public string Url { get; set; } 10 | 11 | [JsonPropertyName("AppName")] 12 | public string AppName { get; set; } 13 | 14 | [JsonPropertyName("CurrentVersion")] 15 | public string CurrentVersion { get; set; } 16 | 17 | [JsonPropertyName("VersionFileName")] 18 | public string VersionFileName { get; set; } 19 | 20 | [JsonPropertyName("Encoding")] 21 | public string Encoding { get; set; } 22 | 23 | public GlobalConfigInfoOSS() 24 | { 25 | } 26 | 27 | public GlobalConfigInfoOSS(string url, string appName, string currentVersion, string versionFileName) 28 | { 29 | Url = url ?? throw new ArgumentNullException(nameof(url)); 30 | AppName = appName ?? throw new ArgumentNullException(nameof(appName)); 31 | CurrentVersion = currentVersion ?? throw new ArgumentNullException(nameof(currentVersion)); 32 | VersionFileName = versionFileName ?? "versions.json"; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Shared/Object/Packet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace GeneralUpdate.Common.Shared.Object; 5 | 6 | /// 7 | /// Currently used only for upgrade push. 8 | /// 9 | public class Packet 10 | { 11 | [JsonPropertyName("Name")] 12 | public string? Name { get; set; } 13 | 14 | [JsonPropertyName("Hash")] 15 | public string Hash { get; set; } 16 | 17 | [JsonPropertyName("ReleaseDate")] 18 | public DateTime? ReleaseDate { get; set; } 19 | 20 | [JsonPropertyName("Url")] 21 | public string? Url { get; set; } 22 | 23 | [JsonPropertyName("Version")] 24 | public string? Version { get; set; } 25 | 26 | [JsonPropertyName("AppType")] 27 | public int? AppType { get; set; } 28 | 29 | [JsonPropertyName("Platform")] 30 | public int? Platform { get; set; } 31 | 32 | [JsonPropertyName("ProductId")] 33 | public string? ProductId { get; set; } 34 | 35 | [JsonPropertyName("IsForcibly")] 36 | public bool? IsForcibly { get; set; } 37 | 38 | [JsonPropertyName("IsFreeze")] 39 | public bool? IsFreeze { get; set; } 40 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Shared/Object/ProcessInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | using System.Text.Json.Serialization; 6 | 7 | namespace GeneralUpdate.Common.Shared.Object 8 | { 9 | public class ProcessInfo 10 | { 11 | public ProcessInfo() { } 12 | 13 | public ProcessInfo(string appName 14 | , string installPath 15 | , string currentVersion 16 | , string lastVersion 17 | , string updateLogUrl 18 | , Encoding compressEncoding 19 | , string compressFormat 20 | , int downloadTimeOut 21 | , string appSecretKey 22 | , List updateVersions 23 | , string reportUrl 24 | , string backupDirectory 25 | , string bowl 26 | , string scheme 27 | , string token 28 | , List blackFileFormats 29 | , List blackFiles 30 | , List skipDirectories) 31 | { 32 | AppName = appName ?? throw new ArgumentNullException(nameof(appName)); 33 | if (!Directory.Exists(installPath)) throw new ArgumentException($"{nameof(installPath)} path does not exist ! {installPath}."); 34 | InstallPath = installPath ?? throw new ArgumentNullException(nameof(installPath)); 35 | CurrentVersion = currentVersion ?? throw new ArgumentNullException(nameof(currentVersion)); 36 | LastVersion = lastVersion ?? throw new ArgumentNullException(nameof(lastVersion)); 37 | UpdateLogUrl = updateLogUrl; 38 | CompressEncoding = compressEncoding.WebName; 39 | CompressFormat = compressFormat; 40 | if (downloadTimeOut < 0) throw new ArgumentException("Timeout must be greater than 0 !"); 41 | DownloadTimeOut = downloadTimeOut; 42 | AppSecretKey = appSecretKey ?? throw new ArgumentNullException(nameof(appSecretKey)); 43 | if (updateVersions == null || updateVersions.Count == 0) throw new ArgumentException("Collection cannot be null or has 0 elements !"); 44 | UpdateVersions = updateVersions; 45 | ReportUrl = reportUrl ?? throw new ArgumentNullException(nameof(reportUrl)); 46 | BackupDirectory = backupDirectory ?? throw new ArgumentNullException(nameof(backupDirectory)); 47 | Bowl = bowl; 48 | Scheme = scheme; 49 | Token = token; 50 | BlackFileFormats = blackFileFormats; 51 | BlackFiles = blackFiles; 52 | SkipDirectorys = skipDirectories; 53 | } 54 | 55 | /// 56 | /// Need to start the name of the app. 57 | /// 58 | [JsonPropertyName("AppName")] 59 | public string AppName { get; set; } 60 | 61 | /// 62 | /// Installation directory (the path where the update package is decompressed). 63 | /// 64 | [JsonPropertyName("InstallPath")] 65 | public string InstallPath { get; set; } 66 | 67 | /// 68 | /// Current version. 69 | /// 70 | [JsonPropertyName("CurrentVersion")] 71 | public string CurrentVersion { get; set; } 72 | 73 | /// 74 | /// The version of the last update. 75 | /// 76 | [JsonPropertyName("LastVersion")] 77 | public string LastVersion { get; set; } 78 | 79 | /// 80 | /// Update log web address. 81 | /// 82 | [JsonPropertyName("UpdateLogUrl")] 83 | public string UpdateLogUrl { get; set; } 84 | 85 | /// 86 | /// The encoding type of the update package. 87 | /// 88 | [JsonPropertyName("CompressEncoding")] 89 | public string CompressEncoding { get; set; } 90 | 91 | /// 92 | /// The compression format of the update package. 93 | /// 94 | [JsonPropertyName("CompressFormat")] 95 | public string CompressFormat { get; set; } 96 | 97 | /// 98 | /// The timeout of the download. 99 | /// 100 | [JsonPropertyName("DownloadTimeOut")] 101 | public int DownloadTimeOut { get; set; } 102 | 103 | /// 104 | /// application key 105 | /// 106 | [JsonPropertyName("AppSecretKey")] 107 | public string AppSecretKey { get; set; } 108 | 109 | /// 110 | /// One or more version update information. 111 | /// 112 | [JsonPropertyName("UpdateVersions")] 113 | public List UpdateVersions { get; set; } 114 | 115 | /// 116 | /// update report web address 117 | /// 118 | [JsonPropertyName("ReportUrl")] 119 | public string ReportUrl { get; set; } 120 | 121 | /// 122 | /// Back up the current version files that have not been updated. 123 | /// 124 | [JsonPropertyName("BackupDirectory")] 125 | public string BackupDirectory { get; set; } 126 | 127 | [JsonPropertyName("Bowl")] 128 | public string Bowl { get; set; } 129 | 130 | [JsonPropertyName("Scheme")] 131 | public string Scheme { get; set; } 132 | 133 | [JsonPropertyName("Token")] 134 | public string Token { get; set; } 135 | 136 | [JsonPropertyName("BlackFileFormats")] 137 | public List BlackFileFormats { get; set; } 138 | 139 | [JsonPropertyName("BlackFiles")] 140 | public List BlackFiles { get; set; } 141 | 142 | [JsonPropertyName("SkipDirectorys")] 143 | public List SkipDirectorys { get; set; } 144 | } 145 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Shared/Object/VersionInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace GeneralUpdate.Common.Shared.Object; 5 | 6 | public class VersionInfo 7 | { 8 | [JsonPropertyName("recordId")] 9 | public int RecordId { get; set; } 10 | 11 | [JsonPropertyName("name")] 12 | public string? Name { get; set; } 13 | 14 | [JsonPropertyName("hash")] 15 | public string? Hash { get; set; } 16 | 17 | [JsonPropertyName("releaseDate")] 18 | public DateTime? ReleaseDate { get; set; } 19 | 20 | [JsonPropertyName("url")] 21 | public string? Url { get; set; } 22 | 23 | [JsonPropertyName("version")] 24 | public string? Version { get; set; } 25 | 26 | [JsonPropertyName("appType")] 27 | public int? AppType { get; set; } 28 | 29 | [JsonPropertyName("platform")] 30 | public int? Platform { get; set; } 31 | 32 | [JsonPropertyName("productId")] 33 | public string? ProductId { get; set; } 34 | 35 | [JsonPropertyName("isForcibly")] 36 | public bool? IsForcibly { get; set; } 37 | 38 | [JsonPropertyName("format")] 39 | public string? Format { get; set; } 40 | 41 | [JsonPropertyName("size")] 42 | public long? Size { get; set; } 43 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Shared/Object/VersionOSS.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace GeneralUpdate.Common.Shared.Object 5 | { 6 | /// 7 | /// Version data persistence. 8 | /// 9 | public class VersionOSS 10 | { 11 | /// 12 | /// Update package release time. 13 | /// 14 | 15 | [JsonPropertyName("PubTime")] 16 | public DateTime PubTime { get; set; } 17 | 18 | /// 19 | /// Update package name. 20 | /// 21 | [JsonPropertyName("PacketName")] 22 | public string PacketName { get; set; } 23 | 24 | /// 25 | /// Compare and verify with the downloaded update package. 26 | /// 27 | [JsonPropertyName("Hash")] 28 | public string Hash { get; set; } 29 | 30 | /// 31 | /// The version number. 32 | /// 33 | [JsonPropertyName("Version")] 34 | public string Version { get; set; } 35 | 36 | /// 37 | /// Remote service url address. 38 | /// 39 | [JsonPropertyName("Url")] 40 | public string Url { get; set; } 41 | } 42 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Common/Shared/Service/VersionService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Net.Http; 5 | using System.Security.Cryptography.X509Certificates; 6 | using System.Net.Security; 7 | using System.Text; 8 | using System.Text.Json; 9 | using System.Text.Json.Serialization.Metadata; 10 | using System.Threading.Tasks; 11 | using GeneralUpdate.Common.Internal.JsonContext; 12 | using GeneralUpdate.Common.Shared.Object; 13 | 14 | namespace GeneralUpdate.Common.Shared.Service 15 | { 16 | public class VersionService 17 | { 18 | private VersionService() { } 19 | 20 | /// 21 | /// Report the result of this update: whether it was successful. 22 | /// 23 | /// 24 | /// 25 | /// 26 | /// 27 | /// 28 | public static async Task Report(string httpUrl 29 | , int recordId 30 | , int status 31 | , int? type 32 | , string scheme = null 33 | , string token = null) 34 | { 35 | var parameters = new Dictionary 36 | { 37 | { "RecordId", recordId }, 38 | { "Status", status }, 39 | { "Type", type } 40 | }; 41 | await PostTaskAsync>(httpUrl, parameters, ReportRespJsonContext.Default.BaseResponseDTOBoolean, scheme, token); 42 | } 43 | 44 | /// 45 | /// Verify whether the current version needs an update. 46 | /// 47 | /// 48 | /// 49 | /// 50 | /// 51 | /// 52 | /// 53 | /// 54 | public static async Task Validate(string httpUrl 55 | , string version 56 | , int appType 57 | , string appKey 58 | , int platform 59 | , string productId 60 | , string scheme = null 61 | , string token = null) 62 | { 63 | var parameters = new Dictionary 64 | { 65 | { "Version", version }, 66 | { "AppType", appType }, 67 | { "AppKey", appKey }, 68 | { "Platform", platform }, 69 | { "ProductId", productId } 70 | }; 71 | return await PostTaskAsync(httpUrl, parameters, VersionRespJsonContext.Default.VersionRespDTO, scheme, token); 72 | } 73 | 74 | private static async Task PostTaskAsync(string httpUrl, Dictionary parameters, JsonTypeInfo? typeInfo = null, string scheme = null, string token = null) 75 | { 76 | try 77 | { 78 | var uri = new Uri(httpUrl); 79 | using var httpClient = new HttpClient(new HttpClientHandler 80 | { 81 | ServerCertificateCustomValidationCallback = CheckValidationResult 82 | }); 83 | httpClient.Timeout = TimeSpan.FromSeconds(15); 84 | httpClient.DefaultRequestHeaders.Accept.ParseAdd("text/html, application/xhtml+xml, */*"); 85 | 86 | if (!string.IsNullOrEmpty(scheme) && !string.IsNullOrEmpty(token)) 87 | { 88 | httpClient.DefaultRequestHeaders.Authorization = 89 | new System.Net.Http.Headers.AuthenticationHeaderValue(scheme, token); 90 | } 91 | 92 | var parametersJson = 93 | JsonSerializer.Serialize(parameters, HttpParameterJsonContext.Default.DictionaryStringObject); 94 | var stringContent = new StringContent(parametersJson, Encoding.UTF8, "application/json"); 95 | var result = await httpClient.PostAsync(uri, stringContent); 96 | var reseponseJson = await result.Content.ReadAsStringAsync(); 97 | return typeInfo == null 98 | ? JsonSerializer.Deserialize(reseponseJson) 99 | : JsonSerializer.Deserialize(reseponseJson, typeInfo); 100 | } 101 | catch (Exception e) 102 | { 103 | Debug.WriteLine(e.Message); 104 | throw; 105 | } 106 | } 107 | 108 | private static bool CheckValidationResult( 109 | HttpRequestMessage message, 110 | X509Certificate2 certificate, 111 | X509Chain chain, 112 | SslPolicyErrors sslPolicyErrors 113 | ) => true; 114 | } 115 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Common/git.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/src/c#/GeneralUpdate.Core/Common/git.keep -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Driver/BackupDriverCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using GeneralUpdate.Common.FileBasic; 8 | 9 | namespace GeneralUpdate.Core.Driver 10 | { 11 | /// 12 | /// When the /export-driver command backs up a driver, it backs up the driver package along with all its dependencies, such as associated library files and other related files. 13 | /// 14 | public class BackupDriverCommand(DriverInformation information) : DriverCommand 15 | { 16 | private readonly string _driverExtension = $"*{information.DriverFileExtension}"; 17 | 18 | public override void Execute() 19 | { 20 | var uninstalledDrivers = Directory.GetFiles(information.DriverDirectory, _driverExtension, SearchOption.AllDirectories).ToList(); 21 | var installedDrivers = GetInstalledDrivers(information.FieldMappings); 22 | var tempDrivers = installedDrivers.Where(a => uninstalledDrivers.Any(b => string.Equals(a.OriginalName, Path.GetFileName(b)))).ToList(); 23 | information.Drivers = tempDrivers; 24 | 25 | //Export the backup according to the driver name. 26 | if (Directory.Exists(information.OutPutDirectory)) 27 | { 28 | StorageManager.DeleteDirectory(information.OutPutDirectory); 29 | } 30 | 31 | Directory.CreateDirectory(information.OutPutDirectory); 32 | 33 | /* 34 | * Back up the specified list of drives. 35 | */ 36 | foreach (var driver in tempDrivers) 37 | { 38 | /* 39 | * If no test driver files are available, you can run the following command to export all installed driver files. 40 | * (1) dism /online /export-driver /destination:"D:\packet\cache\" 41 | * (2) pnputil /export-driver * D:\packet\cache 42 | * 43 | * The following code example exports the specified driver to the specified directory. 44 | * pnputil /export-driver oemXX.inf D:\packet\cache 45 | */ 46 | var path = Path.Combine(information.OutPutDirectory, driver.PublishedName); 47 | var command = new StringBuilder("/c pnputil /export-driver ") 48 | .Append(driver.PublishedName) 49 | .Append(' ') 50 | .Append(path) 51 | .ToString(); 52 | 53 | if (!Directory.Exists(path)) 54 | { 55 | Directory.CreateDirectory(path); 56 | } 57 | 58 | CommandExecutor.ExecuteCommand(command); 59 | } 60 | } 61 | 62 | private IEnumerable GetInstalledDrivers(Dictionary fieldMappings) 63 | { 64 | var drivers = new List(); 65 | var process = new Process(); 66 | process.StartInfo.FileName = "pnputil"; 67 | process.StartInfo.Arguments = "/enum-drivers"; 68 | process.StartInfo.RedirectStandardOutput = true; 69 | process.StartInfo.UseShellExecute = false; 70 | process.StartInfo.CreateNoWindow = true; 71 | process.Start(); 72 | 73 | var output = process.StandardOutput.ReadToEnd(); 74 | process.WaitForExit(); 75 | 76 | var lines = output.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); 77 | 78 | DriverInfo currentDriver = null; 79 | foreach (var line in lines) 80 | { 81 | if (line.StartsWith(fieldMappings["PublishedName"])) 82 | { 83 | if (currentDriver != null) 84 | { 85 | drivers.Add(currentDriver); 86 | } 87 | currentDriver = new (); 88 | currentDriver.PublishedName = line.Split(new[] { ':' }, 2)[1].Trim(); 89 | } 90 | else if (line.StartsWith(fieldMappings["OriginalName"]) && currentDriver != null) 91 | { 92 | currentDriver.OriginalName = line.Split(new[] { ':' }, 2)[1].Trim(); 93 | } 94 | else if (line.StartsWith(fieldMappings["Provider"]) && currentDriver != null) 95 | { 96 | currentDriver.Provider = line.Split(new[] { ':' }, 2)[1].Trim(); 97 | } 98 | else if (line.StartsWith(fieldMappings["ClassName"]) && currentDriver != null) 99 | { 100 | currentDriver.ClassName = line.Split(new[] { ':' }, 2)[1].Trim(); 101 | } 102 | else if (line.StartsWith(fieldMappings["ClassGUID"]) && currentDriver != null) 103 | { 104 | currentDriver.ClassGUID = line.Split(new[] { ':' }, 2)[1].Trim(); 105 | } 106 | else if (line.StartsWith(fieldMappings["Version"]) && currentDriver != null) 107 | { 108 | currentDriver.Version = line.Split(new[] { ':' }, 2)[1].Trim(); 109 | } 110 | else if (line.StartsWith(fieldMappings["Signer"]) && currentDriver != null) 111 | { 112 | currentDriver.Signer = line.Split(new[] { ':' }, 2)[1].Trim(); 113 | } 114 | } 115 | 116 | if (currentDriver != null) 117 | { 118 | drivers.Add(currentDriver); 119 | } 120 | 121 | return drivers; 122 | } 123 | } 124 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Driver/CommandExecutor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace GeneralUpdate.Core.Driver 5 | { 6 | /// 7 | /// When the process starts, PnPUtil is used to execute driver processing commands. 8 | /// 9 | public class CommandExecutor 10 | { 11 | private CommandExecutor() 12 | { } 13 | 14 | public static void ExecuteCommand(string command) 15 | { 16 | /* 17 | * 18 | *Problems may occur, including: 19 | Permission issues: PnPUtil requires administrator rights to run. If you try to run it without the proper permissions, the backup or restore may fail. 20 | Driver compatibility: Although the backed up drivers work properly at backup time, if the operating system is upgraded, the backed up drivers may no longer be compatible with the new operating system version. 21 | Hardware problems: If the hardware device fails or the hardware configuration changes, the backup driver may not work properly. 22 | 23 | To minimize these risks, the following measures are recommended: 24 | Before doing anything, create a system restore point so that it can be restored to its previous state if something goes wrong. 25 | Update the driver regularly to ensure that the driver is compatible with the current operating system version. 26 | If possible, use pre-tested drivers that are proven to work. 27 | * 28 | */ 29 | var processStartInfo = new ProcessStartInfo 30 | { 31 | WindowStyle = ProcessWindowStyle.Hidden, 32 | FileName = "cmd.exe", 33 | Arguments = command, 34 | UseShellExecute = false, 35 | RedirectStandardOutput = true, 36 | RedirectStandardError = true, 37 | Verb = "runas" 38 | }; 39 | 40 | var process = new Process(); 41 | try 42 | { 43 | process.StartInfo = processStartInfo; 44 | process.Start(); 45 | process.WaitForExit(); 46 | 47 | var output = process.StandardOutput.ReadToEnd(); 48 | Debug.WriteLine(output); 49 | 50 | var error = process.StandardError.ReadToEnd(); 51 | if (!string.IsNullOrEmpty(error)) 52 | { 53 | Debug.WriteLine("Error: " + error); 54 | } 55 | 56 | if (process.ExitCode != 0) 57 | throw new ApplicationException($"Operation failed code: {process.ExitCode}"); 58 | } 59 | finally 60 | { 61 | process.Dispose(); 62 | } 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Driver/DeleteDriverCommand.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace GeneralUpdate.Core.Driver; 4 | 5 | public class DeleteDriverCommand(DriverInformation information) : DriverCommand 6 | { 7 | public override void Execute() 8 | { 9 | //Before installing the driver, delete the driver that has been installed on the local system. Otherwise, an exception may occur. 10 | foreach (var driver in information.Drivers) 11 | { 12 | var command = new StringBuilder("/c pnputil /delete-driver ") 13 | .Append(driver.PublishedName) 14 | .ToString(); 15 | CommandExecutor.ExecuteCommand(command); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Driver/DriverCommand.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Linq; 4 | using GeneralUpdate.Common.FileBasic; 5 | 6 | namespace GeneralUpdate.Core.Driver 7 | { 8 | public abstract class DriverCommand 9 | { 10 | public abstract void Execute(); 11 | 12 | /// 13 | /// Search for driver files. 14 | /// 15 | /// 16 | /// 17 | protected static IEnumerable SearchDrivers(string patchPath, string fileExtension) 18 | { 19 | var files = StorageManager.GetAllFiles(patchPath, BlackListManager.Instance.SkipDirectorys.ToList()); 20 | return files.Where(x => x.FullName.EndsWith(fileExtension)).ToList(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Driver/DriverInfo.cs: -------------------------------------------------------------------------------- 1 | namespace GeneralUpdate.Core.Driver; 2 | 3 | public class DriverInfo 4 | { 5 | public string PublishedName { get; set; } 6 | public string OriginalName { get; set; } 7 | public string Provider { get; set; } 8 | public string ClassName { get; set; } 9 | public string ClassGUID { get; set; } 10 | public string Version { get; set; } 11 | public string Signer { get; set; } 12 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Driver/DriverInformation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace GeneralUpdate.Core.Driver 5 | { 6 | /// 7 | /// Driver information object. 8 | /// 9 | public class DriverInformation 10 | { 11 | public Dictionary FieldMappings { get; private set; } 12 | 13 | public string DriverFileExtension { get; private set; } 14 | 15 | /// 16 | /// All driver backup directories. 17 | /// 18 | public string OutPutDirectory { get; private set; } 19 | 20 | public string DriverDirectory { get; private set; } 21 | 22 | /// 23 | /// A collection of driver files to be backed up. 24 | /// 25 | public IEnumerable Drivers { get; set; } 26 | 27 | private DriverInformation() 28 | { } 29 | 30 | public class Builder 31 | { 32 | private DriverInformation _information = new (); 33 | 34 | public Builder SetDriverFileExtension(string fileExtension) 35 | { 36 | _information.DriverFileExtension = fileExtension; 37 | return this; 38 | } 39 | 40 | public Builder SetOutPutDirectory(string outPutDirectory) 41 | { 42 | _information.OutPutDirectory = outPutDirectory; 43 | return this; 44 | } 45 | 46 | public Builder SetDriverDirectory(string driverDirectory) 47 | { 48 | _information.DriverDirectory = driverDirectory; 49 | return this; 50 | } 51 | 52 | public Builder SetFieldMappings(Dictionary fieldMappings) 53 | { 54 | _information.FieldMappings = fieldMappings; 55 | return this; 56 | } 57 | 58 | public DriverInformation Build() 59 | { 60 | if (string.IsNullOrWhiteSpace(_information.OutPutDirectory) || 61 | string.IsNullOrWhiteSpace(_information.DriverFileExtension)) 62 | { 63 | throw new ArgumentNullException("Cannot create DriverInformation, not all fields are set."); 64 | } 65 | 66 | return _information; 67 | } 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Driver/DriverProcessor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace GeneralUpdate.Core.Driver 5 | { 6 | /// 7 | /// Handle all drive-related. 8 | /// 9 | public class DriverProcessor 10 | { 11 | private readonly List _commands = new (); 12 | 13 | public void AddCommand(DriverCommand command) => _commands.Add(command); 14 | 15 | /// 16 | /// Execute all driver-related commands. 17 | /// 18 | public void ProcessCommands() 19 | { 20 | if (!_commands.Any()) return; 21 | 22 | /* 23 | * This section describes the PnPUtil command. 24 | * https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/pnputil-command-syntax 25 | */ 26 | foreach (var command in _commands) 27 | { 28 | command.Execute(); 29 | } 30 | _commands.Clear(); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Driver/InstallDriverCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text; 4 | 5 | namespace GeneralUpdate.Core.Driver 6 | { 7 | /// 8 | /// Install the new driver, and if the installation fails, the backup is automatically restored. 9 | /// 10 | public class InstallDriverCommand(DriverInformation information) : DriverCommand 11 | { 12 | public override void Execute() 13 | { 14 | foreach (var driver in information.Drivers) 15 | { 16 | try 17 | { 18 | /* 19 | * 1.It is best to ensure that the installed file is OEM INF, otherwise PnPUtil may indicate that non-OEM INF cannot perform the current operation. 20 | * 21 | * 2.Before installation, you need to delete the previously installed driver, otherwise PnPUtil will prompt 259 to exit the code. 22 | * (On Windows, an ExitCode value of 259 (STILL_ACTIVE) means that the process is still running) 23 | * If you do not remove the previous installation 259 prompt will give you a misleading impression of what is running. 24 | */ 25 | var path = Path.Combine(information.DriverDirectory, driver.OriginalName); 26 | var command = new StringBuilder("/c pnputil /add-driver ") 27 | .Append(path) 28 | .Append(" /install") 29 | .ToString(); 30 | CommandExecutor.ExecuteCommand(command); 31 | } 32 | catch (Exception ex) 33 | { 34 | //restore all the drivers in the backup directory. 35 | new RestoreDriverCommand(information).Execute(); 36 | throw new ApplicationException($"Failed to execute driver command: {ex.Message}, details: {ex} !"); 37 | } 38 | } 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Driver/RestoreDriverCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Text; 4 | using GeneralUpdate.Common.FileBasic; 5 | 6 | namespace GeneralUpdate.Core.Driver 7 | { 8 | public class RestoreDriverCommand(DriverInformation information) 9 | { 10 | public void Execute() 11 | { 12 | try 13 | { 14 | var backupFiles = StorageManager.GetAllFiles(information.OutPutDirectory, BlackListManager.Instance.SkipDirectorys.ToList()); 15 | var fileExtension = information.DriverFileExtension; 16 | var drivers = backupFiles.Where(x => x.FullName.EndsWith(fileExtension)).ToList(); 17 | 18 | foreach (var driver in drivers) 19 | { 20 | try 21 | { 22 | //Install all drivers in the specified directory, and if the installation fails, restore all the drivers in the backup directory. 23 | var command = new StringBuilder("/c pnputil /add-driver ") 24 | .Append(driver.FullName) 25 | .Append(" /install") 26 | .ToString(); 27 | CommandExecutor.ExecuteCommand(command); 28 | } 29 | catch (Exception e) 30 | { 31 | throw new ApplicationException($"Failed to execute install command for {driver.FullName}, error: {e.Message} !"); 32 | } 33 | } 34 | } 35 | catch 36 | { 37 | throw new ApplicationException($"Failed to execute restore command for {information.OutPutDirectory}"); 38 | } 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/GeneralUpdate.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/src/c#/GeneralUpdate.Core/GeneralUpdate.ico -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/GeneralUpdate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/src/c#/GeneralUpdate.Core/GeneralUpdate.png -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/GeneralUpdateBootstrap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | using System.Text.Json; 8 | using System.Threading.Tasks; 9 | using GeneralUpdate.Common.FileBasic; 10 | using GeneralUpdate.Common.Download; 11 | using GeneralUpdate.Common.Internal; 12 | using GeneralUpdate.Common.Internal.Bootstrap; 13 | using GeneralUpdate.Common.Internal.Event; 14 | using GeneralUpdate.Common.Internal.JsonContext; 15 | using GeneralUpdate.Common.Internal.Strategy; 16 | using GeneralUpdate.Common.Shared.Object; 17 | using GeneralUpdate.Core.Strategys; 18 | 19 | namespace GeneralUpdate.Core 20 | { 21 | public class GeneralUpdateBootstrap : AbstractBootstrap 22 | { 23 | private readonly GlobalConfigInfo _configInfo; 24 | private IStrategy? _strategy; 25 | 26 | public GeneralUpdateBootstrap() 27 | { 28 | var json = Environments.GetEnvironmentVariable("ProcessInfo"); 29 | if (string.IsNullOrWhiteSpace(json)) 30 | throw new ArgumentException("json environment variable is not defined"); 31 | 32 | var processInfo = JsonSerializer.Deserialize(json, ProcessInfoJsonContext.Default.ProcessInfo); 33 | if (processInfo == null) 34 | throw new ArgumentException("ProcessInfo object cannot be null!"); 35 | 36 | BlackListManager.Instance?.AddBlackFileFormats(processInfo.BlackFileFormats); 37 | BlackListManager.Instance?.AddBlackFiles(processInfo.BlackFiles); 38 | BlackListManager.Instance?.AddSkipDirectorys(processInfo.SkipDirectorys); 39 | 40 | _configInfo = new() 41 | { 42 | MainAppName = processInfo.AppName, 43 | InstallPath = processInfo.InstallPath, 44 | ClientVersion = processInfo.CurrentVersion, 45 | LastVersion = processInfo.LastVersion, 46 | UpdateLogUrl = processInfo.UpdateLogUrl, 47 | Encoding = Encoding.GetEncoding(processInfo.CompressEncoding), 48 | Format = processInfo.CompressFormat, 49 | DownloadTimeOut = processInfo.DownloadTimeOut, 50 | AppSecretKey = processInfo.AppSecretKey, 51 | UpdateVersions = processInfo.UpdateVersions, 52 | TempPath = StorageManager.GetTempDirectory("upgrade_temp"), 53 | ReportUrl = processInfo.ReportUrl, 54 | BackupDirectory = processInfo.BackupDirectory, 55 | Scheme = processInfo.Scheme, 56 | Token = processInfo.Token 57 | }; 58 | } 59 | 60 | public override async Task LaunchAsync() 61 | { 62 | try 63 | { 64 | StrategyFactory(); 65 | var manager = 66 | new DownloadManager(_configInfo.TempPath, _configInfo.Format, _configInfo.DownloadTimeOut); 67 | manager.MultiAllDownloadCompleted += OnMultiAllDownloadCompleted; 68 | manager.MultiDownloadCompleted += OnMultiDownloadCompleted; 69 | manager.MultiDownloadError += OnMultiDownloadError; 70 | manager.MultiDownloadStatistics += OnMultiDownloadStatistics; 71 | foreach (var versionInfo in _configInfo.UpdateVersions) 72 | { 73 | manager.Add(new DownloadTask(manager, versionInfo)); 74 | } 75 | 76 | await manager.LaunchTasksAsync(); 77 | } 78 | catch (Exception exception) 79 | { 80 | Debug.WriteLine(exception.Message); 81 | EventManager.Instance.Dispatch(this, new ExceptionEventArgs(exception, exception.Message)); 82 | } 83 | return this; 84 | } 85 | 86 | #region public method 87 | 88 | public GeneralUpdateBootstrap SetFieldMappings(Dictionary fieldMappings) 89 | { 90 | _configInfo.FieldMappings = fieldMappings; 91 | return this; 92 | } 93 | 94 | public GeneralUpdateBootstrap AddListenerMultiAllDownloadCompleted( 95 | Action callbackAction) 96 | => AddListener(callbackAction); 97 | 98 | public GeneralUpdateBootstrap AddListenerMultiDownloadCompleted( 99 | Action callbackAction) 100 | => AddListener(callbackAction); 101 | 102 | public GeneralUpdateBootstrap AddListenerMultiDownloadError( 103 | Action callbackAction) 104 | => AddListener(callbackAction); 105 | 106 | public GeneralUpdateBootstrap AddListenerMultiDownloadStatistics( 107 | Action callbackAction) 108 | => AddListener(callbackAction); 109 | 110 | public GeneralUpdateBootstrap AddListenerException(Action callbackAction) 111 | => AddListener(callbackAction); 112 | 113 | #endregion 114 | 115 | protected override Task ExecuteStrategyAsync()=> throw new NotImplementedException(); 116 | 117 | protected override void ExecuteStrategy() 118 | { 119 | _strategy?.Create(_configInfo); 120 | _strategy?.Execute(); 121 | } 122 | 123 | protected override GeneralUpdateBootstrap StrategyFactory() 124 | { 125 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 126 | _strategy = new WindowsStrategy(); 127 | else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) 128 | _strategy = new LinuxStrategy(); 129 | else 130 | throw new PlatformNotSupportedException("The current operating system is not supported!"); 131 | 132 | return this; 133 | } 134 | 135 | private GeneralUpdateBootstrap AddListener(Action callbackAction) where TArgs : EventArgs 136 | { 137 | Debug.Assert(callbackAction != null); 138 | EventManager.Instance.AddListener(callbackAction); 139 | return this; 140 | } 141 | 142 | private void OnMultiDownloadStatistics(object sender, MultiDownloadStatisticsEventArgs e) 143 | => EventManager.Instance.Dispatch(sender, e); 144 | 145 | private void OnMultiDownloadCompleted(object sender, MultiDownloadCompletedEventArgs e) 146 | => EventManager.Instance.Dispatch(sender, e); 147 | 148 | private void OnMultiDownloadError(object sender, MultiDownloadErrorEventArgs e) 149 | => EventManager.Instance.Dispatch(sender, e); 150 | 151 | private void OnMultiAllDownloadCompleted(object sender, MultiAllDownloadCompletedEventArgs e) 152 | { 153 | EventManager.Instance.Dispatch(sender, e); 154 | ExecuteStrategy(); 155 | } 156 | } 157 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/GeneralUpdateOSS.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Text.Json; 4 | using System.Threading.Tasks; 5 | using GeneralUpdate.Common.Internal.Bootstrap; 6 | using GeneralUpdate.Common.Internal.JsonContext; 7 | using GeneralUpdate.Common.Shared.Object; 8 | using GeneralUpdate.Core.Strategys; 9 | 10 | namespace GeneralUpdate.Core 11 | { 12 | public sealed class GeneralUpdateOSS 13 | { 14 | private GeneralUpdateOSS() { } 15 | 16 | #region Public Methods 17 | 18 | /// 19 | /// Starting an OSS update for windows,Linux,mac platform. 20 | /// 21 | /// 22 | public static async Task Start()=> await BaseStart(); 23 | 24 | #endregion Public Methods 25 | 26 | #region Private Methods 27 | 28 | /// 29 | /// The underlying update method. 30 | /// 31 | private static async Task BaseStart() 32 | { 33 | try 34 | { 35 | var json = Environments.GetEnvironmentVariable("GlobalConfigInfoOSS"); 36 | if (string.IsNullOrWhiteSpace(json)) 37 | return; 38 | 39 | var parameter = JsonSerializer.Deserialize(json, GlobalConfigInfoOSSJsonContext.Default.GlobalConfigInfoOSS); 40 | var strategy = new OSSStrategy(); 41 | strategy.Create(parameter); 42 | await strategy.ExecuteAsync(); 43 | } 44 | catch (Exception exception) 45 | { 46 | Debug.WriteLine(exception); 47 | throw new Exception(exception.Message + "\n" + exception.StackTrace); 48 | } 49 | } 50 | 51 | #endregion Private Methods 52 | } 53 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Pipeline/CompressMiddleware.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using GeneralUpdate.Common.Compress; 7 | using GeneralUpdate.Common.Internal; 8 | using GeneralUpdate.Common.Internal.Event; 9 | using GeneralUpdate.Common.Internal.Pipeline; 10 | 11 | namespace GeneralUpdate.Core.Pipeline; 12 | 13 | public class CompressMiddleware : IMiddleware 14 | { 15 | public Task InvokeAsync(PipelineContext context) 16 | { 17 | return Task.Run(() => 18 | { 19 | var format = context.Get("Format"); 20 | var sourcePath = context.Get("ZipFilePath"); 21 | var patchPath = context.Get("PatchPath"); 22 | var encoding = context.Get("Encoding"); 23 | CompressProvider.Decompress(format, sourcePath, patchPath, encoding); 24 | }); 25 | } 26 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Pipeline/DriverMiddleware.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Runtime.InteropServices; 7 | using System.Threading.Tasks; 8 | using GeneralUpdate.Common; 9 | using GeneralUpdate.Common.Internal; 10 | using GeneralUpdate.Common.Internal.Event; 11 | using GeneralUpdate.Common.Internal.Pipeline; 12 | using GeneralUpdate.Core.Driver; 13 | 14 | namespace GeneralUpdate.Core.Pipeline; 15 | 16 | /// 17 | /// Driver update. 18 | /// Use for Windows Vista/Windows 7/Windows 8/Windows 8.1/Windows 10/Windows 11/Windows Server 2008. 19 | /// 20 | public class DriverMiddleware : IMiddleware 21 | { 22 | private const string FileExtension = ".inf"; 23 | 24 | public Task InvokeAsync(PipelineContext context) 25 | { 26 | return Task.Run(() => 27 | { 28 | var outPutPath = context.Get("DriverOutPut"); 29 | if (string.IsNullOrWhiteSpace(outPutPath)) 30 | return; 31 | 32 | var patchPath = context.Get("PatchPath"); 33 | if (string.IsNullOrWhiteSpace(patchPath)) 34 | return; 35 | 36 | var fieldMappings = context.Get>("FieldMappings"); 37 | if (fieldMappings == null || fieldMappings.Count == 0) 38 | return; 39 | 40 | var information = new DriverInformation.Builder() 41 | .SetDriverFileExtension(FileExtension) 42 | .SetOutPutDirectory(outPutPath) 43 | .SetDriverDirectory(patchPath) 44 | .SetFieldMappings(fieldMappings) 45 | .Build(); 46 | 47 | var processor = new DriverProcessor(); 48 | processor.AddCommand(new BackupDriverCommand(information)); 49 | processor.AddCommand(new DeleteDriverCommand(information)); 50 | processor.AddCommand(new InstallDriverCommand(information)); 51 | processor.ProcessCommands(); 52 | }); 53 | } 54 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Pipeline/HashMiddleware.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Security.Cryptography; 4 | using System.Threading.Tasks; 5 | using GeneralUpdate.Common.HashAlgorithms; 6 | using GeneralUpdate.Common.Internal; 7 | using GeneralUpdate.Common.Internal.Event; 8 | using GeneralUpdate.Common.Internal.Pipeline; 9 | 10 | namespace GeneralUpdate.Core.Pipeline; 11 | 12 | public class HashMiddleware : IMiddleware 13 | { 14 | public async Task InvokeAsync(PipelineContext context) 15 | { 16 | var path = context.Get("ZipFilePath"); 17 | var hash = context.Get("Hash"); 18 | var isVerify = await VerifyFileHash(path, hash); 19 | if (!isVerify) throw new CryptographicException("Hash verification failed !"); 20 | } 21 | 22 | private Task VerifyFileHash(string path, string hash) 23 | { 24 | return Task.Run(() => 25 | { 26 | try 27 | { 28 | var hashAlgorithm = new Sha256HashAlgorithm(); 29 | var hashSha256 = hashAlgorithm.ComputeHash(path); 30 | return string.Equals(hash, hashSha256, StringComparison.OrdinalIgnoreCase); 31 | } 32 | catch (Exception exception) 33 | { 34 | Debug.WriteLine(exception.Message); 35 | EventManager.Instance.Dispatch(this, new ExceptionEventArgs(exception, exception.Message)); 36 | } 37 | 38 | return false; 39 | }); 40 | } 41 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Pipeline/PatchMiddleware.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Threading.Tasks; 5 | using GeneralUpdate.Common.FileBasic; 6 | using GeneralUpdate.Common.Internal; 7 | using GeneralUpdate.Common.Internal.Event; 8 | using GeneralUpdate.Common.Internal.Pipeline; 9 | using GeneralUpdate.Differential; 10 | 11 | namespace GeneralUpdate.Core.Pipeline; 12 | 13 | public class PatchMiddleware : IMiddleware 14 | { 15 | public async Task InvokeAsync(PipelineContext context) 16 | { 17 | var sourcePath = context.Get("SourcePath"); 18 | var targetPath = context.Get("PatchPath"); 19 | await DifferentialCore.Instance?.Dirty(sourcePath, targetPath); 20 | } 21 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // 有关程序集的一般信息由以下 5 | // 控制。更改这些特性值可修改 6 | // 与程序集关联的信息。 7 | [assembly: AssemblyTitle("GeneralUpdate.Core")] 8 | [assembly: AssemblyDescription("Based on dotnet standard, an automatic upgrade program for c/s application is developed.The core part of the update can be easily used in many projects.")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("juster.zhu WELL-E")] 11 | [assembly: AssemblyProduct("GeneralUpdate.Core")] 12 | [assembly: AssemblyCopyright("Copyright © 2021")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // 将 ComVisible 设置为 false 会使此程序集中的类型 17 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 18 | //请将此类型的 ComVisible 特性设置为 true。 19 | [assembly: ComVisible(false)] 20 | 21 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 22 | [assembly: Guid("35bff228-5ee4-49a6-b721-fb0122e967a0")] 23 | 24 | // 程序集的版本信息由下列四个值组成: 25 | // 26 | // 主版本 27 | // 次版本 28 | // 生成号 29 | // 修订号 30 | // 31 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 32 | //通过使用 "*",如下所示: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("3.6.10.0")] 35 | [assembly: AssemblyFileVersion("3.6.10.0")] -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "GeneralUpdate.Core": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "environmentVariables": { 7 | "ASPNETCORE_ENVIRONMENT": "Development" 8 | }, 9 | "applicationUrl": "https://localhost:65348;http://localhost:65359" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Strategys/LinuxStrategy.cs: -------------------------------------------------------------------------------- 1 | namespace GeneralUpdate.Core.Strategys; 2 | public class LinuxStrategy : WindowsStrategy; -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Strategys/OSSStrategy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using GeneralUpdate.Common.Compress; 9 | using GeneralUpdate.Common.FileBasic; 10 | using GeneralUpdate.Common.Download; 11 | using GeneralUpdate.Common.Internal.JsonContext; 12 | using GeneralUpdate.Common.Shared.Object; 13 | 14 | namespace GeneralUpdate.Core.Strategys 15 | { 16 | public class OSSStrategy 17 | { 18 | #region Private Members 19 | 20 | private readonly string _appPath = AppDomain.CurrentDomain.BaseDirectory; 21 | private const int TimeOut = 60; 22 | private GlobalConfigInfoOSS? _parameter; 23 | 24 | #endregion Private Members 25 | 26 | #region Public Methods 27 | 28 | public void Create(GlobalConfigInfoOSS parameter) 29 | => _parameter = parameter; 30 | 31 | public async Task ExecuteAsync() 32 | { 33 | try 34 | { 35 | //1.Download the JSON version configuration file. 36 | var jsonPath = Path.Combine(_appPath, _parameter.VersionFileName); 37 | if (!File.Exists(jsonPath)) 38 | throw new FileNotFoundException(jsonPath); 39 | 40 | //2.Parse the JSON version configuration file content. 41 | var versions = StorageManager.GetJson>(jsonPath, VersionOSSJsonContext.Default.ListVersionOSS); 42 | if (versions == null) 43 | throw new NullReferenceException(nameof(versions)); 44 | 45 | versions = versions.OrderBy(v => v.PubTime).ToList(); 46 | //3.Download version by version according to the version of the configuration file. 47 | await DownloadVersions(versions); 48 | Decompress(versions); 49 | 50 | //4.Launch the main application. 51 | LaunchApp(); 52 | } 53 | catch (Exception ex) 54 | { 55 | Debug.WriteLine(ex.Message); 56 | throw new Exception(ex.Message + "\n" + ex.StackTrace); 57 | } 58 | finally 59 | { 60 | Process.GetCurrentProcess().Kill(); 61 | } 62 | } 63 | 64 | #endregion Public Methods 65 | 66 | #region Private Methods 67 | 68 | /// 69 | /// Download all updated versions version by version. 70 | /// 71 | /// The collection of version information to be updated as described in the configuration file. 72 | private async Task DownloadVersions(List versions) 73 | { 74 | try 75 | { 76 | var manager = new DownloadManager(_appPath, Format.ZIP, TimeOut); 77 | foreach (var versionInfo in versions) 78 | { 79 | var version = new VersionInfo 80 | { 81 | Name = versionInfo.PacketName, 82 | Version = versionInfo.Version, 83 | Url = versionInfo.Url, 84 | Format = Format.ZIP, 85 | Hash = versionInfo.Hash 86 | }; 87 | manager.Add(new DownloadTask(manager, version)); 88 | } 89 | 90 | await manager.LaunchTasksAsync(); 91 | } 92 | catch (Exception e) 93 | { 94 | Debug.WriteLine(e.Message); 95 | throw new Exception(e.Message + "\n" + e.StackTrace); 96 | } 97 | } 98 | 99 | /// 100 | /// Start the main application when the update is complete. 101 | /// 102 | /// 103 | private void LaunchApp() 104 | { 105 | var appPath = Path.Combine(_appPath, _parameter.AppName); 106 | if (!File.Exists(appPath)) throw new FileNotFoundException($"{nameof(appPath)} , The application is not accessible !"); 107 | Process.Start(appPath); 108 | } 109 | 110 | private void Decompress(List versions) 111 | { 112 | var encoding = Encoding.GetEncoding(_parameter.Encoding); 113 | foreach (var version in versions) 114 | { 115 | try 116 | { 117 | var zipFilePath = Path.Combine(_appPath, $"{version.PacketName}{Format.ZIP}"); 118 | CompressProvider.Decompress(Format.ZIP, zipFilePath, _appPath, encoding); 119 | 120 | if (!File.Exists(zipFilePath)) continue; 121 | File.SetAttributes(zipFilePath, FileAttributes.Normal); 122 | File.Delete(zipFilePath); 123 | } 124 | catch (Exception e) 125 | { 126 | Debug.WriteLine(e.Message); 127 | } 128 | } 129 | } 130 | 131 | #endregion Private Methods 132 | } 133 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Core/Strategys/WindowsStrategy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Runtime.InteropServices; 5 | using System.Threading.Tasks; 6 | using GeneralUpdate.Common.FileBasic; 7 | using GeneralUpdate.Common.Internal; 8 | using GeneralUpdate.Common.Internal.Event; 9 | using GeneralUpdate.Common.Internal.Pipeline; 10 | using GeneralUpdate.Common.Internal.Strategy; 11 | using GeneralUpdate.Common.Shared.Object; 12 | using GeneralUpdate.Common.Shared.Object.Enum; 13 | using GeneralUpdate.Common.Shared.Service; 14 | using GeneralUpdate.Core.Pipeline; 15 | 16 | namespace GeneralUpdate.Core.Strategys 17 | { 18 | /// 19 | /// Update policy based on the Windows platform. 20 | /// 21 | public class WindowsStrategy : AbstractStrategy 22 | { 23 | private GlobalConfigInfo _configinfo = new(); 24 | 25 | public override void Create(GlobalConfigInfo parameter) => _configinfo = parameter; 26 | 27 | public override void Execute() 28 | { 29 | Task.Run(async () => 30 | { 31 | try 32 | { 33 | var status = ReportType.None; 34 | var patchPath = StorageManager.GetTempDirectory(Patchs); 35 | foreach (var version in _configinfo.UpdateVersions) 36 | { 37 | try 38 | { 39 | var context = new PipelineContext(); 40 | //Common 41 | context.Add("ZipFilePath", 42 | Path.Combine(_configinfo.TempPath, $"{version.Name}{_configinfo.Format}")); 43 | //Hash middleware 44 | context.Add("Hash", version.Hash); 45 | //Zip middleware 46 | context.Add("Format", _configinfo.Format); 47 | context.Add("Name", version.Name); 48 | context.Add("Encoding", _configinfo.Encoding); 49 | //Patch middleware 50 | context.Add("SourcePath", _configinfo.InstallPath); 51 | context.Add("PatchPath", patchPath); 52 | //Driver middleware 53 | if (_configinfo.DriveEnabled == true) 54 | { 55 | context.Add("DriverOutPut", StorageManager.GetTempDirectory("DriverOutPut")); 56 | context.Add("FieldMappings", _configinfo.FieldMappings); 57 | } 58 | 59 | var pipelineBuilder = new PipelineBuilder(context) 60 | .UseMiddleware() 61 | .UseMiddleware() 62 | .UseMiddleware() 63 | .UseMiddlewareIf(_configinfo.DriveEnabled); 64 | await pipelineBuilder.Build(); 65 | status = ReportType.Success; 66 | } 67 | catch (Exception e) 68 | { 69 | status = ReportType.Failure; 70 | EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); 71 | } 72 | finally 73 | { 74 | await VersionService.Report(_configinfo.ReportUrl 75 | , version.RecordId 76 | , status 77 | , version.AppType 78 | , _configinfo.Scheme 79 | , _configinfo.Token); 80 | } 81 | } 82 | 83 | if (!string.IsNullOrEmpty(_configinfo.UpdateLogUrl)) 84 | { 85 | OpenBrowser(_configinfo.UpdateLogUrl); 86 | } 87 | 88 | Clear(patchPath); 89 | Clear(_configinfo.TempPath); 90 | StartApp(); 91 | } 92 | catch (Exception e) 93 | { 94 | Debug.WriteLine(e.Message); 95 | EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); 96 | } 97 | }); 98 | } 99 | 100 | public override void StartApp() 101 | { 102 | try 103 | { 104 | var mainAppPath = CheckPath(_configinfo.InstallPath, _configinfo.MainAppName); 105 | if (string.IsNullOrEmpty(mainAppPath)) 106 | throw new Exception($"Can't find the app {mainAppPath}!"); 107 | 108 | Process.Start(mainAppPath); 109 | 110 | if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) 111 | { 112 | var bowlAppPath = CheckPath(_configinfo.InstallPath, _configinfo.Bowl); 113 | if (!string.IsNullOrEmpty(bowlAppPath)) 114 | Process.Start(bowlAppPath); 115 | } 116 | } 117 | catch (Exception e) 118 | { 119 | Debug.WriteLine(e.Message); 120 | EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); 121 | } 122 | finally 123 | { 124 | Process.GetCurrentProcess().Kill(); 125 | } 126 | } 127 | 128 | private string CheckPath(string path,string name) 129 | { 130 | if (string.IsNullOrWhiteSpace(path) || string.IsNullOrWhiteSpace(name)) return string.Empty; 131 | var tempPath = Path.Combine(path, name); 132 | return File.Exists(tempPath) ? tempPath : string.Empty; 133 | } 134 | } 135 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Differential/Binary/BZip2Constants.cs: -------------------------------------------------------------------------------- 1 | namespace GeneralUpdate.Differential.Binary 2 | { 3 | internal sealed class BZip2Constants 4 | { 5 | public const int BaseBlockSize = 100000; 6 | 7 | public const int MaximumAlphaSize = 258; 8 | 9 | public const int MaximumCodeLength = 23; 10 | 11 | public const int RunA = 0; 12 | 13 | public const int RunB = 1; 14 | 15 | public const int GroupCount = 6; 16 | 17 | public const int GroupSize = 50; 18 | 19 | public const int NumberOfIterations = 4; 20 | 21 | public const int MaximumSelectors = 18002; 22 | 23 | public const int OvershootBytes = 20; 24 | 25 | public static readonly int[] RandomNumbers = new int[512] 26 | { 27 | 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, 28 | 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, 29 | 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, 30 | 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, 31 | 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, 32 | 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, 33 | 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, 34 | 170, 607, 520, 932, 727, 476, 693, 425, 174, 647, 35 | 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, 36 | 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, 37 | 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, 38 | 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, 39 | 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, 40 | 98, 553, 163, 354, 666, 933, 424, 341, 533, 870, 41 | 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, 42 | 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, 43 | 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, 44 | 715, 67, 618, 276, 204, 918, 873, 777, 604, 560, 45 | 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, 46 | 652, 934, 970, 447, 318, 353, 859, 672, 112, 785, 47 | 645, 863, 803, 350, 139, 93, 354, 99, 820, 908, 48 | 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, 49 | 653, 282, 762, 623, 680, 81, 927, 626, 789, 125, 50 | 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, 51 | 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, 52 | 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, 53 | 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, 54 | 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, 55 | 344, 805, 988, 739, 511, 655, 814, 334, 249, 515, 56 | 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, 57 | 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, 58 | 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, 59 | 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, 60 | 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, 61 | 680, 879, 194, 572, 640, 724, 926, 56, 204, 700, 62 | 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, 63 | 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, 64 | 134, 108, 571, 364, 631, 212, 174, 643, 304, 329, 65 | 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, 66 | 140, 206, 73, 263, 980, 736, 876, 478, 430, 305, 67 | 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, 68 | 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, 69 | 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, 70 | 896, 831, 547, 261, 524, 462, 293, 465, 502, 56, 71 | 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, 72 | 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, 73 | 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, 74 | 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, 75 | 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, 76 | 920, 176, 193, 713, 857, 265, 203, 50, 668, 108, 77 | 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, 78 | 936, 638 79 | }; 80 | 81 | private BZip2Constants() 82 | { 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Differential/Binary/IChecksum.cs: -------------------------------------------------------------------------------- 1 | namespace GeneralUpdate.Differential.Binary 2 | { 3 | public interface IChecksum 4 | { 5 | long Value { get; } 6 | 7 | void Reset(); 8 | 9 | void Update(int value); 10 | 11 | void Update(byte[] buffer); 12 | 13 | void Update(byte[] buffer, int offset, int count); 14 | } 15 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Differential/Binary/StrangeCRC.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GeneralUpdate.Differential.Binary 4 | { 5 | public class StrangeCRC : IChecksum 6 | { 7 | private static readonly uint[] crc32Table = new uint[256] 8 | { 9 | 0u, 79764919u, 159529838u, 222504665u, 319059676u, 398814059u, 445009330u, 507990021u, 638119352u, 583659535u, 10 | 797628118u, 726387553u, 890018660u, 835552979u, 1015980042u, 944750013u, 1276238704u, 1221641927u, 1167319070u, 1095957929u, 11 | 1595256236u, 1540665371u, 1452775106u, 1381403509u, 1780037320u, 1859660671u, 1671105958u, 1733955601u, 2031960084u, 2111593891u, 12 | 1889500026u, 1952343757u, 2552477408u, 2632100695u, 2443283854u, 2506133561u, 2334638140u, 2414271883u, 2191915858u, 2254759653u, 13 | 3190512472u, 3135915759u, 3081330742u, 3009969537u, 2905550212u, 2850959411u, 2762807018u, 2691435357u, 3560074640u, 3505614887u, 14 | 3719321342u, 3648080713u, 3342211916u, 3287746299u, 3467911202u, 3396681109u, 4063920168u, 4143685023u, 4223187782u, 4286162673u, 15 | 3779000052u, 3858754371u, 3904687514u, 3967668269u, 881225847u, 809987520u, 1023691545u, 969234094u, 662832811u, 591600412u, 16 | 771767749u, 717299826u, 311336399u, 374308984u, 453813921u, 533576470u, 25881363u, 88864420u, 134795389u, 214552010u, 17 | 2023205639u, 2086057648u, 1897238633u, 1976864222u, 1804852699u, 1867694188u, 1645340341u, 1724971778u, 1587496639u, 1516133128u, 18 | 1461550545u, 1406951526u, 1302016099u, 1230646740u, 1142491917u, 1087903418u, 2896545431u, 2825181984u, 2770861561u, 2716262478u, 19 | 3215044683u, 3143675388u, 3055782693u, 3001194130u, 2326604591u, 2389456536u, 2200899649u, 2280525302u, 2578013683u, 2640855108u, 20 | 2418763421u, 2498394922u, 3769900519u, 3832873040u, 3912640137u, 3992402750u, 4088425275u, 4151408268u, 4197601365u, 4277358050u, 21 | 3334271071u, 3263032808u, 3476998961u, 3422541446u, 3585640067u, 3514407732u, 3694837229u, 3640369242u, 1762451694u, 1842216281u, 22 | 1619975040u, 1682949687u, 2047383090u, 2127137669u, 1938468188u, 2001449195u, 1325665622u, 1271206113u, 1183200824u, 1111960463u, 23 | 1543535498u, 1489069629u, 1434599652u, 1363369299u, 622672798u, 568075817u, 748617968u, 677256519u, 907627842u, 853037301u, 24 | 1067152940u, 995781531u, 51762726u, 131386257u, 177728840u, 240578815u, 269590778u, 349224269u, 429104020u, 491947555u, 25 | 4046411278u, 4126034873u, 4172115296u, 4234965207u, 3794477266u, 3874110821u, 3953728444u, 4016571915u, 3609705398u, 3555108353u, 26 | 3735388376u, 3664026991u, 3290680682u, 3236090077u, 3449943556u, 3378572211u, 3174993278u, 3120533705u, 3032266256u, 2961025959u, 27 | 2923101090u, 2868635157u, 2813903052u, 2742672763u, 2604032198u, 2683796849u, 2461293480u, 2524268063u, 2284983834u, 2364738477u, 28 | 2175806836u, 2238787779u, 1569362073u, 1498123566u, 1409854455u, 1355396672u, 1317987909u, 1246755826u, 1192025387u, 1137557660u, 29 | 2072149281u, 2135122070u, 1912620623u, 1992383480u, 1753615357u, 1816598090u, 1627664531u, 1707420964u, 295390185u, 358241886u, 30 | 404320391u, 483945776u, 43990325u, 106832002u, 186451547u, 266083308u, 932423249u, 861060070u, 1041341759u, 986742920u, 31 | 613929101u, 542559546u, 756411363u, 701822548u, 3316196985u, 3244833742u, 3425377559u, 3370778784u, 3601682597u, 3530312978u, 32 | 3744426955u, 3689838204u, 3819031489u, 3881883254u, 3928223919u, 4007849240u, 4037393693u, 4100235434u, 4180117107u, 4259748804u, 33 | 2310601993u, 2373574846u, 2151335527u, 2231098320u, 2596047829u, 2659030626u, 2470359227u, 2550115596u, 2947551409u, 2876312838u, 34 | 2788305887u, 2733848168u, 3165939309u, 3094707162u, 3040238851u, 2985771188u 35 | }; 36 | 37 | private int globalCrc; 38 | 39 | public long Value => ~globalCrc; 40 | 41 | public StrangeCRC() 42 | { 43 | Reset(); 44 | } 45 | 46 | public void Reset() 47 | { 48 | globalCrc = -1; 49 | } 50 | 51 | public void Update(int value) 52 | { 53 | int num = (globalCrc >> 24) ^ value; 54 | if (num < 0) 55 | { 56 | num = 256 + num; 57 | } 58 | 59 | globalCrc = (int)((globalCrc << 8) ^ crc32Table[num]); 60 | } 61 | 62 | public void Update(byte[] buffer) 63 | { 64 | if (buffer == null) 65 | { 66 | throw new ArgumentNullException("buffer"); 67 | } 68 | 69 | Update(buffer, 0, buffer.Length); 70 | } 71 | 72 | public void Update(byte[] buffer, int offset, int count) 73 | { 74 | if (buffer == null) 75 | { 76 | throw new ArgumentNullException("buffer"); 77 | } 78 | 79 | if (offset < 0) 80 | { 81 | throw new ArgumentOutOfRangeException("offset", "cannot be less than zero"); 82 | } 83 | 84 | if (count < 0) 85 | { 86 | throw new ArgumentOutOfRangeException("count", "cannot be less than zero"); 87 | } 88 | 89 | if (offset + count > buffer.Length) 90 | { 91 | throw new ArgumentOutOfRangeException("count"); 92 | } 93 | 94 | for (int i = 0; i < count; i++) 95 | { 96 | Update(buffer[offset++]); 97 | } 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Differential/GeneralUpdate.Differential.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | GeneralUpdate.ico 6 | GeneralUpdate.png 7 | https://github.com/JusterZhu/GeneralUpdate 8 | The binary differential update function is provided, but the configuration file update function is reserved. 9 | JusterZhu 10 | 9.1.6 11 | https://github.com/GeneralLibrary/GeneralUpdate 12 | Copyright © 2024 JusterZhu. All rights reserved. 13 | default 14 | enable 15 | GeneralUpdate.Differential 16 | https://github.com/GeneralLibrary/GeneralUpdate?tab=MIT-1-ov-file#readme 17 | public 18 | upgrade,update 19 | The binary differential update function is provided, but the configuration file update function is reserved. 20 | true 21 | true 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | True 31 | 32 | 33 | 34 | 35 | 36 | 37 | True 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Differential/GeneralUpdate.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/src/c#/GeneralUpdate.Differential/GeneralUpdate.ico -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Differential/GeneralUpdate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeneralLibrary/GeneralUpdate/69c16da6d74b6a1e8cfbf571b9d49e1b5a820da2/src/c#/GeneralUpdate.Differential/GeneralUpdate.png -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Differential/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "GeneralUpdate.Differential": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "environmentVariables": { 7 | "ASPNETCORE_ENVIRONMENT": "Development" 8 | }, 9 | "applicationUrl": "https://localhost:65354;http://localhost:65360" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Upgrad/GeneralUpdate.Upgrad.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | true 9 | default 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | all 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.Upgrad/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using GeneralUpdate.Common.Download; 3 | using GeneralUpdate.Common.FileBasic; 4 | using GeneralUpdate.Common.Internal; 5 | using GeneralUpdate.Common.Internal.Bootstrap; 6 | using GeneralUpdate.Common.Shared.Object; 7 | using GeneralUpdate.Core; 8 | using GeneralUpdate.Core.Driver; 9 | 10 | namespace GeneralUpdate.Upgrad 11 | { 12 | internal class Program 13 | { 14 | static async Task Main(string[] args) 15 | { 16 | try 17 | { 18 | Console.WriteLine($"升级程序初始化,{DateTime.Now}!"); 19 | Console.WriteLine("当前运行目录:" + Thread.GetDomain().BaseDirectory); 20 | await Task.Delay(2000); 21 | _ = await new GeneralUpdateBootstrap() 22 | //单个或多个更新包下载速度、剩余下载事件、当前下载版本信息通知事件 23 | .AddListenerMultiDownloadStatistics(OnMultiDownloadStatistics) 24 | //单个或多个更新包下载完成 25 | .AddListenerMultiDownloadCompleted(OnMultiDownloadCompleted) 26 | //完成所有的下载任务通知 27 | .AddListenerMultiAllDownloadCompleted(OnMultiAllDownloadCompleted) 28 | //下载过程出现的异常通知 29 | .AddListenerMultiDownloadError(OnMultiDownloadError) 30 | //整个更新过程出现的任何问题都会通过这个事件通知 31 | .AddListenerException(OnException) 32 | //设置字段映射表,用于解析所有驱动包的信息的字符串 33 | //.SetFieldMappings(fieldMappingsCN) 34 | //是否开启驱动更新 35 | //.Option(UpdateOption.Drive, true) 36 | .LaunchAsync(); 37 | Console.WriteLine($"升级程序已启动,{DateTime.Now}!"); 38 | } 39 | catch (Exception e) 40 | { 41 | Console.WriteLine(e.Message + "\n" + e.StackTrace); 42 | } 43 | 44 | //中文操作系统的驱动包字段映射表,用于解析所有驱动包的信息的字符串 45 | /*var fieldMappingsCN = new Dictionary 46 | { 47 | { "PublishedName", "发布名称" }, 48 | { "OriginalName", "原始名称" }, 49 | { "Provider", "提供程序名称" }, 50 | { "ClassName", "类名" }, 51 | { "ClassGUID", "类 GUID" }, 52 | { "Version", "驱动程序版本" }, 53 | { "Signer", "签名者姓名" } 54 | }; 55 | 56 | //英文操作系统的驱动包字段映射表,用于解析所有驱动包的信息的字符串 57 | var fieldMappingsEN = new Dictionary 58 | { 59 | { "PublishedName", "Driver" }, 60 | { "OriginalName", "OriginalFileName" }, 61 | { "Provider", "ProviderName" }, 62 | { "ClassName", "ClassName" }, 63 | { "Version", "Version" } 64 | }; 65 | 66 | var fileExtension = ".inf"; 67 | var outPutPath = @"D:\drivers\"; 68 | var driversPath = @"D:\driverslocal\"; 69 | 70 | var information = new DriverInformation.Builder() 71 | .SetDriverFileExtension(fileExtension) 72 | .SetOutPutDirectory(outPutPath) 73 | .SetDriverDirectory(driversPath) 74 | .SetFieldMappings(fieldMappingsCN) 75 | .Build(); 76 | 77 | var processor = new DriverProcessor(); 78 | processor.AddCommand(new BackupDriverCommand(information)); 79 | processor.AddCommand(new DeleteDriverCommand(information)); 80 | processor.AddCommand(new InstallDriverCommand(information)); 81 | processor.ProcessCommands();*/ 82 | 83 | //await GeneralUpdateOSS.Start(); 84 | 85 | while (true) 86 | { 87 | var input = Console.ReadLine(); 88 | if (input == "exit") 89 | { 90 | break; 91 | } 92 | } 93 | } 94 | 95 | private static void OnMultiDownloadError(object arg1, MultiDownloadErrorEventArgs arg2) 96 | { 97 | var version = arg2.Version as VersionInfo; 98 | Console.WriteLine($"{version.Version} {arg2.Exception}"); 99 | } 100 | 101 | private static void OnMultiAllDownloadCompleted(object arg1, MultiAllDownloadCompletedEventArgs arg2) 102 | { 103 | Console.WriteLine(arg2.IsAllDownloadCompleted ? "所有的下载任务已完成!" : $"下载任务已失败!{arg2.FailedVersions.Count}"); 104 | } 105 | 106 | private static void OnMultiDownloadCompleted(object arg1, MultiDownloadCompletedEventArgs arg2) 107 | { 108 | var version = arg2.Version as VersionInfo; 109 | Console.WriteLine(arg2.IsComplated ? $"当前下载版本:{version.Version}, 下载完成!" : $"当前下载版本:{version.Version}, 下载失败!"); 110 | } 111 | 112 | private static void OnMultiDownloadStatistics(object arg1, MultiDownloadStatisticsEventArgs arg2) 113 | { 114 | var version = arg2.Version as VersionInfo; 115 | Console.WriteLine($"当前下载版本:{version.Version},下载速度:{arg2.Speed},剩余下载时间:{arg2.Remaining},已下载大小:{arg2.BytesReceived},总大小:{arg2.TotalBytesToReceive}, 进度百分比:{arg2.ProgressPercentage}%"); 116 | } 117 | 118 | private static void OnException(object arg1, ExceptionEventArgs arg2) 119 | { 120 | Console.WriteLine($"{arg2.Exception}"); 121 | } 122 | } 123 | } -------------------------------------------------------------------------------- /src/c#/GeneralUpdate.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.31423.177 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{91F059E6-7AD3-4FB7-9604-30A7849C6EFF}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeneralUpdate.Core", "GeneralUpdate.Core\GeneralUpdate.Core.csproj", "{35BFF228-5EE4-49A6-B721-FB0122E967A0}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeneralUpdate.ClientCore", "GeneralUpdate.ClientCore\GeneralUpdate.ClientCore.csproj", "{BAEFF926-6B2C-46F1-BB73-AA2AB1355565}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeneralUpdate.Differential", "GeneralUpdate.Differential\GeneralUpdate.Differential.csproj", "{40BDA496-7614-4213-92D0-3B1B187675D3}" 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{74BE0282-A10D-4A81-A0F0-FAA79A6152B7}" 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeneralUpdate.Upgrad", "GeneralUpdate.Upgrad\GeneralUpdate.Upgrad.csproj", "{E1F9FF93-CA63-4A9C-82F0-450F09ED81F9}" 17 | EndProject 18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeneralUpdate.Client", "GeneralUpdate.Client\GeneralUpdate.Client.csproj", "{7779FB4A-D121-48CC-B033-C3D36BD5D4FF}" 19 | EndProject 20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeneralUpdate.Common", "GeneralUpdate.Common\GeneralUpdate.Common.csproj", "{D14E59CD-404B-467B-9C6D-91EFC5994D37}" 21 | EndProject 22 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeneralUpdate.Bowl", "GeneralUpdate.Bowl\GeneralUpdate.Bowl.csproj", "{49D0687D-1321-48E9-84C3-936B10532367}" 23 | EndProject 24 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Generalupdate.CatBowl", "Generalupdate.CatBowl\Generalupdate.CatBowl.csproj", "{1BA0EEDF-D75A-49E9-9244-EA32DFA130B3}" 25 | EndProject 26 | Global 27 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 28 | Debug|Any CPU = Debug|Any CPU 29 | Release|Any CPU = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 32 | {35BFF228-5EE4-49A6-B721-FB0122E967A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {35BFF228-5EE4-49A6-B721-FB0122E967A0}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {35BFF228-5EE4-49A6-B721-FB0122E967A0}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {35BFF228-5EE4-49A6-B721-FB0122E967A0}.Release|Any CPU.Build.0 = Release|Any CPU 36 | {BAEFF926-6B2C-46F1-BB73-AA2AB1355565}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {BAEFF926-6B2C-46F1-BB73-AA2AB1355565}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {BAEFF926-6B2C-46F1-BB73-AA2AB1355565}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {BAEFF926-6B2C-46F1-BB73-AA2AB1355565}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {40BDA496-7614-4213-92D0-3B1B187675D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 41 | {40BDA496-7614-4213-92D0-3B1B187675D3}.Debug|Any CPU.Build.0 = Debug|Any CPU 42 | {40BDA496-7614-4213-92D0-3B1B187675D3}.Release|Any CPU.ActiveCfg = Release|Any CPU 43 | {40BDA496-7614-4213-92D0-3B1B187675D3}.Release|Any CPU.Build.0 = Release|Any CPU 44 | {E1F9FF93-CA63-4A9C-82F0-450F09ED81F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 45 | {E1F9FF93-CA63-4A9C-82F0-450F09ED81F9}.Debug|Any CPU.Build.0 = Debug|Any CPU 46 | {E1F9FF93-CA63-4A9C-82F0-450F09ED81F9}.Release|Any CPU.ActiveCfg = Release|Any CPU 47 | {E1F9FF93-CA63-4A9C-82F0-450F09ED81F9}.Release|Any CPU.Build.0 = Release|Any CPU 48 | {7779FB4A-D121-48CC-B033-C3D36BD5D4FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 49 | {7779FB4A-D121-48CC-B033-C3D36BD5D4FF}.Debug|Any CPU.Build.0 = Debug|Any CPU 50 | {7779FB4A-D121-48CC-B033-C3D36BD5D4FF}.Release|Any CPU.ActiveCfg = Release|Any CPU 51 | {7779FB4A-D121-48CC-B033-C3D36BD5D4FF}.Release|Any CPU.Build.0 = Release|Any CPU 52 | {D14E59CD-404B-467B-9C6D-91EFC5994D37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 53 | {D14E59CD-404B-467B-9C6D-91EFC5994D37}.Debug|Any CPU.Build.0 = Debug|Any CPU 54 | {D14E59CD-404B-467B-9C6D-91EFC5994D37}.Release|Any CPU.ActiveCfg = Release|Any CPU 55 | {D14E59CD-404B-467B-9C6D-91EFC5994D37}.Release|Any CPU.Build.0 = Release|Any CPU 56 | {49D0687D-1321-48E9-84C3-936B10532367}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 57 | {49D0687D-1321-48E9-84C3-936B10532367}.Debug|Any CPU.Build.0 = Debug|Any CPU 58 | {49D0687D-1321-48E9-84C3-936B10532367}.Release|Any CPU.ActiveCfg = Release|Any CPU 59 | {49D0687D-1321-48E9-84C3-936B10532367}.Release|Any CPU.Build.0 = Release|Any CPU 60 | {1BA0EEDF-D75A-49E9-9244-EA32DFA130B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 61 | {1BA0EEDF-D75A-49E9-9244-EA32DFA130B3}.Debug|Any CPU.Build.0 = Debug|Any CPU 62 | {1BA0EEDF-D75A-49E9-9244-EA32DFA130B3}.Release|Any CPU.ActiveCfg = Release|Any CPU 63 | {1BA0EEDF-D75A-49E9-9244-EA32DFA130B3}.Release|Any CPU.Build.0 = Release|Any CPU 64 | EndGlobalSection 65 | GlobalSection(SolutionProperties) = preSolution 66 | HideSolutionNode = FALSE 67 | EndGlobalSection 68 | GlobalSection(NestedProjects) = preSolution 69 | {35BFF228-5EE4-49A6-B721-FB0122E967A0} = {91F059E6-7AD3-4FB7-9604-30A7849C6EFF} 70 | {BAEFF926-6B2C-46F1-BB73-AA2AB1355565} = {91F059E6-7AD3-4FB7-9604-30A7849C6EFF} 71 | {40BDA496-7614-4213-92D0-3B1B187675D3} = {91F059E6-7AD3-4FB7-9604-30A7849C6EFF} 72 | {E1F9FF93-CA63-4A9C-82F0-450F09ED81F9} = {74BE0282-A10D-4A81-A0F0-FAA79A6152B7} 73 | {7779FB4A-D121-48CC-B033-C3D36BD5D4FF} = {74BE0282-A10D-4A81-A0F0-FAA79A6152B7} 74 | {D14E59CD-404B-467B-9C6D-91EFC5994D37} = {91F059E6-7AD3-4FB7-9604-30A7849C6EFF} 75 | {49D0687D-1321-48E9-84C3-936B10532367} = {91F059E6-7AD3-4FB7-9604-30A7849C6EFF} 76 | {1BA0EEDF-D75A-49E9-9244-EA32DFA130B3} = {74BE0282-A10D-4A81-A0F0-FAA79A6152B7} 77 | EndGlobalSection 78 | GlobalSection(ExtensibilityGlobals) = postSolution 79 | SolutionGuid = {A7B2D0AD-E000-4749-BAC0-FF21B9872805} 80 | EndGlobalSection 81 | EndGlobal 82 | -------------------------------------------------------------------------------- /src/c#/Generalupdate.CatBowl/Generalupdate.CatBowl.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net9.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/c#/Generalupdate.CatBowl/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Text; 3 | using GeneralUpdate.Bowl; 4 | using GeneralUpdate.Bowl.Strategys; 5 | 6 | namespace Generalupdate.CatBowl; 7 | 8 | class Program 9 | { 10 | static void Main(string[] args) 11 | { 12 | var installPath = AppDomain.CurrentDomain.BaseDirectory; 13 | var lastVersion = "1.0.0.3"; 14 | var processInfo = new MonitorParameter 15 | { 16 | ProcessNameOrId = "JsonTest.exe", 17 | DumpFileName = $"{lastVersion}_fail.dmp", 18 | FailFileName = $"{lastVersion}_fail.json", 19 | TargetPath = installPath, 20 | FailDirectory = Path.Combine(installPath, "fail", lastVersion), 21 | BackupDirectory = Path.Combine(installPath, lastVersion), 22 | WorkModel = "Normal" 23 | }; 24 | Bowl.Launch(processInfo); 25 | 26 | /*var source = @"D:\packet\release"; 27 | var target = @"D:\packet\1.zip"; 28 | CompressProvider.Compress(Format.ZIP,source,target, false, Encoding.UTF8); 29 | CompressProvider.Decompress(Format.ZIP,target,source, Encoding.UTF8); 30 | Console.WriteLine($"Done {File.Exists(target)}");*/ 31 | 32 | Console.Read(); 33 | } 34 | } --------------------------------------------------------------------------------