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

IIS部署.NET Core如何不终止全部dotnet进程释放指定目录文件锁

问题描述

在Windows Server 2019服务器上使用CodeDeploy部署多个IIS应用时,部署其中一个.NET Core 3.1应用出现如下报错:

Permission denied @ unlink_internal - C:/inetpub/wwwroot/webApi/AutocheckerEntities.dll

最初为解决该问题,在停止站点、停止对应应用池的操作逻辑外,额外添加了强制结束所有dotnet.exe进程的命令——仅停止站点和应用池无法解决上述文件占用报错。
初始版本的appstop.ps1脚本内容如下:

Stop-WebSite 'WebApi'
Stop-WebAppPool (Get-Website -Name WebApi).applicationPool
taskkill /IM "dotnet.exe" /F

对应appspec.yml配置内容如下:

version: 0.0
os: windows
files:
  - source: /
    destination: C:\inetpub\wwwroot\webApi
hooks:
   BeforeInstall:
     - location: CodeDeploy/appstop.ps1
       runas: administrator
   ApplicationStart:
     - location: CodeDeploy/appstart.ps1       
       runas: administrator

该方案存在明确业务影响风险:服务器上同时运行了其他.NET应用,强制结束全部dotnet.exe进程会导致其他业务异常,需要实现仅临时释放C:\inetpub\wwwroot\webApi目录下的文件锁、无需终止全部dotnet.exe进程的方案。

可行方案

根因说明

仅停止站点和应用池后仍存在文件锁,核心原因是IIS停止站点、回收应用池的操作不是同步完成的:工作进程(w3wp.exe)、OutOfProcess托管模式下的.NET Core dotnet宿主进程,会等待现有请求处理完成后才退出,默认最长等待时间是90秒,这段时间内进程会持续持有应用目录下dll文件的句柄,就会触发部署时的unlink权限报错。
直接全局杀所有dotnet.exe属于过度操作,完全可以通过精准定位、终止仅占用目标部署目录的进程解决问题,不会影响其他业务。

具体实现

修改appstop.ps1脚本,替换全局杀进程的逻辑,改为等待IIS回收+精准查杀占用目标目录的关联进程,修改后的脚本如下:

$siteName = "WebApi"
$deployPath = "C:\inetpub\wwwroot\webApi"

# 停止目标站点
Stop-WebSite -Name $siteName

# 获取站点绑定的应用池并执行停止操作
$appPoolName = (Get-Website -Name $siteName).applicationPool
Stop-WebAppPool -Name $appPoolName

# 等待3秒,给IIS留出默认进程回收的缓冲时间
Start-Sleep -Seconds 3

# 二次校验应用池状态,未完全停止则强制停止
if ((Get-WebAppPoolState -Name $appPoolName).Value -ne "Stopped") {
    Stop-WebAppPool -Name $appPoolName -Force
}

# 精准查找命令行参数包含目标部署路径的w3wp、dotnet进程,仅终止这部分进程
Get-CimInstance Win32_Process | Where-Object {
    $_.Name -in @('w3wp.exe', 'dotnet.exe') -and
    $_.CommandLine -match [regex]::Escape($deployPath)
} | ForEach-Object {
    Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue
}

优化配置(可选)

可以提前在IIS中调整目标应用池的配置,从根源减少文件锁出现的概率:

  • 打开目标应用池的高级设置
  • 找到进程模型分组,将闲置超时设置为0,关闭时间限制设置为1秒
  • 找到常规分组,将启动模式设置为OnDemand
    配置完成后,停止应用池时工作进程会在1秒内被强制销毁,基本不会出现残留文件锁的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 12:45:37