如何快速将当前的c#工程发布成单文件

build 脚本使用说明(use_build_script.md)

本文档说明 build.bat / build_cn.bat 的适用范围、参数用法、在当前工程 D:\MyItems\UdpClientUser\ 的实际发布示例、输出结果与注意事项,便于日后参考。

先上脚本,有英文本和中文本,如果有兼容性问题,请优先使用英文版。

bash 复制代码
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion

rem =====================
rem Settings (editable via args; args override defaults)
rem =====================
set CONFIG=Release
set RUNTIME=win-x64
set SELF_CONTAINED=false

rem Usage: build_fail.bat [runtime] [selfContained(true/false)] [config]
if not "%~1"=="" set RUNTIME=%~1
if not "%~2"=="" set SELF_CONTAINED=%~2
if not "%~3"=="" set CONFIG=%~3

rem ---------------------
rem Paths & Project detection
rem ---------------------
set SCRIPT_DIR=%~dp0
set PUBLISH_DIR=%SCRIPT_DIR%publish
set CSPROJ=

pushd "%SCRIPT_DIR%" >nul 2>&1
for %%f in ("*.csproj") do (
  if not defined CSPROJ set CSPROJ=%%~nxf
)

if not defined CSPROJ (
  rem search subdirs for .csproj
  for /r "%SCRIPT_DIR%" %%f in (*.csproj) do (
    if not defined CSPROJ set CSPROJ=%%~nxf & set CSPROJ_DIR=%%~dpf
  )
  if defined CSPROJ_DIR pushd "%CSPROJ_DIR%" >nul 2>&1
)

if not defined CSPROJ (
  echo No .csproj found. Place this script in the project folder or specify manually.
  echo Current dir: %CD%
  dir /b *.csproj
  goto :fail
)

set FULL_CSPROJ_PATH=%CD%\%CSPROJ%

where dotnet >nul 2>&1
if errorlevel 1 (
  echo dotnet SDK not found. Please install .NET SDK.
  goto :fail
)

dotnet --info

echo.
echo Project: %FULL_CSPROJ_PATH%
echo Config: %CONFIG%  Runtime: %RUNTIME%  SelfContained: %SELF_CONTAINED%

echo.
if not exist "%PUBLISH_DIR%" mkdir "%PUBLISH_DIR%"

echo Cleaning...
 dotnet clean "%FULL_CSPROJ_PATH%" -c %CONFIG%
if errorlevel 1 goto :fail

echo.
echo Publishing to: "%PUBLISH_DIR%"
 dotnet publish "%FULL_CSPROJ_PATH%" ^
  -c %CONFIG% ^
  -r %RUNTIME% ^
  --self-contained %SELF_CONTAINED% ^
  -p:PublishSingleFile=true ^
  -p:IncludeNativeLibrariesForSelfExtract=true ^
  -o "%PUBLISH_DIR%"
if errorlevel 1 goto :fail

echo.
set APP_EXE=
for %%e in ("%PUBLISH_DIR%\*.exe") do (
  if not defined APP_EXE set APP_EXE=%%~nxe
)

echo Done.
if defined APP_EXE (
  echo Output EXE: %APP_EXE%
) else (
  echo Note: no .exe found in publish; library/non-Windows-ui projects output .dll only.
)

goto :success

:fail
echo.
echo Build/Publish failed; see logs above.
set ERR=1

:success
popd >nul 2>&1
exit /b %ERR%

中文版:

bash 复制代码
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion

rem =====================
rem 构建与发布设置(可通过命令行参数覆盖默认值)
rem =====================
set CONFIG=Release
set RUNTIME=win-x64
set SELF_CONTAINED=false

rem 用法:build_cn.bat [运行时RID] [是否自包含(true/false)] [配置]
rem 示例:
rem   build_cn.bat               (等同于 win-x64 + 非自包含 + Release)
rem   build_cn.bat win-x86       (发布为 32 位)
rem   build_cn.bat win-x64 true  (自包含单文件,无需安装 .NET 运行时)
rem   build_cn.bat win-x64 false Debug
if not "%~1"=="" set RUNTIME=%~1
if not "%~2"=="" set SELF_CONTAINED=%~2
if not "%~3"=="" set CONFIG=%~3

rem ---------------------
rem 路径与项目探测
rem ---------------------
set SCRIPT_DIR=%~dp0
set PUBLISH_DIR=%SCRIPT_DIR%publish
set CSPROJ=

rem 先在当前目录找 .csproj
pushd "%SCRIPT_DIR%" >nul 2>&1
for %%f in ("*.csproj") do (
  if not defined CSPROJ set CSPROJ=%%~nxf
)

rem 若未找到,则到子目录继续找
if not defined CSPROJ (
  for /r "%SCRIPT_DIR%" %%f in (*.csproj) do (
    if not defined CSPROJ set CSPROJ=%%~nxf & set CSPROJ_DIR=%%~dpf
  )
  if defined CSPROJ_DIR pushd "%CSPROJ_DIR%" >nul 2>&1
)

if not defined CSPROJ (
  echo 未找到任何 .csproj 文件,请将脚本放在包含项目文件的目录下,或手动指定。
  echo 当前目录:%CD%
  dir /b *.csproj
  goto :fail
)

set FULL_CSPROJ_PATH=%CD%\%CSPROJ%

rem 校验 .NET SDK 可用性
where dotnet >nul 2>&1
if errorlevel 1 (
  echo 未检测到 dotnet SDK,请先安装 .NET SDK。
  goto :fail
)

dotnet --info

echo.
echo 检测到项目: %FULL_CSPROJ_PATH%
echo 配置: %CONFIG%  运行时: %RUNTIME%  自包含: %SELF_CONTAINED%

echo.
if not exist "%PUBLISH_DIR%" mkdir "%PUBLISH_DIR%"

echo 清理旧构建...
 dotnet clean "%FULL_CSPROJ_PATH%" -c %CONFIG%
if errorlevel 1 goto :fail

echo.
echo 发布到: "%PUBLISH_DIR%"
 dotnet publish "%FULL_CSPROJ_PATH%" ^
  -c %CONFIG% ^
  -r %RUNTIME% ^
  --self-contained %SELF_CONTAINED% ^
  -p:PublishSingleFile=true ^
  -p:IncludeNativeLibrariesForSelfExtract=true ^
  -o "%PUBLISH_DIR%"
if errorlevel 1 goto :fail

echo.
set APP_EXE=
for %%e in ("%PUBLISH_DIR%\*.exe") do (
  if not defined APP_EXE set APP_EXE=%%~nxe
)

echo 发布完成!
if defined APP_EXE (
  echo 生成的可执行文件:%APP_EXE%
) else (
  echo 注意:未在 publish 目录发现 .exe;如果是类库或非 Windows 桌面项目,可能只生成 .dll。
)

goto :success

:fail
echo.
echo 构建/发布失败,请查看上方错误信息。
set ERR=1

:success
popd >nul 2>&1
exit /b %ERR%

1. 适用范围

  • 适用于 SDK 风格的 .NET 项目(.NET Core/.NET 5+/6+/7+/8+/9+),例如 WinForms、WPF、Console 等可执行项目。
  • 支持生成"单文件"应用(SingleFile)。
  • 支持"自包含"(Self-contained)或"依赖框架"(Framework-dependent)两种发布模式。
  • 脚本可放置在:
    • 目标项目根目录(该目录包含 .csproj),或
    • 项目根目录的上一层目录(脚本会自动向下探测首个 .csproj)。

不适用或需改造的情况:

  • 非 SDK 风格的旧版 .NET Framework 项目(如 TargetFrameworkVersion=v4.x.csproj 非 Sdk 格式)。这类项目不支持 dotnet publish 的 SingleFile,需要改用 MSBuild 或第三方打包(如 ILMerge、Costura.Fody)。
  • 纯类库(Class Library)项目不会生成 .exe,而是 .dll------这是预期行为。

2. 脚本清单

  • build.bat:英文注释版本(UTF-8 无 BOM + CRLF)。
  • build_cn.bat:中文注释版本(UTF-8 无 BOM + CRLF)。

二者功能一致:

  • 自动探测当前/子目录中的第一个 .csproj 作为发布目标。
  • 执行 dotnet cleandotnet publish
  • 发布为"单文件",默认输出到同级目录下的 publish/

3. 快速开始

在项目目录 D:\MyItems\UdpClientUser\ 中打开终端(PowerShell 或 CMD):

  • 默认发布(Release + win-x64 + 非自包含):

    build_cn.bat

或:

复制代码
build.bat
  • 指定运行时(RID):

    build_cn.bat win-x86

  • 自包含发布(无需安装 .NET 运行时):

    build_cn.bat win-x64 true

  • 指定配置(Debug/Release):

    build_cn.bat win-x64 false Debug

参数顺序:[运行时RID] [是否自包含(true/false)] [配置]

常见 RID:win-x64win-x86win-arm64

4. 参数说明

  • CONFIG:构建配置,默认 Release
  • RUNTIME:运行时标识(RID),默认 win-x64
  • SELF_CONTAINED:是否自包含,默认 false
    • true:自包含;目标机器无需安装 .NET 运行时,单文件体积更大。
    • false:依赖框架;目标机器需要安装对应版本的 .NET 运行时,体积较小。

脚本内部固定发布参数:

  • -p:PublishSingleFile=true:启用单文件发布。
  • -p:IncludeNativeLibrariesForSelfExtract=true:包含原生库(避免部分场景缺失依赖)。
  • -o publish/:输出目录。

5. 以当前工程为例(D:\MyItems\UdpClientUser)

  • 工程文件:D:\MyItems\UdpClientUser\UdpClientUser.WinForms.csproj

  • 目标框架:net6.0-windows

  • 运行命令(示例):

    build_cn.bat

  • 关键日志(典型):

    • dotnet --info 显示 SDK 与运行时信息。
    • dotnet clean 清理成功。
    • dotnet publish 输出:
      • UdpClientUser.WinForms -> D:\MyItems\UdpClientUser\bin\Release\net6.0-windows\win-x64\UdpClientUser.WinForms.dll
      • UdpClientUser.WinForms -> D:\MyItems\UdpClientUser\publish\
  • 发布产物:

    • 目录:D:\MyItems\UdpClientUser\publish\
    • 文件:UdpClientUser.WinForms.exe(单文件,可直接运行)

6. 注意事项与常见问题(FAQ)

  • 编码/换行:
    • 脚本以"UTF-8 无 BOM + CRLF"保存,首行 @echo off,第二行 chcp 65001 >nul
    • 避免使用 UTF-16(记事本的"Unicode")或仅 LF 换行,否则 CMD 解析可能异常。
  • 中文注释:
    • 中文注释不会影响执行,但必须保证脚本编码与换行规范;否则可能出现"不是内部或外部命令"的报错。
    • 若终端显示中文乱码,建议使用 Windows Terminal/PowerShell 7,或保留 chcp 65001 >nul
  • 多项目目录:
    • 目录中若有多个 .csproj,脚本会取扫描到的第一个作为目标。建议将脚本放入具体项目根目录,或在脚本中增强为"显式指定 .csproj 路径"。
  • 类库项目:
    • 类库不会生成 .exepublish/ 下只有 .dll 属正常现象。
  • 自包含 vs 非自包含:
    • 自包含(true)生成更大的单文件,无需额外安装 .NET 运行时;适合分发给未装 .NET 的环境。
    • 非自包含(false)体积更小,但依赖目标环境的 .NET 运行时版本。
  • 运行权限:
    • 发布过程中需要访问网络(NuGet 恢复)与写入 publish/ 目录的权限。若有防护软件拦截,需放行 dotnet.exe 与当前工作目录。

7. 进阶用法建议(可选增强)

  • 显式指定项目文件:
    • 可扩展脚本支持 PROJECT=path\to\MyApp.csproj 的命名参数,以避免在多项目目录中误选。
  • 输出版本与文件信息:
    • .csproj 中设置 AssemblyVersion / FileVersion / InformationalVersion,便于追踪。
  • 生成自包含默认:
    • 若分发到无 .NET 环境的机器较多,可将脚本默认 SELF_CONTAINED=true

8. 参考命令(脚本内部核心命令)

bat 复制代码
rem 清理
"dotnet" clean "%FULL_CSPROJ_PATH%" -c %CONFIG%

rem 发布单文件
"dotnet" publish "%FULL_CSPROJ_PATH%" ^
  -c %CONFIG% ^
  -r %RUNTIME% ^
  --self-contained %SELF_CONTAINED% ^
  -p:PublishSingleFile=true ^
  -p:IncludeNativeLibrariesForSelfExtract=true ^
  -o "%PUBLISH_DIR%"

如需将脚本增强为"显式选择 .csproj / 支持命名参数 / 默认自包含"等,请在 D:\MyItems\UdpClientUser\ 中提出具体需求,我可以直接修改脚本并验证结果。

相关推荐
天***88962 小时前
使用python写一个应用程序要求实现微软常用vc++功能排查与安装功能
java
代码充电宝3 小时前
LeetCode 算法题【简单】283. 移动零
java·算法·leetcode·职场和发展
切糕师学AI6 小时前
在 C# 中,如何使 $““ 字符串支持换行
c#
ccccczy_6 小时前
Spring Security 深度解读:JWT 无状态认证与权限控制实现细节
java·spring security·jwt·authentication·authorization·securityfilterchain·onceperrequestfilter
Lin_Aries_04216 小时前
容器化 Tomcat 应用程序
java·linux·运维·docker·容器·tomcat
sheji34166 小时前
【开题答辩全过程】以 springboot高校社团管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
、BeYourself6 小时前
Android 常见界面布局详解
android
weixin_411191846 小时前
安卓Handler+Messenger实现跨应用通讯
android
咕噜企业签名分发-淼淼6 小时前
App防止恶意截屏功能的方法:iOS、Android和鸿蒙系统的实现方案
android·ios·harmonyos