You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

dotnet publish偶发DLL被占用失败,回收应用池仍无法解决

问题成因
  • 传统ASP.NET默认启用*影子复制(Shadow Copy)*机制,运行时会将站点DLL复制到临时目录加载,不会锁定站点根目录下的原始文件,因此不会出现发布时文件占用问题;而ASP.NET Core默认关闭该机制,IIS的w3wp进程会直接加载站点根目录的DLL并持有独占文件锁。
  • IIS应用池回收是异步操作:执行appcmd recycle命令返回成功仅代表IIS已下发回收指令,旧的w3wp进程需要等待现有请求处理完毕、资源完全释放后才会退出,锁释放存在几秒到几十秒的延迟。若回收后立刻执行发布命令,旧进程尚未释放锁就会触发文件占用报错。
  • IIS默认启用重叠回收功能:回收时会先启动新的w3wp进程承接新请求,等旧进程处理完所有请求后再销毁旧进程,若新进程启动后立刻加载了站点目录的DLL,同样会导致发布时文件被锁。
解决方案

以下方案按优先级从高到低排序:

方案1:启用ASP.NET Core影子复制(最省心)

ASP.NET Core 3.1及以上版本原生支持影子复制功能,只需修改站点根目录的web.config配置,在aspNetCore节点添加shadowCopyEnabled="true"属性即可:

<configuration>
  <system.webServer>
    <aspNetCore 
      processPath="dotnet" 
      arguments=".\NeatF2PWebsite.dll" 
      stdoutLogEnabled="false" 
      stdoutLogFile=".\logs\stdout"
      shadowCopyEnabled="true" 
    />
  </system.webServer>
</configuration>

配置生效后,ASP.NET Core会自动将DLL复制到临时目录加载,不会锁定站点根目录的原始文件,发布时无需操作应用池即可正常覆盖文件。

方案2:调整发布脚本逻辑,先停止再启动应用池

相比回收操作,先停止应用池可以强制进程退出释放锁,调整后的脚本如下:

ECHO ON
REM 停止目标应用池
%SYSTEMROOT%\System32\inetsrv\appcmd stop apppool /apppool.name:"NeatF2P"
REM 等待5秒确保进程完全退出、锁释放
timeout /t 5 /nobreak
REM 执行发布
dotnet publish --output C:\Websites\NeatF2P --force --no-build
REM 启动应用池
%SYSTEMROOT%\System32\inetsrv\appcmd start apppool /apppool.name:"NeatF2P"
pause

如果服务器性能较低、进程释放慢,可以适当延长timeout的等待时间。

方案3:使用Web Deploy发布

Visual Studio自带的Web Deploy发布工具原生支持IIS站点发布,会自动处理文件锁、应用池启停等逻辑,无需自行编写脚本,适合日常开发使用。


内容的提问来源于stack exchange,提问作者Paul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 23:00:01