MToolbox:基于 C# + WPF + AssemblyLoadContext 的插件化 Windows 工具箱项目

用户可借助该项目快速构建支持热更新的 Windows 工具集。它采用插件化架构,主程序通过 PluginManager 加载/卸载工具插件,利用 AssemblyLoadContext 实现隔离加载,UpdateService 支持后台检查更新与热切换。【此简介由AI生成】

分支1Tags0
文件最后提交记录最后更新时间
1 个月前
29 天前
1 个月前
1 个月前
1 个月前
1 个月前
1 个月前
1 个月前

MToolbox - Windows 工具箱

基于 C# + WPF + AssemblyLoadContext 插件化 架构的 Windows 工具箱,支持热更新。

架构概览

MToolbox.Shell (WPF 主程序) ── IToolPlugin 接口 ── 插件.dll
     │                           │
     ├── PluginManager      ──── 加载/卸载/热切换(通过 IPluginDisplay 与 UI 解耦)
     ├── PluginLoadContext  ──── 可回收 Assembly 隔离加载 + 临时文件自动清理
     └── UpdateService      ──── 后台检查更新 → HTTP 下载 → 热切换(支持 CancellationToken)
                                        │
MToolbox.WebServer (ASP.NET, linux-x64) ─┘ 提供 manifest API + 文件下载

设计原则

  • 依赖注入:使用 Microsoft.Extensions.DependencyInjection,所有服务(PluginManager、UpdateService、MainViewModel)由 DI 容器管理
  • UI 解耦IPluginDisplay 接口隔离插件管理器对 WPF UI 线程的依赖,便于单元测试
  • 共享契约UpdateManifestPluginInfo 等 DTO 统一定义在 MToolbox.Contracts 中,Shell 和 WebServer 共享
  • 单实例互斥体:使用命名 Mutex 确保单实例运行,避免进程名匹配的误判
  • 异步取消UpdateService.StartAutoCheckAsync 支持 CancellationToken,程序退出时优雅取消

项目结构

MToolbox/
├── MToolbox.sln                          # 解决方案
├── global.json                           # SDK 版本锁定(CI 一致性)
├── build.bat                             # 一键构建脚本(编译 + 打包 + 发布)
├── scripts/
│   └── setup-ci-environment.ps1          # CI 机器环境部署脚本
├── src/
│   ├── MToolbox.Contracts/               # 接口契约层(多目标:net10.0; net10.0-windows)
│   │   ├── IToolPlugin.cs                # 插件必须实现的接口(仅 windows 目标编译)
│   │   ├── Contracts/
│   │   │   ├── PluginInfo.cs             # 插件信息 DTO(Shell + WebServer 共享)
│   │   │   └── UpdateManifest.cs         # 更新清单 DTO
│   │   └── Utilities/
│   │       └── FormatUtils.cs            # 公共工具方法(FormatBytes 等)
│   ├── MToolbox.Shell/                   # 主程序 (WPF)
│   │   ├── App.xaml(.cs)                 # 应用入口(DI 容器、Mutex 单实例、崩溃日志)
│   │   ├── MainWindow.xaml(.cs)          # 主窗口(DI 构造注入、托盘 try/finally 清理)
│   │   ├── Resources/icon.ico            # 应用图标
│   │   ├── Services/
│   │   │   ├── IPluginDisplay.cs         # 插件 UI 操作接口(UI 线程隔离)
│   │   │   ├── PluginLoadContext.cs      # 插件加载上下文(隔离 Assembly、临时文件清理)
│   │   │   ├── PluginManager.cs          # 插件管理器(通过 IPluginDisplay 与 UI 交互)
│   │   │   └── UpdateService.cs          # 更新服务(CancellationToken 支持)
│   │   └── ViewModels/
│   │       ├── MainViewModel.cs          # 主视图模型(实现 IPluginDisplay)
│   │       ├── PluginItem.cs             # 插件 UI 条目模型
│   │       └── RelayCommand.cs           # 泛型 RelayCommand
│   ├── MToolbox.Tests/                   # 单元测试 (xUnit)
│   │   └── UpdateServiceTests.cs         # 版本比较、CollectUpdates 纯函数测试
│   ├── MToolbox.WebServer/               # 更新服务器 (ASP.NET)
│   │   ├── Program.cs                    # 入口:API 路由 + 静态文件服务
│   │   ├── appsettings.json              # 配置
│   │   ├── Properties/launchSettings.json
│   │   ├── Pages/
│   │   │   ├── Index.cshtml              # 插件发布管理页面
│   │   │   └── Index.cshtml.cs           # 页面模型(使用共享 DTO)
│   │   └── README.md                     # WebServer 部署文档
│   └── Plugins/
│       ├── MToolbox.Plugin.Sample/       # 示例插件
│       ├── MToolbox.Plugin.QuickActions/ # 快捷操作插件
│       └── MToolbox.Plugin.SystemInfo/   # 系统信息插件(WMI)
└── build/                                # 构建产物
    ├── Shell/                            # 主程序 (win-x64, 单文件)
    ├── WebServer/                        # 更新服务器 (linux-x64, 自包含)
    ├── Plugins/                          # 插件 DLL
    └── Server/                           # 更新服务器静态文件
        ├── manifest.json                 # 插件版本清单
        ├── shell-version.json            # 主程序版本
        ├── plugins/                      # 插件下载
        └── shell/                        # 主程序下载

快速开始

前置条件

  • .NET 10 SDK(>= 10.0.302,由 global.json 锁定)

CI 环境部署(Windows Server 2025)

全新机器一键部署编译环境:

.\scripts\setup-ci-environment.ps1

脚本会通过 winget 自动安装 .NET 10 SDK 和 Git,并验证构建是否通过。详见脚本注释

构建

# 一键构建(编译 + 打包 + 生成更新清单 + 交叉编译 WebServer)
.\build.bat

# 可通过环境变量指定更新服务器地址
set UPDATE_SERVER_BASE=http://your-server:5000
.\build.bat

构建过程(共 6 步):

步骤 说明
[1/6] 清理旧构建
[2/6] 编译全部项目
[3/6] 发布 Shell 主程序(win-x64 单文件,自包含)
[4/6] 准备更新服务器文件(生成 manifest.json、shell-version.json)
[5/6] 交叉编译 WebServer 为 linux-x64(单文件,自包含)
[6/6] 打印生成内容预览

运行测试

dotnet test src/MToolbox.Tests/

运行客户端

.\build\Shell\MToolbox.exe

部署 WebServer 到 Linux

# 1. 上传 build\WebServer\ 到 Linux 服务器
# 2. 将 build\Server\ 放在 build\WebServer\ 的同级目录
# 3. 启动
chmod +x MToolbox.WebServer
MT_WEB_URL=http://0.0.0.0:5000 ./MToolbox.WebServer

WebServer 的环境变量:

变量 说明 默认值
MT_WEB_URL 监听地址(最高优先级)
ASPNETCORE_URLS ASP.NET Core 标准监听地址
MT_SERVER_ROOT 插件文件根目录 ../Server

开发新插件

  1. src/Plugins/ 下新建 WPF 类库项目
  2. 引用 MToolbox.Contracts 项目
  3. 将输出目录设为 $(SolutionDir)build\Plugins\
  4. 实现 IToolPlugin 接口:
public class MyTool : IToolPlugin
{
    public string Id => "my.tool";
    public string Name => "我的工具";
    public string Version => "1.0.0";
    public string Description => "功能描述";
    public string Author => "作者";
    public string? Icon => null;

    public UserControl CreateView() => new MyToolView();
    public void Initialize() { /* 初始化 */ }
    public void Shutdown() { /* 清理 */ }
}

编译后 DLL 自动出现在 build\Plugins\,主程序运行时会自动发现并加载。

使用公共工具方法

MToolbox.Contracts.Utilities.FormatUtils 提供了常用的格式化方法:

using MToolbox.Contracts.Utilities;

var memStr = FormatUtils.FormatBytes(workingSet);  // "1.5 GB"

热更新工作流

开发者                   WebServer (Linux)              客户端 (Windows)
  │                          │                              │
  ├─ 编译新版本插件            │                              │
  ├─ build.bat ──────────────►│ 生成 manifest.json           │
  │                          │ /plugins/*.dll               │
  │                          │                              │
  │                          │   ◄── GET /api/plugins/manifest ──┤ UpdateService 定时轮询
  │                          │ ── 返回版本清单 ─────────────►│ 发现新版本
  │                          │                              │
  │                          │   ◄── GET /plugins/xxx.dll ─────┤ 下载新 DLL
  │                          │ ── 返回 DLL ────────────────►│
  │                          │                              ├─ Shutdown() 旧插件
  │                          │                              ├─ 卸载 AssemblyLoadContext + 清理临时文件
  │                          │                              ├─ GC.Collect()
  │                          │                              ├─ 加载新 DLL
  │                          │                              └─ 刷新 UI(用户无感知)

更新服务器 API

UpdateService 连接 WebServer 获取更新,协议如下:

GET /api/plugins/manifest

{
  "plugins": [
    {
      "id": "MToolbox.Plugin.Sample",
      "version": "2.0.0",
      "downloadUrl": "http://localhost:5000/plugins/MToolbox.Plugin.Sample.dll"
    }
  ]
}

其他端点

方法 路由 说明
GET /api/shell/version 主程序版本
GET /api/health 健康检查
GET /plugins/{filename} 下载插件 DLL
GET /shell/{filename} 下载主程序
GET / 插件发布管理页面

修改更新服务器地址

MToolbox.Shell/Services/UpdateService.cs 中修改 UpdateServerUrl 为实际地址即可。

项目介绍

用户可借助该项目快速构建支持热更新的 Windows 工具集。它采用插件化架构,主程序通过 PluginManager 加载/卸载工具插件,利用 AssemblyLoadContext 实现隔离加载,UpdateService 支持后台检查更新与热切换。【此简介由AI生成】

定制我的领域