From 60dc811337dcc1c887025cc080fc9446587afb07 Mon Sep 17 00:00:00 2001 From: iicemeta Date: Thu, 12 Mar 2026 18:46:51 +0800 Subject: [PATCH 1/7] =?UTF-8?q?ci:=20=E6=B7=BB=E5=8A=A0=20GitHub=20Actions?= =?UTF-8?q?=20=E5=8F=91=E5=B8=83=E5=B7=A5=E4=BD=9C=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加 iiCourseWPF 的自动化发布工作流,支持通过推送标签或手动触发 包含构建、测试、打包和创建 GitHub Release 等功能 --- .github/workflows/release.yml | 242 ++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..4d8b376 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,242 @@ +# GitHub Actions Release Workflow for iiCourseWPF +# 触发方式: 推送标签 v* 或手动触发 + +name: Release iiCourseWPF + +on: + # 当推送版本标签时触发 (例如: v1.0.0) + push: + tags: + - 'v*' + # 允许手动触发 + workflow_dispatch: + inputs: + version: + description: '版本号 (例如: 1.8.0)' + required: true + default: '1.8.0' + prerelease: + description: '是否为预发布版本' + type: boolean + required: false + default: false + +env: + DOTNET_VERSION: '9.0.x' + SOLUTION_PATH: 'iiCourseWPF.sln' + MAIN_PROJECT: 'iiCourseWPF/iiCourseWPF.csproj' + +jobs: + # 构建和测试 + build: + runs-on: windows-latest + outputs: + version: ${{ steps.version.outputs.version }} + assembly_version: ${{ steps.version.outputs.assembly_version }} + + steps: + # 检出代码 + - name: 检出代码 + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # 设置 .NET 9.0 + - name: 设置 .NET ${{ env.DOTNET_VERSION }} + uses: actions/setup-dotnet@v4 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + # 提取版本号 + - name: 提取版本号 + id: version + shell: pwsh + run: | + if ('${{ github.event_name }}' -eq 'workflow_dispatch') { + $version = '${{ github.event.inputs.version }}' + } else { + $tag = '${{ github.ref_name }}' + $version = $tag -replace '^v', '' + } + $assemblyVersion = "$version.0" + echo "version=$version" >> $env:GITHUB_OUTPUT + echo "assembly_version=$assemblyVersion" >> $env:GITHUB_OUTPUT + Write-Host "版本: $version" + Write-Host "程序集版本: $assemblyVersion" + + # 还原 NuGet 包 + - name: 还原 NuGet 包 + run: dotnet restore ${{ env.SOLUTION_PATH }} + + # 更新项目版本号 + - name: 更新版本号 + shell: pwsh + run: | + $version = '${{ steps.version.outputs.version }}' + $assemblyVersion = '${{ steps.version.outputs.assembly_version }}' + + # 更新主项目 + $mainProject = '${{ env.MAIN_PROJECT }}' + [xml]$xml = Get-Content $mainProject + $xml.Project.PropertyGroup.Version = $version + $xml.Project.PropertyGroup.AssemblyVersion = $assemblyVersion + $xml.Project.PropertyGroup.FileVersion = $assemblyVersion + $xml.Save($mainProject) + + # 更新 Core 项目 + $coreProject = 'iiCourse.Core/iiCourse.Core.csproj' + [xml]$xml = Get-Content $coreProject + $xml.Project.PropertyGroup.Version = $version + $xml.Project.PropertyGroup.AssemblyVersion = $assemblyVersion + $xml.Project.PropertyGroup.FileVersion = $assemblyVersion + $xml.Save($coreProject) + + Write-Host "版本号已更新为: $version" + + # 构建项目 (Release 配置) + - name: 构建项目 + run: dotnet build ${{ env.SOLUTION_PATH }} --configuration Release --no-restore + + # 运行测试 (如果有测试项目) + - name: 运行测试 + run: dotnet test ${{ env.SOLUTION_PATH }} --configuration Release --no-build --verbosity normal + continue-on-error: true + + # 发布自包含应用 (x64) + - name: 发布应用 (x64 自包含) + run: | + dotnet publish ${{ env.MAIN_PROJECT }} ` + --configuration Release ` + --runtime win-x64 ` + --self-contained true ` + --output ./publish/x64 ` + -p:PublishSingleFile=true ` + -p:IncludeNativeLibrariesForSelfExtract=true + + # 发布框架依赖应用 (x64) + - name: 发布应用 (x64 框架依赖) + run: | + dotnet publish ${{ env.MAIN_PROJECT }} ` + --configuration Release ` + --runtime win-x64 ` + --self-contained false ` + --output ./publish/x64-framework ` + -p:PublishSingleFile=true + + # 打包自包含版本 + - name: 打包自包含版本 + shell: pwsh + run: | + $version = '${{ steps.version.outputs.version }}' + Compress-Archive -Path ./publish/x64/* -DestinationPath "./iiCourseWPF-v$version-win-x64-self-contained.zip" -Force + + # 打包框架依赖版本 + - name: 打包框架依赖版本 + shell: pwsh + run: | + $version = '${{ steps.version.outputs.version }}' + Compress-Archive -Path ./publish/x64-framework/* -DestinationPath "./iiCourseWPF-v$version-win-x64-framework.zip" -Force + + # 上传构建产物 + - name: 上传构建产物 + uses: actions/upload-artifact@v4 + with: + name: release-artifacts + path: | + ./iiCourseWPF-v*.zip + retention-days: 30 + + # 创建 GitHub Release + release: + needs: build + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + # 下载构建产物 + - name: 下载构建产物 + uses: actions/download-artifact@v4 + with: + name: release-artifacts + path: ./artifacts + + # 列出构建产物 + - name: 列出构建产物 + run: ls -la ./artifacts + + # 创建 Release + - name: 创建 GitHub Release + uses: softprops/action-gh-release@v1 + with: + tag_name: ${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }} + name: ${{ github.event_name == 'workflow_dispatch' && format('iiCourseWPF v{0}', github.event.inputs.version) || format('iiCourseWPF {0}', github.ref_name) }} + body: | + ## iiCourseWPF ${{ needs.build.outputs.version }} + + ### 下载 + + | 版本 | 说明 | 文件大小 | + |------|------|----------| + | 自包含版本 | 无需安装 .NET 9 运行时 | ~50MB | + | 框架依赖版本 | 需要安装 .NET 9 运行时 | ~5MB | + + ### 安装说明 + + **自包含版本 (推荐)** + 1. 下载 `iiCourseWPF-v${{ needs.build.outputs.version }}-win-x64-self-contained.zip` + 2. 解压到任意文件夹 + 3. 运行 `iiCourseWPF.exe` + + **框架依赖版本** + 1. 先安装 [.NET 9.0 运行时](https://dotnet.microsoft.com/download/dotnet/9.0) + 2. 下载 `iiCourseWPF-v${{ needs.build.outputs.version }}-win-x64-framework.zip` + 3. 解压到任意文件夹 + 4. 运行 `iiCourseWPF.exe` + + ### 校验 + + 文件 SHA256 校验和可在发布页面查看。 + + --- + **完整更新日志**: 参见 [CHANGELOG.md](./docs/changelog.md) + files: ./artifacts/*.zip + prerelease: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.prerelease || false }} + generate_release_notes: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # 生成校验和 + checksum: + needs: release + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + # 检出代码 + - name: 检出代码 + uses: actions/checkout@v4 + + # 下载构建产物 + - name: 下载构建产物 + uses: actions/download-artifact@v4 + with: + name: release-artifacts + path: ./artifacts + + # 生成校验和文件 + - name: 生成 SHA256 校验和 + run: | + cd ./artifacts + sha256sum *.zip > checksums.txt + cat checksums.txt + + # 上传校验和到 Release + - name: 上传校验和 + uses: softprops/action-gh-release@v1 + with: + tag_name: ${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }} + files: ./artifacts/checksums.txt + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 9e45646fb72668abb0ca2a3cf5091280de70ad3d Mon Sep 17 00:00:00 2001 From: iicemeta Date: Thu, 12 Mar 2026 18:59:49 +0800 Subject: [PATCH 2/7] =?UTF-8?q?ci(release):=20=E6=B7=BB=E5=8A=A0=E7=BA=AF?= =?UTF-8?q?=E6=A1=86=E6=9E=B6=E4=BE=9D=E8=B5=96=E7=89=88=E6=9C=AC=E5=8F=91?= =?UTF-8?q?=E5=B8=83=E5=92=8C=E6=89=93=E5=8C=85=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加新的发布配置用于生成纯框架依赖版本,该版本需要本地安装.NET 9运行时但体积最小。同时更新README说明文档,包含新版本的安装说明和特性对比。 --- .github/workflows/release.yml | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4d8b376..2406029 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -113,7 +113,7 @@ jobs: -p:PublishSingleFile=true ` -p:IncludeNativeLibrariesForSelfExtract=true - # 发布框架依赖应用 (x64) + # 发布框架依赖应用 (x64) - 单文件,包含运行时文件 - name: 发布应用 (x64 框架依赖) run: | dotnet publish ${{ env.MAIN_PROJECT }} ` @@ -123,6 +123,14 @@ jobs: --output ./publish/x64-framework ` -p:PublishSingleFile=true + # 发布纯框架依赖应用 - 需要本地安装 .NET 9 + - name: 发布应用 (纯框架依赖 - 需安装.NET 9) + run: | + dotnet publish ${{ env.MAIN_PROJECT }} ` + --configuration Release ` + --self-contained false ` + --output ./publish/dotnet9-required + # 打包自包含版本 - name: 打包自包含版本 shell: pwsh @@ -137,6 +145,13 @@ jobs: $version = '${{ steps.version.outputs.version }}' Compress-Archive -Path ./publish/x64-framework/* -DestinationPath "./iiCourseWPF-v$version-win-x64-framework.zip" -Force + # 打包纯框架依赖版本 (需安装 .NET 9) + - name: 打包纯框架依赖版本 + shell: pwsh + run: | + $version = '${{ steps.version.outputs.version }}' + Compress-Archive -Path ./publish/dotnet9-required/* -DestinationPath "./iiCourseWPF-v$version-dotnet9-required.zip" -Force + # 上传构建产物 - name: 上传构建产物 uses: actions/upload-artifact@v4 @@ -180,6 +195,7 @@ jobs: |------|------|----------| | 自包含版本 | 无需安装 .NET 9 运行时 | ~50MB | | 框架依赖版本 | 需要安装 .NET 9 运行时 | ~5MB | + | 纯框架依赖版本 | 必须安装 .NET 9 运行时,体积最小 | ~200KB | ### 安装说明 @@ -194,6 +210,13 @@ jobs: 3. 解压到任意文件夹 4. 运行 `iiCourseWPF.exe` + **纯框架依赖版本 (体积最小)** + 1. 先安装 [.NET 9.0 运行时](https://dotnet.microsoft.com/download/dotnet/9.0) + 2. 下载 `iiCourseWPF-v${{ needs.build.outputs.version }}-dotnet9-required.zip` + 3. 解压到任意文件夹 + 4. 运行 `iiCourseWPF.exe` + > ⚠️ 此版本不包含任何运行时文件,必须确保系统已安装 .NET 9 + ### 校验 文件 SHA256 校验和可在发布页面查看。 From f93fbeaebbd5096ded1226d73203f40db4d64f72 Mon Sep 17 00:00:00 2001 From: iicemeta Date: Thu, 12 Mar 2026 19:26:59 +0800 Subject: [PATCH 3/7] =?UTF-8?q?ci(workflow):=20=E6=B7=BB=E5=8A=A0=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=AD=BE=E5=90=8D=E5=8A=9F=E8=83=BD=E5=88=B0=E5=8F=91?= =?UTF-8?q?=E5=B8=83=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加两种代码签名方式配置: 1. 使用本地证书进行签名 2. 使用 SignPath 服务进行签名(推荐开源项目) 支持通过环境变量切换签名方式,并自动处理签名文件的替换 --- .github/workflows/release.yml | 81 +++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2406029..9dff7c0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,6 +25,12 @@ env: DOTNET_VERSION: '9.0.x' SOLUTION_PATH: 'iiCourseWPF.sln' MAIN_PROJECT: 'iiCourseWPF/iiCourseWPF.csproj' + # 代码签名配置 + # 支持两种方式: + # 1. 本地证书: 设置 CERTIFICATE_BASE64 和 CERTIFICATE_PASSWORD + # 2. SignPath: 设置 SIGNPATH_API_TOKEN (推荐开源项目) + ENABLE_LOCAL_SIGNING: ${{ secrets.CERTIFICATE_BASE64 != '' }} + ENABLE_SIGNPATH: ${{ secrets.SIGNPATH_API_TOKEN != '' }} jobs: # 构建和测试 @@ -131,6 +137,81 @@ jobs: --self-contained false ` --output ./publish/dotnet9-required + # 代码签名 - 方式1: 使用本地证书 + - name: 代码签名 (本地证书) + if: env.ENABLE_LOCAL_SIGNING == 'true' + shell: pwsh + run: | + # 解码证书 + $certBytes = [Convert]::FromBase64String('${{ secrets.CERTIFICATE_BASE64 }}') + $certPath = "$env:TEMP\signing-cert.pfx" + [IO.File]::WriteAllBytes($certPath, $certBytes) + + # 签名所有可执行文件 + $executables = Get-ChildItem -Path ./publish -Recurse -Include "*.exe" -ErrorAction SilentlyContinue + foreach ($exe in $executables) { + Write-Host "正在签名: $($exe.FullName)" + & signtool.exe sign ` + /f "$certPath" ` + /p '${{ secrets.CERTIFICATE_PASSWORD }}' ` + /tr "http://timestamp.digicert.com" ` + /td sha256 ` + /fd sha256 ` + "$($exe.FullName)" + if ($LASTEXITCODE -ne 0) { + Write-Warning "签名失败: $($exe.FullName)" + } + } + + # 清理证书文件 + Remove-Item $certPath -Force -ErrorAction SilentlyContinue + Write-Host "本地证书签名完成" + + # 为 SignPath 打包未签名文件 + - name: 打包未签名文件 (SignPath) + if: env.ENABLE_SIGNPATH == 'true' && env.ENABLE_LOCAL_SIGNING != 'true' + shell: pwsh + run: | + # 打包所有待签名文件 + Compress-Archive -Path ./publish/x64/iiCourseWPF.exe -DestinationPath "./unsigned-artifact.zip" -Force + Write-Host "未签名文件已打包" + + # 上传未签名文件供 SignPath 使用 + - name: 上传未签名文件 + if: env.ENABLE_SIGNPATH == 'true' && env.ENABLE_LOCAL_SIGNING != 'true' + uses: actions/upload-artifact@v4 + with: + name: unsigned-artifact + path: ./unsigned-artifact.zip + retention-days: 1 + + # 代码签名 - 方式2: 使用 SignPath (推荐开源项目) + - name: 代码签名 (SignPath) + if: env.ENABLE_SIGNPATH == 'true' && env.ENABLE_LOCAL_SIGNING != 'true' + uses: signpath/github-action-submit-signing-request@v1 + with: + api-token: '${{ secrets.SIGNPATH_API_TOKEN }}' + organization-id: '401c3aae-8e92-4497-a6fe-2572dd3c7f1f' + project-slug: 'iiCourseWPF' + signing-policy-slug: 'ReleaseSigning' + artifact-configuration-slug: '${{ secrets.SIGNPATH_ARTIFACT_CONFIGURATION_SLUG }}' + github-artifact-name: 'unsigned-artifact' + wait-for-completion: true + output-artifact-directory: './publish/signed' + + # 如果使用了 SignPath,替换为签名后的文件 + - name: 替换为签名文件 (SignPath) + if: env.ENABLE_SIGNPATH == 'true' && env.ENABLE_LOCAL_SIGNING != 'true' + shell: pwsh + run: | + # 解压签名后的文件 + if (Test-Path './publish/signed/unsigned-artifact.zip') { + Expand-Archive -Path './publish/signed/unsigned-artifact.zip' -DestinationPath './publish/signed-extracted' -Force + # 复制签名后的 exe 到原位置 + Copy-Item -Path './publish/signed-extracted/iiCourseWPF.exe' -Destination './publish/x64/iiCourseWPF.exe' -Force + Write-Host "已替换为 SignPath 签名文件" + } + # 打包自包含版本 - name: 打包自包含版本 shell: pwsh From 059dbf06183d964bed05c3918b4fb1d91ce476bd Mon Sep 17 00:00:00 2001 From: iicemeta Date: Thu, 12 Mar 2026 19:31:30 +0800 Subject: [PATCH 4/7] =?UTF-8?q?ci(workflow):=20=E6=9B=B4=E6=96=B0=20SignPa?= =?UTF-8?q?th=20=E5=B7=A5=E4=BD=9C=E6=B5=81=E4=BB=A5=E4=BD=BF=E7=94=A8=20a?= =?UTF-8?q?rtifact-id?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改 release.yml 工作流文件,将 SignPath 步骤中的 github-artifact-name 参数替换为 github-artifact-id,确保使用正确的上传工件 ID 进行签名 --- .github/workflows/release.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9dff7c0..9f01e2d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -179,6 +179,7 @@ jobs: # 上传未签名文件供 SignPath 使用 - name: 上传未签名文件 if: env.ENABLE_SIGNPATH == 'true' && env.ENABLE_LOCAL_SIGNING != 'true' + id: upload-unsigned-artifact uses: actions/upload-artifact@v4 with: name: unsigned-artifact @@ -195,7 +196,7 @@ jobs: project-slug: 'iiCourseWPF' signing-policy-slug: 'ReleaseSigning' artifact-configuration-slug: '${{ secrets.SIGNPATH_ARTIFACT_CONFIGURATION_SLUG }}' - github-artifact-name: 'unsigned-artifact' + github-artifact-id: '${{ steps.upload-unsigned-artifact.outputs.artifact-id }}' wait-for-completion: true output-artifact-directory: './publish/signed' From cd60d33bb0097f25ad8a07bc38bba5861c145439 Mon Sep 17 00:00:00 2001 From: iicemeta Date: Thu, 12 Mar 2026 19:35:41 +0800 Subject: [PATCH 5/7] =?UTF-8?q?ci:=20=E9=87=8D=E6=9E=84=E5=8F=91=E5=B8=83?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E6=B5=81=E4=B8=BA=E5=A4=9A=E9=98=B6=E6=AE=B5?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将原有的单一构建任务拆分为五个独立阶段:构建、签名、打包发布、创建Release和生成校验和 优化签名逻辑,分离本地证书和SignPath两种签名方式 添加中间产物上传下载步骤,提高工作流可靠性 --- .github/workflows/release.yml | 177 ++++++++++++++++++++++------------ 1 file changed, 113 insertions(+), 64 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9f01e2d..c566f6c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,5 +1,6 @@ # GitHub Actions Release Workflow for iiCourseWPF # 触发方式: 推送标签 v* 或手动触发 +# 任务拆分: build → sign → release → checksum name: Release iiCourseWPF @@ -25,15 +26,9 @@ env: DOTNET_VERSION: '9.0.x' SOLUTION_PATH: 'iiCourseWPF.sln' MAIN_PROJECT: 'iiCourseWPF/iiCourseWPF.csproj' - # 代码签名配置 - # 支持两种方式: - # 1. 本地证书: 设置 CERTIFICATE_BASE64 和 CERTIFICATE_PASSWORD - # 2. SignPath: 设置 SIGNPATH_API_TOKEN (推荐开源项目) - ENABLE_LOCAL_SIGNING: ${{ secrets.CERTIFICATE_BASE64 != '' }} - ENABLE_SIGNPATH: ${{ secrets.SIGNPATH_API_TOKEN != '' }} jobs: - # 构建和测试 + # ========== Job 1: 构建 ========== build: runs-on: windows-latest outputs: @@ -119,7 +114,7 @@ jobs: -p:PublishSingleFile=true ` -p:IncludeNativeLibrariesForSelfExtract=true - # 发布框架依赖应用 (x64) - 单文件,包含运行时文件 + # 发布框架依赖应用 (x64) - name: 发布应用 (x64 框架依赖) run: | dotnet publish ${{ env.MAIN_PROJECT }} ` @@ -129,25 +124,46 @@ jobs: --output ./publish/x64-framework ` -p:PublishSingleFile=true - # 发布纯框架依赖应用 - 需要本地安装 .NET 9 - - name: 发布应用 (纯框架依赖 - 需安装.NET 9) + # 发布纯框架依赖应用 + - name: 发布应用 (纯框架依赖) run: | dotnet publish ${{ env.MAIN_PROJECT }} ` --configuration Release ` --self-contained false ` --output ./publish/dotnet9-required + # 上传未签名构建产物 + - name: 上传构建产物 (未签名) + uses: actions/upload-artifact@v4 + with: + name: unsigned-build + path: ./publish/ + retention-days: 1 + + # ========== Job 2: 签名 ========== + sign: + needs: build + runs-on: windows-latest + # 只有在有签名配置时才运行 + if: ${{ secrets.CERTIFICATE_BASE64 != '' || secrets.SIGNPATH_API_TOKEN != '' }} + + steps: + # 下载未签名构建产物 + - name: 下载构建产物 + uses: actions/download-artifact@v4 + with: + name: unsigned-build + path: ./publish/ + # 代码签名 - 方式1: 使用本地证书 - name: 代码签名 (本地证书) - if: env.ENABLE_LOCAL_SIGNING == 'true' + if: ${{ secrets.CERTIFICATE_BASE64 != '' }} shell: pwsh run: | - # 解码证书 $certBytes = [Convert]::FromBase64String('${{ secrets.CERTIFICATE_BASE64 }}') $certPath = "$env:TEMP\signing-cert.pfx" [IO.File]::WriteAllBytes($certPath, $certBytes) - # 签名所有可执行文件 $executables = Get-ChildItem -Path ./publish -Recurse -Include "*.exe" -ErrorAction SilentlyContinue foreach ($exe in $executables) { Write-Host "正在签名: $($exe.FullName)" @@ -163,22 +179,19 @@ jobs: } } - # 清理证书文件 Remove-Item $certPath -Force -ErrorAction SilentlyContinue Write-Host "本地证书签名完成" - # 为 SignPath 打包未签名文件 - - name: 打包未签名文件 (SignPath) - if: env.ENABLE_SIGNPATH == 'true' && env.ENABLE_LOCAL_SIGNING != 'true' + # 代码签名 - 方式2: 使用 SignPath + - name: 代码签名 (SignPath) + if: ${{ secrets.SIGNPATH_API_TOKEN != '' && secrets.CERTIFICATE_BASE64 == '' }} shell: pwsh run: | - # 打包所有待签名文件 + # 打包待签名文件 Compress-Archive -Path ./publish/x64/iiCourseWPF.exe -DestinationPath "./unsigned-artifact.zip" -Force - Write-Host "未签名文件已打包" - # 上传未签名文件供 SignPath 使用 - - name: 上传未签名文件 - if: env.ENABLE_SIGNPATH == 'true' && env.ENABLE_LOCAL_SIGNING != 'true' + - name: 上传未签名文件到 SignPath + if: ${{ secrets.SIGNPATH_API_TOKEN != '' && secrets.CERTIFICATE_BASE64 == '' }} id: upload-unsigned-artifact uses: actions/upload-artifact@v4 with: @@ -186,9 +199,8 @@ jobs: path: ./unsigned-artifact.zip retention-days: 1 - # 代码签名 - 方式2: 使用 SignPath (推荐开源项目) - - name: 代码签名 (SignPath) - if: env.ENABLE_SIGNPATH == 'true' && env.ENABLE_LOCAL_SIGNING != 'true' + - name: 提交 SignPath 签名请求 + if: ${{ secrets.SIGNPATH_API_TOKEN != '' && secrets.CERTIFICATE_BASE64 == '' }} uses: signpath/github-action-submit-signing-request@v1 with: api-token: '${{ secrets.SIGNPATH_API_TOKEN }}' @@ -200,76 +212,113 @@ jobs: wait-for-completion: true output-artifact-directory: './publish/signed' - # 如果使用了 SignPath,替换为签名后的文件 - - name: 替换为签名文件 (SignPath) - if: env.ENABLE_SIGNPATH == 'true' && env.ENABLE_LOCAL_SIGNING != 'true' + - name: 替换为 SignPath 签名文件 + if: ${{ secrets.SIGNPATH_API_TOKEN != '' && secrets.CERTIFICATE_BASE64 == '' }} shell: pwsh run: | - # 解压签名后的文件 if (Test-Path './publish/signed/unsigned-artifact.zip') { Expand-Archive -Path './publish/signed/unsigned-artifact.zip' -DestinationPath './publish/signed-extracted' -Force - # 复制签名后的 exe 到原位置 Copy-Item -Path './publish/signed-extracted/iiCourseWPF.exe' -Destination './publish/x64/iiCourseWPF.exe' -Force Write-Host "已替换为 SignPath 签名文件" } - # 打包自包含版本 - - name: 打包自包含版本 - shell: pwsh - run: | - $version = '${{ steps.version.outputs.version }}' - Compress-Archive -Path ./publish/x64/* -DestinationPath "./iiCourseWPF-v$version-win-x64-self-contained.zip" -Force + # 上传签名后的构建产物 + - name: 上传签名构建产物 + uses: actions/upload-artifact@v4 + with: + name: signed-build + path: ./publish/ + retention-days: 1 - # 打包框架依赖版本 - - name: 打包框架依赖版本 + # ========== Job 3: 打包和发布 ========== + release: + needs: sign + runs-on: windows-latest + if: always() && (needs.sign.result == 'success' || needs.sign.result == 'skipped') + + steps: + # 下载签名后的构建产物 (如果签名成功) + - name: 下载签名构建产物 + if: needs.sign.result == 'success' + uses: actions/download-artifact@v4 + with: + name: signed-build + path: ./publish/ + + # 下载未签名构建产物 (如果签名被跳过) + - name: 下载未签名构建产物 + if: needs.sign.result == 'skipped' + uses: actions/download-artifact@v4 + with: + name: unsigned-build + path: ./publish/ + + # 获取版本号 + - name: 获取版本号 + id: version shell: pwsh run: | - $version = '${{ steps.version.outputs.version }}' - Compress-Archive -Path ./publish/x64-framework/* -DestinationPath "./iiCourseWPF-v$version-win-x64-framework.zip" -Force + if ('${{ github.event_name }}' -eq 'workflow_dispatch') { + $version = '${{ github.event.inputs.version }}' + } else { + $tag = '${{ github.ref_name }}' + $version = $tag -replace '^v', '' + } + echo "version=$version" >> $env:GITHUB_OUTPUT + Write-Host "版本: $version" - # 打包纯框架依赖版本 (需安装 .NET 9) - - name: 打包纯框架依赖版本 + # 打包所有版本 + - name: 打包所有版本 shell: pwsh run: | $version = '${{ steps.version.outputs.version }}' + Compress-Archive -Path ./publish/x64/* -DestinationPath "./iiCourseWPF-v$version-win-x64-self-contained.zip" -Force + Compress-Archive -Path ./publish/x64-framework/* -DestinationPath "./iiCourseWPF-v$version-win-x64-framework.zip" -Force Compress-Archive -Path ./publish/dotnet9-required/* -DestinationPath "./iiCourseWPF-v$version-dotnet9-required.zip" -Force + Write-Host "打包完成" - # 上传构建产物 - - name: 上传构建产物 + # 上传发布产物 + - name: 上传发布产物 uses: actions/upload-artifact@v4 with: name: release-artifacts - path: | - ./iiCourseWPF-v*.zip + path: ./iiCourseWPF-v*.zip retention-days: 30 - # 创建 GitHub Release - release: - needs: build + # ========== Job 4: 创建 GitHub Release ========== + create-release: + needs: release runs-on: ubuntu-latest permissions: contents: write steps: - # 下载构建产物 - - name: 下载构建产物 + # 下载发布产物 + - name: 下载发布产物 uses: actions/download-artifact@v4 with: name: release-artifacts path: ./artifacts - # 列出构建产物 - - name: 列出构建产物 - run: ls -la ./artifacts - - # 创建 Release + # 获取版本号 + - name: 获取版本号 + id: version + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT + else + version=$(echo "${{ github.ref_name }}" | sed 's/^v//') + echo "version=$version" >> $GITHUB_OUTPUT + fi + + # 创建 GitHub Release - name: 创建 GitHub Release uses: softprops/action-gh-release@v1 with: tag_name: ${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }} name: ${{ github.event_name == 'workflow_dispatch' && format('iiCourseWPF v{0}', github.event.inputs.version) || format('iiCourseWPF {0}', github.ref_name) }} body: | - ## iiCourseWPF ${{ needs.build.outputs.version }} + ## iiCourseWPF ${{ steps.version.outputs.version }} ### 下载 @@ -282,19 +331,19 @@ jobs: ### 安装说明 **自包含版本 (推荐)** - 1. 下载 `iiCourseWPF-v${{ needs.build.outputs.version }}-win-x64-self-contained.zip` + 1. 下载 `iiCourseWPF-v${{ steps.version.outputs.version }}-win-x64-self-contained.zip` 2. 解压到任意文件夹 3. 运行 `iiCourseWPF.exe` **框架依赖版本** 1. 先安装 [.NET 9.0 运行时](https://dotnet.microsoft.com/download/dotnet/9.0) - 2. 下载 `iiCourseWPF-v${{ needs.build.outputs.version }}-win-x64-framework.zip` + 2. 下载 `iiCourseWPF-v${{ steps.version.outputs.version }}-win-x64-framework.zip` 3. 解压到任意文件夹 4. 运行 `iiCourseWPF.exe` **纯框架依赖版本 (体积最小)** 1. 先安装 [.NET 9.0 运行时](https://dotnet.microsoft.com/download/dotnet/9.0) - 2. 下载 `iiCourseWPF-v${{ needs.build.outputs.version }}-dotnet9-required.zip` + 2. 下载 `iiCourseWPF-v${{ steps.version.outputs.version }}-dotnet9-required.zip` 3. 解压到任意文件夹 4. 运行 `iiCourseWPF.exe` > ⚠️ 此版本不包含任何运行时文件,必须确保系统已安装 .NET 9 @@ -311,9 +360,9 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # 生成校验和 + # ========== Job 5: 生成校验和 ========== checksum: - needs: release + needs: create-release runs-on: ubuntu-latest permissions: contents: write @@ -323,8 +372,8 @@ jobs: - name: 检出代码 uses: actions/checkout@v4 - # 下载构建产物 - - name: 下载构建产物 + # 下载发布产物 + - name: 下载发布产物 uses: actions/download-artifact@v4 with: name: release-artifacts From 49db1265a14f65345f2ee9a648b7839ea6e2ac1c Mon Sep 17 00:00:00 2001 From: iicemeta Date: Thu, 12 Mar 2026 19:41:43 +0800 Subject: [PATCH 6/7] =?UTF-8?q?ci:=20=E7=AE=80=E5=8C=96=E5=8F=91=E5=B8=83?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=B9=B6=E6=B7=BB=E5=8A=A0=20ARM64=20?= =?UTF-8?q?=E5=92=8C=20x86=20=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移除签名步骤,简化发布工作流 添加 ARM64 和 x86 架构的自包含和框架依赖版本 更新发布说明文档以包含新架构的安装说明 --- .github/workflows/release.yml | 202 +++++++++++++++------------------- 1 file changed, 87 insertions(+), 115 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c566f6c..45fc78b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,6 @@ # GitHub Actions Release Workflow for iiCourseWPF # 触发方式: 推送标签 v* 或手动触发 -# 任务拆分: build → sign → release → checksum +# 任务拆分: build → release → checksum name: Release iiCourseWPF @@ -124,133 +124,75 @@ jobs: --output ./publish/x64-framework ` -p:PublishSingleFile=true - # 发布纯框架依赖应用 - - name: 发布应用 (纯框架依赖) + # 发布自包含应用 (x86) + - name: 发布应用 (x86 自包含) run: | dotnet publish ${{ env.MAIN_PROJECT }} ` --configuration Release ` - --self-contained false ` - --output ./publish/dotnet9-required - - # 上传未签名构建产物 - - name: 上传构建产物 (未签名) - uses: actions/upload-artifact@v4 - with: - name: unsigned-build - path: ./publish/ - retention-days: 1 - - # ========== Job 2: 签名 ========== - sign: - needs: build - runs-on: windows-latest - # 只有在有签名配置时才运行 - if: ${{ secrets.CERTIFICATE_BASE64 != '' || secrets.SIGNPATH_API_TOKEN != '' }} - - steps: - # 下载未签名构建产物 - - name: 下载构建产物 - uses: actions/download-artifact@v4 - with: - name: unsigned-build - path: ./publish/ + --runtime win-x86 ` + --self-contained true ` + --output ./publish/x86 ` + -p:PublishSingleFile=true ` + -p:IncludeNativeLibrariesForSelfExtract=true - # 代码签名 - 方式1: 使用本地证书 - - name: 代码签名 (本地证书) - if: ${{ secrets.CERTIFICATE_BASE64 != '' }} - shell: pwsh + # 发布框架依赖应用 (x86) + - name: 发布应用 (x86 框架依赖) run: | - $certBytes = [Convert]::FromBase64String('${{ secrets.CERTIFICATE_BASE64 }}') - $certPath = "$env:TEMP\signing-cert.pfx" - [IO.File]::WriteAllBytes($certPath, $certBytes) - - $executables = Get-ChildItem -Path ./publish -Recurse -Include "*.exe" -ErrorAction SilentlyContinue - foreach ($exe in $executables) { - Write-Host "正在签名: $($exe.FullName)" - & signtool.exe sign ` - /f "$certPath" ` - /p '${{ secrets.CERTIFICATE_PASSWORD }}' ` - /tr "http://timestamp.digicert.com" ` - /td sha256 ` - /fd sha256 ` - "$($exe.FullName)" - if ($LASTEXITCODE -ne 0) { - Write-Warning "签名失败: $($exe.FullName)" - } - } - - Remove-Item $certPath -Force -ErrorAction SilentlyContinue - Write-Host "本地证书签名完成" + dotnet publish ${{ env.MAIN_PROJECT }} ` + --configuration Release ` + --runtime win-x86 ` + --self-contained false ` + --output ./publish/x86-framework ` + -p:PublishSingleFile=true - # 代码签名 - 方式2: 使用 SignPath - - name: 代码签名 (SignPath) - if: ${{ secrets.SIGNPATH_API_TOKEN != '' && secrets.CERTIFICATE_BASE64 == '' }} - shell: pwsh + # 发布自包含应用 (ARM64) + - name: 发布应用 (ARM64 自包含) run: | - # 打包待签名文件 - Compress-Archive -Path ./publish/x64/iiCourseWPF.exe -DestinationPath "./unsigned-artifact.zip" -Force + dotnet publish ${{ env.MAIN_PROJECT }} ` + --configuration Release ` + --runtime win-arm64 ` + --self-contained true ` + --output ./publish/arm64 ` + -p:PublishSingleFile=true ` + -p:IncludeNativeLibrariesForSelfExtract=true - - name: 上传未签名文件到 SignPath - if: ${{ secrets.SIGNPATH_API_TOKEN != '' && secrets.CERTIFICATE_BASE64 == '' }} - id: upload-unsigned-artifact - uses: actions/upload-artifact@v4 - with: - name: unsigned-artifact - path: ./unsigned-artifact.zip - retention-days: 1 + # 发布框架依赖应用 (ARM64) + - name: 发布应用 (ARM64 框架依赖) + run: | + dotnet publish ${{ env.MAIN_PROJECT }} ` + --configuration Release ` + --runtime win-arm64 ` + --self-contained false ` + --output ./publish/arm64-framework ` + -p:PublishSingleFile=true - - name: 提交 SignPath 签名请求 - if: ${{ secrets.SIGNPATH_API_TOKEN != '' && secrets.CERTIFICATE_BASE64 == '' }} - uses: signpath/github-action-submit-signing-request@v1 - with: - api-token: '${{ secrets.SIGNPATH_API_TOKEN }}' - organization-id: '401c3aae-8e92-4497-a6fe-2572dd3c7f1f' - project-slug: 'iiCourseWPF' - signing-policy-slug: 'ReleaseSigning' - artifact-configuration-slug: '${{ secrets.SIGNPATH_ARTIFACT_CONFIGURATION_SLUG }}' - github-artifact-id: '${{ steps.upload-unsigned-artifact.outputs.artifact-id }}' - wait-for-completion: true - output-artifact-directory: './publish/signed' - - - name: 替换为 SignPath 签名文件 - if: ${{ secrets.SIGNPATH_API_TOKEN != '' && secrets.CERTIFICATE_BASE64 == '' }} - shell: pwsh + # 发布纯框架依赖应用 + - name: 发布应用 (纯框架依赖) run: | - if (Test-Path './publish/signed/unsigned-artifact.zip') { - Expand-Archive -Path './publish/signed/unsigned-artifact.zip' -DestinationPath './publish/signed-extracted' -Force - Copy-Item -Path './publish/signed-extracted/iiCourseWPF.exe' -Destination './publish/x64/iiCourseWPF.exe' -Force - Write-Host "已替换为 SignPath 签名文件" - } + dotnet publish ${{ env.MAIN_PROJECT }} ` + --configuration Release ` + --self-contained false ` + --output ./publish/dotnet9-required - # 上传签名后的构建产物 - - name: 上传签名构建产物 + # 上传构建产物 + - name: 上传构建产物 uses: actions/upload-artifact@v4 with: - name: signed-build + name: build-artifacts path: ./publish/ retention-days: 1 - # ========== Job 3: 打包和发布 ========== + # ========== Job 2: 打包和发布 ========== release: - needs: sign + needs: build runs-on: windows-latest - if: always() && (needs.sign.result == 'success' || needs.sign.result == 'skipped') steps: - # 下载签名后的构建产物 (如果签名成功) - - name: 下载签名构建产物 - if: needs.sign.result == 'success' - uses: actions/download-artifact@v4 - with: - name: signed-build - path: ./publish/ - - # 下载未签名构建产物 (如果签名被跳过) - - name: 下载未签名构建产物 - if: needs.sign.result == 'skipped' + # 下载构建产物 + - name: 下载构建产物 uses: actions/download-artifact@v4 with: - name: unsigned-build + name: build-artifacts path: ./publish/ # 获取版本号 @@ -274,6 +216,10 @@ jobs: $version = '${{ steps.version.outputs.version }}' Compress-Archive -Path ./publish/x64/* -DestinationPath "./iiCourseWPF-v$version-win-x64-self-contained.zip" -Force Compress-Archive -Path ./publish/x64-framework/* -DestinationPath "./iiCourseWPF-v$version-win-x64-framework.zip" -Force + Compress-Archive -Path ./publish/x86/* -DestinationPath "./iiCourseWPF-v$version-win-x86-self-contained.zip" -Force + Compress-Archive -Path ./publish/x86-framework/* -DestinationPath "./iiCourseWPF-v$version-win-x86-framework.zip" -Force + Compress-Archive -Path ./publish/arm64/* -DestinationPath "./iiCourseWPF-v$version-win-arm64-self-contained.zip" -Force + Compress-Archive -Path ./publish/arm64-framework/* -DestinationPath "./iiCourseWPF-v$version-win-arm64-framework.zip" -Force Compress-Archive -Path ./publish/dotnet9-required/* -DestinationPath "./iiCourseWPF-v$version-dotnet9-required.zip" -Force Write-Host "打包完成" @@ -285,7 +231,7 @@ jobs: path: ./iiCourseWPF-v*.zip retention-days: 30 - # ========== Job 4: 创建 GitHub Release ========== + # ========== Job 3: 创建 GitHub Release ========== create-release: needs: release runs-on: ubuntu-latest @@ -322,25 +268,51 @@ jobs: ### 下载 - | 版本 | 说明 | 文件大小 | - |------|------|----------| - | 自包含版本 | 无需安装 .NET 9 运行时 | ~50MB | - | 框架依赖版本 | 需要安装 .NET 9 运行时 | ~5MB | - | 纯框架依赖版本 | 必须安装 .NET 9 运行时,体积最小 | ~200KB | + | 版本 | 架构 | 说明 | 文件大小 | + |------|------|------|----------| + | 自包含版本 (x64) | x64 | 无需安装 .NET 9 运行时 | ~50MB | + | 框架依赖版本 (x64) | x64 | 需要安装 .NET 9 运行时 | ~5MB | + | 自包含版本 (x86) | x86 | 无需安装 .NET 9 运行时 | ~45MB | + | 框架依赖版本 (x86) | x86 | 需要安装 .NET 9 运行时 | ~4MB | + | 自包含版本 (ARM64) | ARM64 | 无需安装 .NET 9 运行时 | ~45MB | + | 框架依赖版本 (ARM64) | ARM64 | 需要安装 .NET 9 运行时 | ~4MB | + | 纯框架依赖版本 | 任意 | 必须安装 .NET 9 运行时,体积最小 | ~200KB | ### 安装说明 - **自包含版本 (推荐)** + **自包含版本 x64 (推荐)** 1. 下载 `iiCourseWPF-v${{ steps.version.outputs.version }}-win-x64-self-contained.zip` 2. 解压到任意文件夹 3. 运行 `iiCourseWPF.exe` - **框架依赖版本** + **框架依赖版本 x64** 1. 先安装 [.NET 9.0 运行时](https://dotnet.microsoft.com/download/dotnet/9.0) 2. 下载 `iiCourseWPF-v${{ steps.version.outputs.version }}-win-x64-framework.zip` 3. 解压到任意文件夹 4. 运行 `iiCourseWPF.exe` + **自包含版本 x86** + 1. 下载 `iiCourseWPF-v${{ steps.version.outputs.version }}-win-x86-self-contained.zip` + 2. 解压到任意文件夹 + 3. 运行 `iiCourseWPF.exe` + + **框架依赖版本 x86** + 1. 先安装 [.NET 9.0 运行时](https://dotnet.microsoft.com/download/dotnet/9.0) + 2. 下载 `iiCourseWPF-v${{ steps.version.outputs.version }}-win-x86-framework.zip` + 3. 解压到任意文件夹 + 4. 运行 `iiCourseWPF.exe` + + **自包含版本 ARM64 (Surface Pro X / Copilot+ PC)** + 1. 下载 `iiCourseWPF-v${{ steps.version.outputs.version }}-win-arm64-self-contained.zip` + 2. 解压到任意文件夹 + 3. 运行 `iiCourseWPF.exe` + + **框架依赖版本 ARM64** + 1. 先安装 [.NET 9.0 ARM64 运行时](https://dotnet.microsoft.com/download/dotnet/9.0) + 2. 下载 `iiCourseWPF-v${{ steps.version.outputs.version }}-win-arm64-framework.zip` + 3. 解压到任意文件夹 + 4. 运行 `iiCourseWPF.exe` + **纯框架依赖版本 (体积最小)** 1. 先安装 [.NET 9.0 运行时](https://dotnet.microsoft.com/download/dotnet/9.0) 2. 下载 `iiCourseWPF-v${{ steps.version.outputs.version }}-dotnet9-required.zip` @@ -360,7 +332,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # ========== Job 5: 生成校验和 ========== + # ========== Job 4: 生成校验和 ========== checksum: needs: create-release runs-on: ubuntu-latest From f9e6568b49e9ff248d8c9414250ce74c54b83bff Mon Sep 17 00:00:00 2001 From: iicemeta Date: Thu, 12 Mar 2026 19:45:59 +0800 Subject: [PATCH 7/7] =?UTF-8?q?docs(release):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=8F=91=E5=B8=83=E8=AF=B4=E6=98=8E=E7=9A=84=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E5=92=8C=E5=AE=89=E8=A3=85=E6=8C=87=E5=8D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 简化发布说明的结构,将下载链接直接嵌入表格中,并添加版本选择指南。移除重复的安装步骤说明,改为更简洁的"快速开始"部分。同时添加校验文件的具体下载链接。 --- .github/workflows/release.yml | 85 +++++++++++++---------------------- 1 file changed, 31 insertions(+), 54 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 45fc78b..252932b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -266,63 +266,40 @@ jobs: body: | ## iiCourseWPF ${{ steps.version.outputs.version }} - ### 下载 - - | 版本 | 架构 | 说明 | 文件大小 | - |------|------|------|----------| - | 自包含版本 (x64) | x64 | 无需安装 .NET 9 运行时 | ~50MB | - | 框架依赖版本 (x64) | x64 | 需要安装 .NET 9 运行时 | ~5MB | - | 自包含版本 (x86) | x86 | 无需安装 .NET 9 运行时 | ~45MB | - | 框架依赖版本 (x86) | x86 | 需要安装 .NET 9 运行时 | ~4MB | - | 自包含版本 (ARM64) | ARM64 | 无需安装 .NET 9 运行时 | ~45MB | - | 框架依赖版本 (ARM64) | ARM64 | 需要安装 .NET 9 运行时 | ~4MB | - | 纯框架依赖版本 | 任意 | 必须安装 .NET 9 运行时,体积最小 | ~200KB | - - ### 安装说明 - - **自包含版本 x64 (推荐)** - 1. 下载 `iiCourseWPF-v${{ steps.version.outputs.version }}-win-x64-self-contained.zip` - 2. 解压到任意文件夹 - 3. 运行 `iiCourseWPF.exe` - - **框架依赖版本 x64** - 1. 先安装 [.NET 9.0 运行时](https://dotnet.microsoft.com/download/dotnet/9.0) - 2. 下载 `iiCourseWPF-v${{ steps.version.outputs.version }}-win-x64-framework.zip` - 3. 解压到任意文件夹 - 4. 运行 `iiCourseWPF.exe` - - **自包含版本 x86** - 1. 下载 `iiCourseWPF-v${{ steps.version.outputs.version }}-win-x86-self-contained.zip` - 2. 解压到任意文件夹 - 3. 运行 `iiCourseWPF.exe` - - **框架依赖版本 x86** - 1. 先安装 [.NET 9.0 运行时](https://dotnet.microsoft.com/download/dotnet/9.0) - 2. 下载 `iiCourseWPF-v${{ steps.version.outputs.version }}-win-x86-framework.zip` - 3. 解压到任意文件夹 - 4. 运行 `iiCourseWPF.exe` - - **自包含版本 ARM64 (Surface Pro X / Copilot+ PC)** - 1. 下载 `iiCourseWPF-v${{ steps.version.outputs.version }}-win-arm64-self-contained.zip` - 2. 解压到任意文件夹 - 3. 运行 `iiCourseWPF.exe` - - **框架依赖版本 ARM64** - 1. 先安装 [.NET 9.0 ARM64 运行时](https://dotnet.microsoft.com/download/dotnet/9.0) - 2. 下载 `iiCourseWPF-v${{ steps.version.outputs.version }}-win-arm64-framework.zip` - 3. 解压到任意文件夹 - 4. 运行 `iiCourseWPF.exe` - - **纯框架依赖版本 (体积最小)** - 1. 先安装 [.NET 9.0 运行时](https://dotnet.microsoft.com/download/dotnet/9.0) - 2. 下载 `iiCourseWPF-v${{ steps.version.outputs.version }}-dotnet9-required.zip` - 3. 解压到任意文件夹 - 4. 运行 `iiCourseWPF.exe` - > ⚠️ 此版本不包含任何运行时文件,必须确保系统已安装 .NET 9 + ### 下载地址 + + **Windows (需要 Windows 10 1809+ 或 Windows 11)** + + 自包含版本(推荐,无需安装 .NET 9 运行时) + - [64位(常用)](https://github.com/${{ github.repository }}/releases/download/${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}/iiCourseWPF-v${{ steps.version.outputs.version }}-win-x64-self-contained.zip) | [32位](https://github.com/${{ github.repository }}/releases/download/${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}/iiCourseWPF-v${{ steps.version.outputs.version }}-win-x86-self-contained.zip) | [ARM64](https://github.com/${{ github.repository }}/releases/download/${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}/iiCourseWPF-v${{ steps.version.outputs.version }}-win-arm64-self-contained.zip) + + 框架依赖版本(体积较小,需先安装 [.NET 9 运行时](https://dotnet.microsoft.com/download/dotnet/9.0)) + - [64位](https://github.com/${{ github.repository }}/releases/download/${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}/iiCourseWPF-v${{ steps.version.outputs.version }}-win-x64-framework.zip) | [32位](https://github.com/${{ github.repository }}/releases/download/${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}/iiCourseWPF-v${{ steps.version.outputs.version }}-win-x86-framework.zip) | [ARM64](https://github.com/${{ github.repository }}/releases/download/${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}/iiCourseWPF-v${{ steps.version.outputs.version }}-win-arm64-framework.zip) + + 纯框架依赖版本(体积最小 ~200KB,需先安装 [.NET 9 运行时](https://dotnet.microsoft.com/download/dotnet/9.0)) + - [下载](https://github.com/${{ github.repository }}/releases/download/${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}/iiCourseWPF-v${{ steps.version.outputs.version }}-dotnet9-required.zip) + + ### 如何选择版本? + + | 版本类型 | 文件大小 | 是否需要 .NET 9 | 适用场景 | + |---------|---------|----------------|---------| + | 自包含 64位 | ~50MB | ❌ 不需要 | **大多数用户推荐**,64位 Windows | + | 自包含 32位 | ~45MB | ❌ 不需要 | 32位 Windows 系统 | + | 自包含 ARM64 | ~45MB | ❌ 不需要 | Surface Pro X、Copilot+ PC 等 ARM 设备 | + | 框架依赖 64位 | ~5MB | ✅ 需要 | 已安装 .NET 9 的 64位系统 | + | 框架依赖 32位 | ~4MB | ✅ 需要 | 已安装 .NET 9 的 32位系统 | + | 框架依赖 ARM64 | ~4MB | ✅ 需要 | 已安装 .NET 9 的 ARM 设备 | + | 纯框架依赖 | ~200KB | ✅ 必须 | 开发者或磁盘空间极紧张 | + + ### 快速开始 + + 1. **下载对应版本**(不确定就选「自包含 64位」) + 2. **解压**到任意文件夹 + 3. **运行** `iiCourseWPF.exe` ### 校验 - 文件 SHA256 校验和可在发布页面查看。 + 文件 SHA256 校验和可在发布页面查看,或下载 [checksums.txt](https://github.com/${{ github.repository }}/releases/download/${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}/checksums.txt)。 --- **完整更新日志**: 参见 [CHANGELOG.md](./docs/changelog.md)