first commit

This commit is contained in:
dong 2025-04-10 23:13:38 +08:00
commit f74f725c55
16 changed files with 1201 additions and 0 deletions

83
.gitignore vendored Normal file
View File

@ -0,0 +1,83 @@
/.github
/.idea
/.vs
/.vscode
#环境变量
.env
#构建删除
Run/*.exe
# 忽略所有obj
**/obj/**
# 已构建程序不上传
*.exe
# IDEA
Server/.idea
[Tt]humbs.db
*.DS_Store
#Visual Studio files
*.[Oo]bj
*.user
*.aps
*.pch
*.vspscc
*.vssscc
*_i.c
*_p.c
*.ncb
*.suo
*.tlb
*.tlh
*.bak
*.[Cc]ache
*.ilk
*.log
*.lib
*.sbr
*.sdf
*.opensdf
*.unsuccessfulbuild
ipch/
obj/
[Bb]in
[Dd]ebug*/
[Rr]elease*/
Ankh.NoLoad
#MonoDevelop
*.pidb
*.userprefs
#Tooling
_ReSharper*/
*.resharper
[Tt]est[Rr]esult*
*.sass-cache
#Project files
[Bb]uild/
#Subversion files
.svn
# Office Temp Files
~$*
#NuGet
packages/
#ncrunch
*ncrunch*
*crunch*.local.xml
# visual studio database projects
*.dbmdl
#Test files
*.testsettings

6
App.config Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>

120
CheckDownload.csproj Normal file
View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F4681804-7E5A-4A02-87EF-B28E34AA443B}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>CheckDownload</RootNamespace>
<AssemblyName>CheckDownload</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="DnsClient, Version=1.8.0.0, Culture=neutral, PublicKeyToken=4574bb5573c51424, processorArchitecture=MSIL">
<HintPath>packages\DnsClient.1.8.0\lib\net472\DnsClient.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.7.2">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.7.2 %28x86 和 x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

25
CheckDownload.sln Normal file
View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.13.35825.156 d17.13
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CheckDownload", "CheckDownload.csproj", "{F4681804-7E5A-4A02-87EF-B28E34AA443B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F4681804-7E5A-4A02-87EF-B28E34AA443B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F4681804-7E5A-4A02-87EF-B28E34AA443B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F4681804-7E5A-4A02-87EF-B28E34AA443B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F4681804-7E5A-4A02-87EF-B28E34AA443B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EB680316-B04E-4697-BD44-CF7E4AE2D8BD}
EndGlobalSection
EndGlobal

87
Form1.Designer.cs generated Normal file
View File

@ -0,0 +1,87 @@
namespace CheckDownload
{
partial class Update
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.Update_Text = new System.Windows.Forms.Label();
this.Update_Pro = new System.Windows.Forms.ProgressBar();
this.Status_Box = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// Update_Text
//
this.Update_Text.AutoSize = true;
this.Update_Text.Location = new System.Drawing.Point(12, 12);
this.Update_Text.Name = "Update_Text";
this.Update_Text.Size = new System.Drawing.Size(59, 12);
this.Update_Text.TabIndex = 0;
this.Update_Text.Text = "更新状态:";
//
// Update_Pro
//
this.Update_Pro.Location = new System.Drawing.Point(12, 36);
this.Update_Pro.Name = "Update_Pro";
this.Update_Pro.Size = new System.Drawing.Size(339, 23);
this.Update_Pro.TabIndex = 1;
//
// Status_Box
//
this.Status_Box.AutoSize = true;
this.Status_Box.Location = new System.Drawing.Point(72, 12);
this.Status_Box.Name = "Status_Box";
this.Status_Box.Size = new System.Drawing.Size(23, 12);
this.Status_Box.TabIndex = 2;
this.Status_Box.Text = "...";
//
// Update
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(363, 73);
this.ControlBox = false;
this.Controls.Add(this.Status_Box);
this.Controls.Add(this.Update_Pro);
this.Controls.Add(this.Update_Text);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Update";
this.Text = "自动更新";
this.Load += new System.EventHandler(this.Update_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label Update_Text;
private System.Windows.Forms.ProgressBar Update_Pro;
private System.Windows.Forms.Label Status_Box;
}
}

428
Form1.cs Normal file
View File

@ -0,0 +1,428 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace CheckDownload
{
public partial class Update : Form
{
private const string LocalMd5File = "md5.json";
private const string DnsQueryDomain = "test.file.ipoi.cn";
private const string BaseDownloadUrl = "http://localhost:8000/";
private const int MaxConcurrentDownloads = 5;
private string _onlineMd5File = "";
private int _completedFiles = 0;
public Update()
{
InitializeComponent();
ConfigureProgressBar();
}
private void ConfigureProgressBar()
{
Update_Pro.Minimum = 0;
Update_Pro.Maximum = 100;
Update_Pro.Value = 0;
Update_Pro.Step = 1;
}
public async void Update_Load(object sender, EventArgs e)
{
await UpdateFile();
this.Close();
}
private async Task UpdateFile()
{
try
{
var localData = await ReadLocalMd5File();
if (!ValidateLocalData(localData.Version, localData.Md5, localData.Data)) return;
var onlineData = await GetOnlineMd5File();
if (!ValidateOnlineData(onlineData.Version, onlineData.Md5)) return;
if (!ShouldUpdate(localData.Version, onlineData.Version)) return;
var onlineFileData = await DownloadOnlineMd5File();
if (onlineFileData == null) return;
var differences = CompareDataDifferences(localData.Data, onlineFileData);
if (differences.Count > 0)
{
await DownloadUpdatedFiles(differences);
}
ReplaceLocalMd5File();
}
catch (Exception ex)
{
UpdateStatus($"发生错误: {ex.Message}");
}
}
private bool ValidateLocalData(string version, string md5, JObject data)
{
if (string.IsNullOrEmpty(version) || string.IsNullOrEmpty(md5) || data == null)
{
UpdateStatus("本地MD5文件无效");
return false;
}
return true;
}
private bool ValidateOnlineData(string version, string md5)
{
if (string.IsNullOrEmpty(version) || string.IsNullOrEmpty(md5))
{
UpdateStatus("无法获取在线MD5信息");
return false;
}
return true;
}
private async Task<(string Version, string Md5, JObject Data)> ReadLocalMd5File()
{
try
{
UpdateStatus("读取md5.json...");
string json = await Task.Run(() => File.ReadAllText(LocalMd5File));
var obj = JObject.Parse(json);
string version = obj["version"]?.ToString();
var data = (JObject)obj["data"];
string jsonMd5 = CalculateMD5(json);
return (version, jsonMd5, data);
}
catch (Exception ex) when (ex is FileNotFoundException || ex is JsonException)
{
UpdateStatus($"读取本地MD5文件失败: {ex.Message}");
return (null, null, null);
}
}
private async Task<(string Version, string Md5)> GetOnlineMd5File()
{
try
{
UpdateStatus("解析在线md5.json...");
string responseData = await QueryDnsAsync();
string firstUnescaped = JsonConvert.DeserializeObject<string>(responseData);
var dataJson = JObject.Parse(firstUnescaped);
string version = dataJson["version"]?.ToString();
string md5 = dataJson["md5"]?.ToString();
_onlineMd5File = $"{md5}.json";
return (version, md5);
}
catch (Exception ex)
{
UpdateStatus($"获取在线MD5信息失败: {ex.Message}");
return (null, null);
}
}
private bool ShouldUpdate(string localVersion, string onlineVersion)
{
try
{
UpdateStatus("校验信息...");
var localVer = new Version(localVersion);
var onlineVer = new Version(onlineVersion);
return localVer.CompareTo(onlineVer) < 0;
}
catch (Exception ex) when (ex is FormatException || ex is ArgumentNullException)
{
UpdateStatus($"版本比较失败: {ex.Message}");
return false;
}
}
private async Task<JObject> DownloadOnlineMd5File()
{
try
{
UpdateStatus("下载在线md5.json文件...");
using (var client = new WebClient())
{
await client.DownloadFileTaskAsync(
new Uri($"{BaseDownloadUrl}MD5/{_onlineMd5File}"),
_onlineMd5File);
}
UpdateStatus("读取在线md5.json文件...");
string json = await Task.Run(() => File.ReadAllText(_onlineMd5File));
var obj = JObject.Parse(json);
return (JObject)obj["data"];
}
catch (Exception ex)
{
UpdateStatus($"下载在线MD5文件失败: {ex.Message}");
return null;
}
}
private Dictionary<string, string> CompareDataDifferences(JObject localData, JObject onlineData, string currentPath = "")
{
var differences = new Dictionary<string, string>();
foreach (var onlineProperty in onlineData.Properties())
{
string key = onlineProperty.Name;
JToken onlineValue = onlineProperty.Value;
string fullPath = string.IsNullOrEmpty(currentPath) ? key : $"{currentPath}/{key}";
if (onlineValue.Type == JTokenType.String)
{
string expectedMd5 = onlineValue.ToString();
if (ShouldDownloadFile(localData, key, expectedMd5, fullPath))
{
differences[fullPath] = expectedMd5;
}
}
else if (onlineValue.Type == JTokenType.Object)
{
JObject localSubData = GetSubData(localData, key);
var subDifferences = CompareDataDifferences(localSubData, (JObject)onlineValue, fullPath);
foreach (var diff in subDifferences)
{
differences[diff.Key] = diff.Value;
}
}
}
return differences;
}
private bool ShouldDownloadFile(JObject localData, string key, string expectedMd5, string fullPath)
{
bool fileMissing = !localData.ContainsKey(key);
bool md5Mismatch = localData.ContainsKey(key) &&
(localData[key].Type != JTokenType.String ||
localData[key].ToString() != expectedMd5);
bool physicalFileMissing = !File.Exists(Path.Combine(".", fullPath.Replace('/', '\\')));
return fileMissing || md5Mismatch || physicalFileMissing;
}
private JObject GetSubData(JObject localData, string key)
{
return localData.ContainsKey(key) && localData[key].Type == JTokenType.Object
? (JObject)localData[key]
: new JObject();
}
private async Task DownloadUpdatedFiles(Dictionary<string, string> differences)
{
Update_Pro.Maximum = differences.Count;
Update_Pro.Value = 0;
var semaphore = new SemaphoreSlim(MaxConcurrentDownloads);
var downloadTasks = new List<Task>();
foreach (var file in differences)
{
downloadTasks.Add(DownloadFileWithSemaphore(file, semaphore));
}
await Task.WhenAll(downloadTasks);
}
private async Task DownloadFileWithSemaphore(KeyValuePair<string, string> file, SemaphoreSlim semaphore)
{
await semaphore.WaitAsync();
try
{
await DownloadAndVerifyFile(file.Key, file.Value);
UpdateProgress();
}
catch (Exception ex)
{
UpdateStatus($"下载失败: {file.Key} - {ex.Message}");
}
finally
{
semaphore.Release();
}
}
private async Task DownloadAndVerifyFile(string relativePath, string expectedMd5)
{
UpdateStatus($"正在下载 ({Update_Pro.Value + 1}/{Update_Pro.Maximum}): {relativePath}");
string localPath = GetLocalPath(relativePath);
string tempPath = $"{localPath}.tmp";
EnsureDirectoryExists(localPath);
using (var client = new WebClient())
{
await client.DownloadFileTaskAsync(
new Uri($"{BaseDownloadUrl}{relativePath}"),
tempPath);
}
VerifyFileMd5(tempPath, expectedMd5, relativePath);
ReplaceExistingFile(tempPath, localPath);
}
private string GetLocalPath(string relativePath)
{
return Path.Combine(".", relativePath.Replace('/', '\\'));
}
private void EnsureDirectoryExists(string filePath)
{
string directory = Path.GetDirectoryName(filePath);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
}
private void VerifyFileMd5(string filePath, string expectedMd5, string relativePath)
{
string actualMd5 = CalculateFileMD5(filePath);
if (actualMd5 != expectedMd5)
{
File.Delete(filePath);
throw new Exception($"MD5校验失败: {relativePath}");
}
}
private void ReplaceExistingFile(string tempPath, string localPath)
{
if (File.Exists(localPath))
{
File.Delete(localPath);
}
File.Move(tempPath, localPath);
}
private void UpdateProgress()
{
this.Invoke((MethodInvoker)delegate
{
Update_Pro.Value++;
});
}
private void ReplaceLocalMd5File()
{
try
{
if (File.Exists(LocalMd5File))
{
File.Delete(LocalMd5File);
}
File.Move(_onlineMd5File, LocalMd5File);
UpdateStatus("已更新本地版本信息");
}
catch (Exception ex)
{
UpdateStatus($"更新本地版本信息失败: {ex.Message}");
}
}
private void UpdateStatus(string message)
{
this.Invoke((MethodInvoker)delegate
{
Status_Box.Text = message;
});
}
private string CalculateMD5(string input)
{
using (var md5 = MD5.Create())
{
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
}
}
private string CalculateFileMD5(string filePath)
{
using (var md5 = MD5.Create())
using (var stream = File.OpenRead(filePath))
{
byte[] hashBytes = md5.ComputeHash(stream);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
}
}
private static async Task<string> QueryDnsAsync()
{
var dohServers = new List<string>
{
"https://cloudflare-dns.com/dns-query",
"https://dns.cloudflare.com/dns-query",
"https://1.1.1.1/dns-query",
"https://1.0.0.1/dns-query",
"https://dns.google/resolve",
"https://sm2.doh.pub/dns-query",
"https://doh.pub/dns-query",
"https://dns.alidns.com/resolve",
"https://223.5.5.5/resolve",
"https://223.6.6.6/resolve",
"https://doh.360.cn/resolve"
};
using (var httpClient = new HttpClient())
{
var cts = new CancellationTokenSource();
var tasks = new List<Task<string>>();
foreach (var server in dohServers)
{
tasks.Add(QueryDnsServer(httpClient, server, cts.Token));
}
var completedTask = await Task.WhenAny(tasks);
cts.Cancel();
return await completedTask;
}
}
private static async Task<string> QueryDnsServer(HttpClient client, string server, CancellationToken token)
{
try
{
var url = $"{server}?name={DnsQueryDomain}&type=TXT";
var response = await client.GetStringAsync(url);
var jsonResponse = JObject.Parse(response);
foreach (var record in jsonResponse["Answer"])
{
string txtRecord = record["data"]?.ToString();
if (!string.IsNullOrEmpty(txtRecord))
{
return txtRecord;
}
}
return string.Empty;
}
catch
{
return string.Empty;
}
}
}
}

120
Form1.resx Normal file
View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

22
Program.cs Normal file
View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CheckDownload
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Update());
}
}
}

View File

@ -0,0 +1,33 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("CheckDownload")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CheckDownload")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("f4681804-7e5a-4a02-87ef-b28e34aa443b")]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

71
Properties/Resources.Designer.cs generated Normal file
View File

@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本: 4.0.30319.42000
//
// 对此文件的更改可能导致不正确的行为,如果
// 重新生成代码,则所做更改将丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace CheckDownload.Properties
{
/// <summary>
/// 强类型资源类,用于查找本地化字符串等。
/// </summary>
// 此类是由 StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// 返回此类使用的缓存 ResourceManager 实例。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CheckDownload.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 重写当前线程的 CurrentUICulture 属性,对
/// 使用此强类型资源类的所有资源查找执行重写。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

117
Properties/Resources.resx Normal file
View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

30
Properties/Settings.Designer.cs generated Normal file
View File

@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace CheckDownload.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

1
README.md Normal file
View File

@ -0,0 +1 @@
Check files & Download files

45
md5.json Normal file
View File

@ -0,0 +1,45 @@
{
"version": "1.0.1",
"date": {
"Admin-Keyauth-test.exe": "90e4541dd0ce570d726ef5ec7e955f1e",
"CodeDependencies.iss": "3f20c3b14eefa82dd73c4ba8c8cd16a8",
"f1c7016af6c8ca5eaad5c1ad0b8ad28b.json": "f1c7016af6c8ca5eaad5c1ad0b8ad28b",
"GKeyManager_1.4.8_test_auto.exe": "7d1eb2a411ea6e7e14bd4de40274a52f",
"main.go": "b1c53d8b985e6680cbe6b579c25a827e",
"output_test.iss": "fb17a52e4b6dd12c643cd37f61497ab6",
"new": {
"md5-a.json": "1d0cd2f12943c23201610035ca2fc53f"
},
"test": {
"aspnetcore-runtime-6.0.36-win-x86.exe": "638cd17cc32c6882fe01c56eaf003a2c",
"dockerfile": "3ac7da6188e62fd43f8b8558486fe702",
"go.mod": "4a3891b4e68630f56d57e0eca125a185",
"go.sum": "37aff3bcc4eeea1c52aa867c83670d9c",
"Login_update.exe": "d4fbcab2a61960de56c7a01c5ecace85",
"Main.exe": "af5b5d9f44f74e121b0d78e21dfe8328",
"main.go": "a725751ba669944ac36ee6a3cdcffca1",
"md5.json": "58c4bf8e5a9c77ac06eea0bbd6cf25ab",
"netcorecheck.exe": "298fa2564c44e3c1fdbc84cc76d97bd9",
"ssh.tar": "5f87ff72678afc5e15cd92d4344ff901",
"vc_redist.x86.exe": "3ca2b599c42442b57aeb07229d731d71",
"Windows6.1-KB2533623-x64.msu": "0a894c59c245dad32e6e48ecbdbc8921",
"Windows6.1-KB2533623-x86.msu": "edf1d538c85f24ec0ef0991e6b27f0d7",
"windowsdesktop-runtime-6.0.36-win-x86.exe": "9c62d5c212725b00563ca6b201326b8f",
"FIle": {
"aspnetcorev2_inprocess.dll": "a9ec468ef61b60f43cf24d4b62bef9de",
"D3DCompiler_47_cor3.dll": "5ce90e0d97f339e0cdf9873d3cb7c222",
"KeyManages.pdb": "7c1cbed9f87e556630d35f3ec9ea3092",
"Login_update.exe": "dad6b14e7a0ee41514bcbee826084b87",
"Main.exe": "1566dc18caa5ff94e84b7a0b097a1256",
"PenImc_cor3.dll": "931cf859776dbac94c5ab2f69055d9c6",
"PresentationNative_cor3.dll": "690cd2dd64ceaecc84a037835682a1ab",
"vcruntime140_cor3.dll": "9248c36666a2fec5e2a8913d6edabf80",
"wpfgfx_cor3.dll": "5fbd0fb4e2a2cc6f7ed3c6369b369ef6"
},
"utils": {
"encryptData.go": "509d003b33b915372639919f2ad6de6f"
}
},
"新建文件夹": {}
}
}

6
packages.config Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="DnsClient" version="1.8.0" targetFramework="net472" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" />
<package id="System.Buffers" version="4.5.1" targetFramework="net472" />
</packages>