using System.Text.Json; using WindowsToolbox.Core; using WindowsToolbox.Infrastructure; var failures = new List(); Check(ToolboxCommandDispatcher.RequiresElevation(ToolboxCommandKind.DisableWindowsUpdate), "关闭更新必须提权"); Check(!ToolboxCommandDispatcher.RequiresElevation(ToolboxCommandKind.ArchiveDesktop), "桌面归档不应要求提权"); var command = new ToolboxCommand { Id = "verification", Kind = ToolboxCommandKind.PauseWindowsUpdate, Arguments = new Dictionary { ["days"] = "35" } }; var roundTrip = JsonSerializer.Deserialize( JsonSerializer.Serialize(command, JsonDefaults.Options), JsonDefaults.Options); Check(roundTrip?.Kind == ToolboxCommandKind.PauseWindowsUpdate, "命令 JSON 往返失败"); Check(roundTrip?.Arguments.GetValueOrDefault("days") == "35", "命令参数 JSON 往返失败"); var activation = new ActivationService(new RegistryStore(), new SnapshotStore(), new ProcessRunner()); var catalog = activation.LoadCatalog(); Check(catalog.Any(x => x.EditionId == "Professional" && x.ProductKey == "W269N-WFGWX-YVC9B-4J6C9-T83GX"), "KMS 专业版目录缺失"); Check(catalog.Any(x => x.EditionId == "Core" && !x.Supported), "家庭版应明确标记为不支持 KMS"); Check(catalog.Where(x => x.Supported).All(x => x.ProductKey.Length == 29), "KMS 客户端密钥格式错误"); var temporaryRoot = Path.Combine(Path.GetTempPath(), "WindowsToolbox-Verification-" + Guid.NewGuid().ToString("N")); try { var testDesktop = Path.Combine(temporaryRoot, "Desktop"); var testDestination = Path.Combine(temporaryRoot, "Archive"); Directory.CreateDirectory(testDesktop); File.WriteAllText(Path.Combine(testDesktop, "report.txt"), "first"); File.WriteAllText(Path.Combine(testDesktop, "keep.lnk"), "shortcut"); var projectFolder = Path.Combine(testDesktop, "Project"); Directory.CreateDirectory(projectFolder); File.WriteAllText(Path.Combine(projectFolder, "first.txt"), "folder-first"); var systemFolder = Path.Combine(testDesktop, "SystemFolder"); Directory.CreateDirectory(systemFolder); File.SetAttributes(systemFolder, File.GetAttributes(systemFolder) | FileAttributes.System); var desktopService = new DesktopArchiveService( new TaskSchedulerService(), () => testDesktop, Path.Combine(temporaryRoot, "Data")); var archiveCommand = new ToolboxCommand { Id = Guid.NewGuid().ToString("N"), Kind = ToolboxCommandKind.ArchiveDesktop, Arguments = new Dictionary { ["profile"] = "verification", ["destination"] = testDestination } }; var firstArchive = await desktopService.ArchiveAsync(archiveCommand); var dateFolder = Path.Combine(testDestination, DateTime.Now.ToString("yyyy-MM-dd")); Check(firstArchive.Success, "第一次桌面归档失败"); Check(File.Exists(Path.Combine(dateFolder, "report.txt")), "普通文件没有归档"); Check(File.Exists(Path.Combine(testDesktop, "keep.lnk")), "快捷方式不应被移动"); Check(Directory.Exists(Path.Combine(dateFolder, "Project")), "普通文件夹没有归档"); Check(Directory.Exists(systemFolder), "系统文件夹不应被移动"); await Task.Delay(5); File.WriteAllText(Path.Combine(testDesktop, "report.txt"), "second"); Directory.CreateDirectory(projectFolder); File.WriteAllText(Path.Combine(projectFolder, "second.txt"), "folder-second"); var secondArchive = await desktopService.ArchiveAsync(archiveCommand with { Id = Guid.NewGuid().ToString("N") }); Check(secondArchive.Success, "第二次桌面归档失败"); Check(File.Exists(Path.Combine(dateFolder, "report (1).txt")), "同一天同名文件没有自动编号"); Check(Directory.Exists(Path.Combine(dateFolder, "Project (1)")), "同一天同名文件夹没有自动编号"); await Task.Delay(5); Directory.CreateDirectory(projectFolder); File.WriteAllText(Path.Combine(projectFolder, "third.txt"), "folder-third"); var thirdArchive = await desktopService.ArchiveAsync(archiveCommand with { Id = Guid.NewGuid().ToString("N") }); Check(thirdArchive.Success, "第三次桌面归档失败"); Check(Directory.Exists(Path.Combine(dateFolder, "Project (2)")), "多次同名文件夹没有继续自动编号"); var undo = await desktopService.UndoLatestAsync(new ToolboxCommand { Id = Guid.NewGuid().ToString("N"), Kind = ToolboxCommandKind.UndoDesktopArchive, Arguments = new Dictionary { ["profile"] = "verification" } }); Check(undo.Success, "撤销最近桌面归档失败"); Check(File.Exists(Path.Combine(testDesktop, "Project", "third.txt")), "撤销没有恢复最近一次文件夹"); Check(File.Exists(Path.Combine(dateFolder, "report.txt")), "撤销最近一次不应影响更早归档"); Check(File.Exists(Path.Combine(dateFolder, "report (1).txt")), "撤销文件夹归档不应影响更早归档文件"); Check(Directory.Exists(Path.Combine(dateFolder, "Project")), "撤销最近一次不应影响更早归档文件夹"); Check(Directory.Exists(Path.Combine(dateFolder, "Project (1)")), "撤销最近一次不应影响第二次归档文件夹"); // 下载目录整理:分类、排除、二次整理合并、撤销与 profile 过滤。 var testDownloads = Path.Combine(temporaryRoot, "Downloads"); Directory.CreateDirectory(testDownloads); File.WriteAllText(Path.Combine(testDownloads, "setup.exe"), "exe"); File.WriteAllText(Path.Combine(testDownloads, "report.pdf"), "pdf"); File.WriteAllText(Path.Combine(testDownloads, "photo.png"), "png"); File.WriteAllText(Path.Combine(testDownloads, "unknown.xyz"), "xyz"); File.WriteAllText(Path.Combine(testDownloads, "movie.mp4"), "mp4"); File.WriteAllText(Path.Combine(testDownloads, "half.crdownload"), "downloading"); File.WriteAllText(Path.Combine(testDownloads, "desktop.ini"), "ini"); var extractedFolder = Path.Combine(testDownloads, "Extracted"); Directory.CreateDirectory(extractedFolder); File.WriteAllText(Path.Combine(extractedFolder, "inner.txt"), "inner"); var oldDateFolder = Path.Combine(testDownloads, "2020-01-01"); Directory.CreateDirectory(oldDateFolder); var downloadsService = new DownloadsTidyService( new TaskSchedulerService(), () => testDownloads, Path.Combine(temporaryRoot, "Data")); var tidyCommand = new ToolboxCommand { Id = Guid.NewGuid().ToString("N"), Kind = ToolboxCommandKind.TidyDownloads, Arguments = new Dictionary { ["profile"] = "downloads" } }; var firstTidy = await downloadsService.TidyAsync(tidyCommand); var downloadsDateFolder = Path.Combine(testDownloads, DateTime.Now.ToString("yyyy-MM-dd")); Check(firstTidy.Success, "第一次下载目录整理失败"); Check(File.Exists(Path.Combine(downloadsDateFolder, "安装包", "setup.exe")), "安装包没有进入类型目录"); Check(File.Exists(Path.Combine(downloadsDateFolder, "文档", "report.pdf")), "文档没有进入类型目录"); Check(File.Exists(Path.Combine(downloadsDateFolder, "图片", "photo.png")), "图片没有进入类型目录"); Check(File.Exists(Path.Combine(downloadsDateFolder, "视频", "movie.mp4")), "视频没有进入类型目录"); Check(File.Exists(Path.Combine(downloadsDateFolder, "其他", "unknown.xyz")), "未识别类型没有进入其他目录"); Check(Directory.Exists(Path.Combine(downloadsDateFolder, "Extracted")), "文件夹没有进入日期目录根"); Check(File.Exists(Path.Combine(testDownloads, "half.crdownload")), "下载中的临时文件不应被移动"); Check(File.Exists(Path.Combine(testDownloads, "desktop.ini")), "desktop.ini 不应被移动"); Check(Directory.Exists(oldDateFolder), "日期格式的旧整理目录不应被移动"); await Task.Delay(5); File.WriteAllText(Path.Combine(testDownloads, "setup.exe"), "exe-second"); File.WriteAllText(Path.Combine(testDownloads, "report.pdf"), "pdf-second"); var secondTidy = await downloadsService.TidyAsync(tidyCommand with { Id = Guid.NewGuid().ToString("N") }); Check(secondTidy.Success, "第二次下载目录整理失败"); Check(File.Exists(Path.Combine(downloadsDateFolder, "安装包", "setup (1).exe")), "同日同名文件没有自动编号"); Check(File.Exists(Path.Combine(downloadsDateFolder, "文档", "report (1).pdf")), "同日同名文档没有自动编号"); var emptyDownloads = Path.Combine(temporaryRoot, "EmptyDownloads"); Directory.CreateDirectory(emptyDownloads); var emptyService = new DownloadsTidyService( new TaskSchedulerService(), () => emptyDownloads, Path.Combine(temporaryRoot, "Data")); var emptyTidy = await emptyService.TidyAsync(tidyCommand with { Id = Guid.NewGuid().ToString("N") }); Check(emptyTidy.Success, "空目录整理应成功返回"); Check(!Directory.Exists(Path.Combine(emptyDownloads, DateTime.Now.ToString("yyyy-MM-dd"))), "空目录整理不应创建日期目录"); // 撤销按 profile 过滤:先制造一个更新的桌面清单,下载撤销必须仍找下载清单。 File.WriteAllText(Path.Combine(testDesktop, "filter-test.txt"), "filter"); var desktopFilterArchive = await desktopService.ArchiveAsync(archiveCommand with { Id = Guid.NewGuid().ToString("N") }); Check(desktopFilterArchive.Success, "桌面归档(过滤测试前置)失败"); var undoDownloads = await downloadsService.UndoLatestAsync(new ToolboxCommand { Id = Guid.NewGuid().ToString("N"), Kind = ToolboxCommandKind.UndoDownloadsTidy }); Check(undoDownloads.Success, "撤销最近一次下载整理失败"); Check(File.Exists(Path.Combine(testDownloads, "setup.exe")), "撤销没有恢复最近整理的文件"); Check(File.Exists(Path.Combine(testDownloads, "report.pdf")), "撤销没有恢复最近整理的文档"); Check(File.Exists(Path.Combine(downloadsDateFolder, "安装包", "setup.exe")), "撤销最近一次不应影响更早整理的文件"); Check(Directory.Exists(Path.Combine(downloadsDateFolder, "Extracted")), "撤销最近一次不应影响更早整理的文件夹"); Check(File.Exists(Path.Combine(dateFolder, "filter-test.txt")), "下载撤销不应影响桌面归档内容"); var undoDesktopAfterFilter = await desktopService.UndoLatestAsync(new ToolboxCommand { Id = Guid.NewGuid().ToString("N"), Kind = ToolboxCommandKind.UndoDesktopArchive, Arguments = new Dictionary { ["profile"] = "verification" } }); Check(undoDesktopAfterFilter.Success, "下载撤销后桌面撤销失败"); Check(File.Exists(Path.Combine(testDesktop, "filter-test.txt")), "桌面撤销没有恢复过滤测试文件"); } finally { if (Directory.Exists(temporaryRoot)) { foreach (var path in Directory.EnumerateFileSystemEntries(temporaryRoot, "*", SearchOption.AllDirectories)) { try { File.SetAttributes(path, FileAttributes.Normal); } catch { } } Directory.Delete(temporaryRoot, recursive: true); } } if (failures.Count > 0) { Console.Error.WriteLine(string.Join(Environment.NewLine, failures)); return 1; } Console.WriteLine($"验证通过:{catalog.Count} 个 KMS 版本条目;命令模型、权限边界、桌面归档与撤销、下载目录分类整理、排除规则、同日合并和按 profile 撤销正常。"); return 0; void Check(bool condition, string message) { if (!condition) { failures.Add("失败: " + message); } }