自动化 NuGet 包打包与上传:完整批处理脚本详解(含 SVN 支持)

发布于:2025-05-14 ⋅ 阅读:(9) ⋅ 点赞:(0)

在大型项目中,我们常常需要定期打包多个 .csproj 项目为 NuGet 包,并上传到私有 NuGet 服务。这篇文章分享一份实战脚本,支持以下自动化流程:

  • 自动读取、更新 .csproj 文件中的 VersionPackageOutputPath 等节点;

  • 自动构建并打包为 .nupkg

  • 自动上传至私有 NuGet 源;

  • 支持 SVN 更新与提交;

  • 支持中文路径,日志分离记录成功与失败信息。

✅ 功能概览

功能点

说明

自动更新版本号

根据日期自动生成版本号,并支持手动输入

修改 .csproj

自动注入 VersionDescriptionPackageOutputPath 等必要节点

打包 NuGet

使用 dotnet pack 命令完成打包

上传 NuGet

自动上传所有打包成功的 .nupkg 包至私有源

SVN 支持

自动执行 SVN 更新并提交修改

日志清晰分离

success_log.txterror_log.txtsvn_commit_list.txt 等日志文件帮助排查问题


📦 脚本内容

以下是完整的批处理脚本代码,推荐将其保存为 auto_push_nuget.bat

@echo off
REM 切换到 UTF-8 编码,支持中文路径
chcp 65001 >nul
setlocal EnableDelayedExpansion
echo ===== Auto push nuget started =====

REM ---------------- 配置区 ----------------
set "NUGET_SOURCE=你的私有nuget服务器"
set "API_KEY=私有nuget服务器的key,没有填空"
set "SUCCESS_LOG=success_log.txt"
set "ERROR_LOG=error_log.txt"
set "SVN_COMMIT_LIST=svn_commit_list.txt"
set "TEMP_LOG=temp_ps_output.txt"
set "SVN_UPDATE_TEMP=svn_update_temp.txt"
set SUCCESS_COUNT=0
set FAIL_COUNT=0
REM -----------------------------------------

⚙️ 脚本前置说明:

  • 脚本自动将当前控制台设置为 UTF-8,确保支持中文路径和日志输出;

  • 所有日志均分离输出到文件中,避免控制台信息混乱。

🎯 项目路径配置

修改以下部分,添加你要打包的 .csproj 路径(相对路径):

注意:索引数与COUNT一致

:: 定义项目路径数组
set "PROJECT_PATHS[0]=Xxx.BI.WebSite.Core\Xxx.BI.WebSite.Core.csproj"
set "PROJECT_PATHS[1]=Xxx.BI.WebSite.RazorWeb\Xxx.BI.WebSite.RazorWeb.csproj"
set "PROJECT_COUNT=2"

根据你的项目实际路径修改 PROJECT_PATHS,添加你希望打包的工程列表。

⚠️ 注意:这里的路径请填写 相对于脚本所在目录的路径,不要写绝对路径。如下图

版本号格式为:
6{YY}.{MM}.{DD}.{X},其中 X 是递增的补丁号。

例如:624.05.14.2

for /f "tokens=1-3 delims=/" %%a in ('powershell -command "Get-Date -Format 'yyyy/MM/dd'"') do (
  set YYYY=%%a
  set MM=%%b
  set DD=%%c
)
set YY=!YYYY:~2,2!
set /a M=1!MM! - 100
set /a D=1!DD! - 100
set VERSION_PREFIX=6!YY!.!M!.!D!

🔧 修改 .csproj 文件

使用 PowerShell 对 XML 进行修改,确保插入以下节点:

  • <Version>:自动计算或用户输入;

  • <Description>:设置描述;

  • <PackageOutputPath>:统一输出至 ..\..\..\nupkgs

  • <GeneratePackageOnBuild>:确保打包时包含所有内容。

$pg = $xml.Project.PropertyGroup | Where-Object { $_.Condition -eq $null -or $_.Condition -eq '' } | Select-Object -First 1;
if (-not $pg) { $pg = $xml.CreateElement('PropertyGroup'); $xml.Project.AppendChild($pg) | Out-Null };
# 后续注入节点逻辑...

🏗️ 构建与打包

dotnet build "!CSProjPath!" -c Release
dotnet pack "!CSProjPath!" -c Release --output "%~dp0nupkgs"

脚本会在 nupkgs 文件夹生成对应 .nupkg 文件。

☁️ 自动上传 NuGet 包

所有成功打包的路径会记录到 success_log.txt,随后逐个推送:

如果没有API-KEY,请删除 --api-key "%API_KEY%"

dotnet nuget push "!NUPKG_PATH!" --source "%NUGET_SOURCE%" --api-key "%API_KEY%"

🧾 SVN 自动化支持

  • 支持脚本运行前执行 svn update

  • 成功处理的项目会记录在 svn_commit_list.txt

  • 最后统一执行 svn commit 自动提交版本号更新:

svn commit "项目路径" -m "Auto update Version to 624.05.14.1"

🧠 SVN 提交

每次成功修改 .csproj 后,记录在列表文件 svn_commit_list.txt 中,最终一并执行 SVN 提交:

svn commit "项目路径" -m "Auto update Version to 6xx.xx.xx.x"

📜 附录:完整批处理脚本源码

@echo off
REM 切换到 UTF-8 编码,支持中文路径
chcp 65001 >nul
setlocal EnableDelayedExpansion
echo ===== Auto push nuget started =====
REM ---------------- 配置区 ----------------
set "NUGET_SOURCE=你的私有nuget服务器"
set "API_KEY=私有nuget服务器key"
set "SUCCESS_LOG=success_log.txt"
set "ERROR_LOG=error_log.txt"
set "SVN_COMMIT_LIST=svn_commit_list.txt"
set "TEMP_LOG=temp_ps_output.txt"
set "SVN_UPDATE_TEMP=svn_update_temp.txt"

::成功/失败条数
set SUCCESS_COUNT=0
set FAIL_COUNT=0
REM 注意:建议检查服务器是否支持 HTTPS,例如 https://www.baidu.com:8888
REM -----------------------------------------

:: 清空日志和 SVN 提交列表
if exist "%SUCCESS_LOG%" del "%SUCCESS_LOG%"
if exist "%ERROR_LOG%" del "%ERROR_LOG%"
if exist "%SVN_COMMIT_LIST%" del "%SVN_COMMIT_LIST%"
if exist "%TEMP_LOG%" del "%TEMP_LOG%"
if exist "%SVN_UPDATE_TEMP%" del "%SVN_UPDATE_TEMP%"

:: 清理 SVN_DIR,确保无换行符或多余字符
set "SVN_DIR=%~dp0"
:: 去掉末尾反斜杠
if "!SVN_DIR:~-1!"=="\" set "SVN_DIR=!SVN_DIR:~0,-1!"
:: 规范化路径
for %%P in ("!SVN_DIR!") do set "SVN_DIR=%%~fP"
echo [Debug] SVN directory: !SVN_DIR! >> "%SUCCESS_LOG%"

:: 执行 SVN 更新
echo [Info] Updating SVN working copy for directory: !SVN_DIR! >> "%SUCCESS_LOG%"
echo [Info] Updating SVN working copy...
svn update "!SVN_DIR!" > "%SVN_UPDATE_TEMP%" 2>&1
if errorlevel 1 (
    echo [Error] Failed to update SVN working copy. >> "%ERROR_LOG%"
    echo [Error] Failed to update SVN working copy. Error details:
    type "%SVN_UPDATE_TEMP%"
    echo [Error] Script will exit. >> "%ERROR_LOG%"
    echo [Error] Script will exit.
    del "%SVN_UPDATE_TEMP%"
    exit /b 1
) else (
    echo [Success] SVN working copy updated successfully. >> "%SUCCESS_LOG%"
    echo [Success] SVN working copy updated successfully.
    del "%SVN_UPDATE_TEMP%"
)

:: 获取当前日期作为版本前缀(6 + 年后两位 + 月 + 日)
for /f "tokens=1-3 delims=/" %%a in ('powershell -command "Get-Date -Format 'yyyy/MM/dd'"') do (
  set YYYY=%%a
  set MM=%%b
  set DD=%%c
)
set YY=!YYYY:~2,2!
set /a M=1!MM! - 100
set /a D=1!DD! - 100
set VERSION_PREFIX=6!YY!.!M!.!D!
echo [Debug] VERSION_PREFIX: !VERSION_PREFIX! >> "%SUCCESS_LOG%"

:: 定义项目路径数组
::注意:PROJECT_PATHS[X]=实际条数(X),COUNT=实际条数
:: 这里的路径规则,请录入相对路径,就是你的BAT所在文件夹以后的路径
set "PROJECT_PATHS[0]=Xxx.BI.WebSite.Core\Xxx.BI.WebSite.Core.csproj"
set "PROJECT_PATHS[1]=Xxx.BI.WebSite.RazorWeb\Xxx.BI.WebSite.RazorWeb.csproj"
set "PROJECT_COUNT=2"

:: 循环处理数组中的相对路径
for /l %%i in (0,1,%PROJECT_COUNT%-1) do (
    set "RELATIVE_PATH=!PROJECT_PATHS[%%i]!"
    if not "!RELATIVE_PATH!"=="" (
        echo [Info] Reading relative path: !RELATIVE_PATH! >> "%SUCCESS_LOG%"
        call :ProcessProject "!RELATIVE_PATH!"
    )
)

REM 统一 NuGet 包上传
echo.
echo ===== Pushing NuGet packages =====
echo ===== Pushing NuGet packages ===== >> "%SUCCESS_LOG%"
echo ===== Pushing NuGet packages ===== >> "%ERROR_LOG%"
set "FOUND_NUPKG=0"
if exist "%SUCCESS_LOG%" (
    for /f "tokens=1,* delims=:" %%a in ('findstr /B "\[Success\] Pack succeeded:" "%SUCCESS_LOG%"') do (
        set "NUPKG_PATH=%%b"
        REM 去除首尾空格并规范化路径
        for /f "tokens=*" %%c in ("!NUPKG_PATH!") do (
            set "NUPKG_PATH=%%~fc"
        )
		if "!NUPKG_PATH!"=="" (
			echo [Warning] Skipping empty NUPKG_PATH >> "%ERROR_LOG%"
			echo [Warning] Skipping empty NUPKG_PATH
		) else (
			echo [Debug] Checking NuGet package: !NUPKG_PATH! >> "%SUCCESS_LOG%"
			if exist "!NUPKG_PATH!" (
				set "FOUND_NUPKG=1"
				echo Pushing: !NUPKG_PATH!
				echo Pushing: !NUPKG_PATH! >> "%SUCCESS_LOG%"
				dotnet nuget push "!NUPKG_PATH!" --source "%NUGET_SOURCE%" --api-key "%API_KEY%" >> "%SUCCESS_LOG%" 2>> "%ERROR_LOG%"
				if errorlevel 1 (
					set /a FAIL_COUNT+=1
					echo [Error] Push failed: !NUPKG_PATH! >> "%ERROR_LOG%"
					echo [Error] Push failed: !NUPKG_PATH!
				) else (				
					set /a SUCCESS_COUNT+=1
					echo [Success] Push succeeded: !NUPKG_PATH! >> "%SUCCESS_LOG%"
					echo [Success] Push succeeded: !NUPKG_PATH! 
				)
			) else (
				set /a FAIL_COUNT+=1
				echo [Error] NuGet package not found during push: !NUPKG_PATH! >> "%ERROR_LOG%"
				echo [Error] NuGet package not found during push: !NUPKG_PATH!
			)
		)
    )
)
if "!FOUND_NUPKG!"=="0" (
    echo [Warning] No successful NuGet packages found to push >> "%ERROR_LOG%"
    echo [Warning] No successful NuGet packages found to push
)

REM 统一 SVN 提交
if exist "%SVN_COMMIT_LIST%" (
    echo.
    echo ===== Committing to SVN =====
    echo ===== Committing to SVN ===== >> "%SUCCESS_LOG%"
    echo ===== Committing to SVN ===== >> "%ERROR_LOG%"
    for /f "tokens=1,2 delims=;" %%a in (%SVN_COMMIT_LIST%) do (
        echo Committing: %%a
        echo Committing: %%a >> "%SUCCESS_LOG%"
        svn commit "%%a" -m "Auto update Version to %%b" >> "%SUCCESS_LOG%" 2>&1
        if errorlevel 1 (
            echo [Error] SVN commit failed: %%a >> "%ERROR_LOG%"
            echo [Error] SVN commit failed: %%a >> "%SUCCESS_LOG%"
            echo [Error] SVN commit failed: %%a
        ) else (
            echo [Success] SVN commit succeeded: %%a >> "%SUCCESS_LOG%"
			echo [Success] SVN commit successed: %%a
        )
    )
    del "%SVN_COMMIT_LIST%"
)

echo. >> "%SUCCESS_LOG%"
echo ===== All tasks completed ===== >> "%SUCCESS_LOG%"
echo. >> "%ERROR_LOG%"
echo ===== All tasks completed ===== >> "%ERROR_LOG%"
echo.
echo ===== All tasks completed =====
echo Success log: %SUCCESS_LOG%
echo Error log: %ERROR_LOG%
echo Nuget push successed : %SUCCESS_COUNT%
echo Nuget push error: %FAIL_COUNT%
del "%ERROR_LOG%"
del "%SUCCESS_LOG%"
if exist "%SVN_UPDATE_TEMP%" del "%SVN_UPDATE_TEMP%"
pause

echo ===== Auto push nuget ended =====
endlocal
exit /b 0

:ProcessProject
set "RELATIVE_PATH=%~1"
echo [Info] Processing relative path: %RELATIVE_PATH% >> "%SUCCESS_LOG%"

REM 移除相对路径的前导 \(如果存在)
set "CLEAN_PATH=%RELATIVE_PATH%"
if "!CLEAN_PATH:~0,1!"=="\" set "CLEAN_PATH=!CLEAN_PATH:~1!"
echo [Debug] CLEAN_PATH: !CLEAN_PATH! >> "%SUCCESS_LOG%"

REM 使用 pushd 切换到脚本目录
pushd "%~dp0"
echo [Debug] Current directory after pushd: %CD% >> "%SUCCESS_LOG%"

REM 拼接完整路径
set "CSProjPath=%CD%\!CLEAN_PATH!"
REM 规范化路径
for %%P in ("!CSProjPath!") do set "CSProjPath=%%~fP"
echo [Info] Full .csproj path: !CSProjPath! >> "%SUCCESS_LOG%"

REM 验证 .csproj 文件存在
if not exist "!CSProjPath!" (
    echo [Warning] File not found: !CSProjPath! >> "%ERROR_LOG%"
    echo [Warning] File not found: !CSProjPath!
    popd
    exit /b 0
)

REM 恢复原始目录
popd
echo [Debug] Directory restored: %CD% >> "%SUCCESS_LOG%"

echo.
echo ===== Processing: !CSProjPath! =====
echo ===== Processing: !CSProjPath! ===== >> "%SUCCESS_LOG%"

REM —— 清空上次遗留的变量 ——
set "OLD_VERSION="
set "LAST_PART="

REM —— 1) 读取 csproj 中已有的 Version —— 
powershell -NoProfile -Command ^
  "try { [xml]$x = Get-Content -Path '!CSProjPath!' -Encoding UTF8 -ErrorAction Stop; $version = $x.Project.PropertyGroup | Where-Object { $_.Version -and ($_.Condition -eq $null -or $_.Condition -eq '') } | Select-Object -ExpandProperty Version -First 1; if ($version) { $version.Trim() } else { '' } } catch { Write-Output 'ERROR: ' + $_.Exception.Message; exit 1 }" > "%TEMP_LOG%"
if errorlevel 1 (
    echo [Error] Failed to read Version from !CSProjPath! >> "%ERROR_LOG%"
    echo [Error] Failed to read Version from !CSProjPath!
    type "%TEMP_LOG%" >> "%ERROR_LOG%"
    popd
    exit /b 1
)
for /f "delims=" %%v in (%TEMP_LOG%) do (
    set "OLD_VERSION=%%v"
)
echo [Debug] OLD_VERSION: !OLD_VERSION! >> "%SUCCESS_LOG%"
del "%TEMP_LOG%"

REM —— 2) 基于 OLD_VERSION 计算新的 LAST_PART ——
set "LAST_PART=1"
if defined OLD_VERSION (
    REM 检查 OLD_VERSION 是否包含错误
    if not "!OLD_VERSION!"=="!OLD_VERSION:ERROR:=!" (
        echo [Warning] Invalid OLD_VERSION: !OLD_VERSION! >> "%ERROR_LOG%"
        echo [Warning] Invalid OLD_VERSION: !OLD_VERSION!
        set "OLD_VERSION="
    ) else (
        REM 清理 OLD_VERSION 中的空格
        set "OLD_VERSION=!OLD_VERSION: =!"
        echo [Debug] Cleaned OLD_VERSION: !OLD_VERSION! >> "%SUCCESS_LOG%"
        for /f "tokens=1-4 delims=." %%a in ("!OLD_VERSION!") do (
            set "OLD_PREFIX=%%a.%%b.%%c"
            echo [Debug] OLD_PREFIX: !OLD_PREFIX!, VERSION_PREFIX: !VERSION_PREFIX! >> "%SUCCESS_LOG%"
            if "!OLD_PREFIX!"=="!VERSION_PREFIX!" (
                set /a LAST_PART=%%d + 1
                echo [Debug] LAST_PART: !LAST_PART! >> "%SUCCESS_LOG%"
            )
        )
    )
)

echo [Info] version number generation in progress...
echo [Info] recommend version: !VERSION_PREFIX!.!LAST_PART! ,Enter use this version or input new version:
set /p USER_VER=

if defined USER_VER (
    set "CUSTOM_VERSION=!USER_VER!"
)

if defined CUSTOM_VERSION (
    set "NEW_VERSION=!CUSTOM_VERSION!"
) else (
    set "NEW_VERSION=!VERSION_PREFIX!.!LAST_PART!"
)

echo [Info] NEW_VERSION = !NEW_VERSION! >> "%SUCCESS_LOG%"
echo [Info] NEW_VERSION = !NEW_VERSION!
echo [Info] version number generation completed...

REM —— 3) 使用 PowerShell 注入并**覆盖**所有必要节点 —— 
echo [Info] modify the csproj file...
set NEW_VERSION=!NEW_VERSION!
powershell -NoProfile -Command ^
  "$path = '!CSProjPath!';" ^
  "try { [xml]$xml = Get-Content -Path $path -Encoding UTF8 -Raw -ErrorAction Stop; $pg = $xml.Project.PropertyGroup | Where-Object { $_.Condition -eq $null -or $_.Condition -eq '' } | Select-Object -First 1; if (-not $pg) { $pg = $xml.CreateElement('PropertyGroup'); $xml.Project.AppendChild($pg) | Out-Null }; $vn = $pg.SelectSingleNode('Version'); if (-not $vn) { $vn = $xml.CreateElement('Version'); $pg.AppendChild($vn) | Out-Null }; $vn.InnerText = $env:NEW_VERSION; $desc = $pg.SelectSingleNode('Description'); if (-not $desc) { $desc = $xml.CreateElement('Description'); $pg.AppendChild($desc) | Out-Null }; $desc.InnerText = 'Automatically generate nuget packages'; $gpb = $pg.SelectSingleNode('GeneratePackageOnBuild'); if (-not $gpb) { $gpb = $xml.CreateElement('GeneratePackageOnBuild'); $gpb.InnerText = 'true'; $pg.AppendChild($gpb) | Out-Null }; $pop = $pg.SelectSingleNode('PackageOutputPath'); if (-not $pop) { $pop = $xml.CreateElement('PackageOutputPath'); $pg.AppendChild($pop) | Out-Null }; $pop.InnerText = '..\\..\\..\\nupkgs'; $sw = New-Object System.IO.StreamWriter($path, $false, (New-Object System.Text.UTF8Encoding $true)); $xml.Save($sw); $sw.Close(); Write-Output 'PS_INJECTION_SUCCESS'; } catch { Write-Output 'ERROR: ' + $_.Exception.Message; exit 1 }" > "%TEMP_LOG%"

findstr "PS_INJECTION_SUCCESS" "%TEMP_LOG%" >nul
if errorlevel 1 (
    echo [Error] XML injection failed: !CSProjPath! >> "%ERROR_LOG%"
    echo [Error] XML injection failed: !CSProjPath!
    type "%TEMP_LOG%" >> "%ERROR_LOG%"
    exit /b 1
) else (
    echo [Success] modify successed
)
echo [Info] modify the csproj file...

REM —— 验证 Version 节点 —— 
powershell -NoProfile -Command ^
  "try { [xml]$x = Get-Content -Path '!CSProjPath!' -Encoding UTF8 -ErrorAction Stop; $version = $x.Project.PropertyGroup | Where-Object { $_.Version -and ($_.Condition -eq $null -or $_.Condition -eq '') } | Select-Object -ExpandProperty Version -First 1; if ($version) { $version.Trim() } else { '' } } catch { Write-Output 'ERROR: ' + $_.Exception.Message; exit 1 }" > "%TEMP_LOG%"
if errorlevel 1 (
    echo [Error] Failed to verify Version in !CSProjPath! >> "%ERROR_LOG%"
    echo [Error] Failed to verify Version in !CSProjPath!
    type "%TEMP_LOG%" >> "%ERROR_LOG%"
    exit /b 1
)
for /f "delims=" %%v in (%TEMP_LOG%) do (
    set "VERIFIED_VERSION=%%v"
)
echo [Debug] Version after injection: !VERIFIED_VERSION! >> "%SUCCESS_LOG%"
if not "!VERIFIED_VERSION!"=="!NEW_VERSION!" (
    echo [Error] Version node not updated to !NEW_VERSION!, found !VERIFIED_VERSION! >> "%ERROR_LOG%"
    echo [Error] Version node not updated to !NEW_VERSION!, found !VERIFIED_VERSION!
    exit /b 1
)

REM —— 4) 构建 —— 
echo [Info] building csproj...
dotnet build "!CSProjPath!" -c Release >> "%SUCCESS_LOG%" 2>> "%ERROR_LOG%"
if errorlevel 1 (
    echo [Error] Build failed: !CSProjPath! >> "%ERROR_LOG%"
    echo [Error] Build failed: !CSProjPath!
    exit /b 1
) else (
    echo [Success] build successed
)
echo [Info] end of csproj construction...

REM —— 5) 打包 —— 
echo [Info] package in csproj...
if not exist "%~dp0nupkgs" mkdir "%~dp0nupkgs"
dotnet pack "!CSProjPath!" -c Release --output "%~dp0nupkgs" -p:Description="Automatically generate nuget packages" >> "%SUCCESS_LOG%" 2>> "%ERROR_LOG%"
if errorlevel 1 (
    echo [Error] Pack failed: !CSProjPath! >> "%ERROR_LOG%"
    echo [Error] Pack failed: !CSProjPath!
    exit /b 1
) else (
    echo [Success] pack successed
)
REM 记录成功打包的 .nupkg 文件
for %%P in ("%~dp0nupkgs\%~n1.!NEW_VERSION!.nupkg") do (
    if exist "%%P" (
        echo [Success] Pack succeeded: %%P >> "%SUCCESS_LOG%"
        echo [Success] Pack succeeded: %%P
    ) else (
        echo [Error] Pack file not found: %%P >> "%ERROR_LOG%"
        echo [Error] Pack file not found: %%P
        exit /b 1
    )
)
echo [Info] end of packaging csproj...

REM —— 6) 记录 SVN 提交 —— 
echo !CSProjPath!;!NEW_VERSION!>> "%SVN_COMMIT_LIST%"

del "%TEMP_LOG%"
exit /b 0

✅ 建议将脚本保存为 auto_push_nuget.bat,每次发布时双击运行即可。

📁 目录结构推荐

/你的解决方案根目录
│
├─ auto_push_nuget.bat
├─ nupkgs/
├─ success_log.txt
├─ error_log.txt
├─ svn_commit_list.txt

📌 注意事项

  • 建议手动验证 .csproj 路径是否正确;

  • 确保 svn 命令行工具已正确安装;

  • dotnet SDK 和私有 NuGet 源地址需提前配置;

  • 每次运行脚本前,请使用最新版源码(SVN update);

  • 批处理脚本推荐使用 Windows PowerShell 5+ 和 Windows Terminal。


🎉 效果展示

成功输出如下所示:

[Success] build successed
[Success] pack successed
Pushing: Xxx.BI.WebSite.Core.624.05.14.1.nupkg
[Success] Push succeeded: Xxx.BI.WebSite.Core.624.05.14.1.nupkg
Committing: Xxx.BI.WebSite.Core.csproj
[Success] SVN commit succeeded: Xxx.BI.WebSite.Core.csproj

🧩 最后

本脚本适合用于 CI/CD 之外的 本地开发辅助打包上传工具。你可以结合 gitJenkinsTeamCity 等系统,将其进一步整合为流水线任务。

如果你有类似自动化构建打包需求,欢迎参考本脚本并结合你项目的实际路径进行修改和优化。


如需该脚本的 .bat 文件,可留言或私信获取完整代码包。

如果你觉得这篇文章对你有帮助,欢迎 👍 点赞 / ⭐ 收藏 / 📝 留言!