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

.NET Core GitLab CI部署IIS报错:文件被其他进程占用

解决GitLab CI部署.NET Core API到IIS时的文件占用问题

当停止IIS应用池后仍出现The process cannot access the file because it is being used by another process错误,通常是因为应用池对应的进程(如w3wp.exe或dotnet.exe)未完全退出,或是有其他进程占用了目标目录的文件。以下是针对性解决方案:

1. 停止应用池后强制终止关联进程

在停止应用池后,添加脚本杀死残留的w3wp和dotnet进程,确保文件完全释放:

修改deploy阶段的脚本如下:

# 停止目标应用池
if((Get-WebAppPoolState -Name $application_pool_name).Value -ne 'Stopped'){
    Write-Output ('Stopping Application Pool: {0}' -f $application_pool_name)
    Stop-WebAppPool -Name $application_pool_name
}

# 等待进程开始退出,然后终止关联的w3wp进程
Start-Sleep -s 2
Get-WmiObject Win32_Process -Filter "Name='w3wp.exe'" | Where-Object {
    $_.GetOwner().User -eq "IIS APPPOOL\$application_pool_name"
} | ForEach-Object {
    Write-Output ('Killing w3wp process with ID: {0}' -f $_.ProcessId)
    Stop-Process -Id $_.ProcessId -Force
}

# 检查并终止占用发布目录的dotnet进程
Get-Process dotnet -ErrorAction SilentlyContinue | Where-Object {
    $_.MainModule -and $_.MainModule.FileName.StartsWith($iis_application_path)
} | ForEach-Object {
    Write-Output ('Killing dotnet process with ID: {0}' -f $_.ProcessId)
    Stop-Process -Id $_.ProcessId -Force
}

# 执行文件复制
Copy-Item ($publish_path + "*") -Destination $iis_application_path -Recurse -Force -PassThru

# 重启应用池
if((Get-WebAppPoolState -Name $application_pool_name).Value -ne 'Started'){
    Write-Output ('Starting Application Pool: {0}' -f $application_pool_name)
    Start-WebAppPool -Name $application_pool_name
}

2. 采用备份替换的方式避免文件占用

如果进程终止仍无效,可以先将原部署目录重命名为备份,再复制新文件,彻底规避文件占用问题:

修改deploy阶段的复制步骤为:

# 停止应用池及清理进程(同方案1的停止/杀进程代码)
...

# 备份原部署目录
$backup_path = "$iis_application_path`_backup_$(Get-Date -Format 'yyyyMMddHHmmss')"
if(Test-Path $iis_application_path){
    Rename-Item -Path $iis_application_path -NewName $backup_path -Force
}

# 复制新发布文件
Copy-Item ($publish_path + "*") -Destination $iis_application_path -Recurse -Force -PassThru

# 可选:清理备份目录(建议先验证部署成功后再启用)
# Remove-Item -Path $backup_path -Recurse -Force -ErrorAction SilentlyContinue

# 重启应用池
...

3. 确保应用池完全停止后再执行复制

替换固定等待时间为循环检查应用池状态,直到确认完全停止:

if((Get-WebAppPoolState -Name $application_pool_name).Value -ne 'Stopped'){
    Write-Output ('Stopping Application Pool: {0}' -f $application_pool_name)
    Stop-WebAppPool -Name $application_pool_name

    # 循环检查应用池状态,最多等待30秒
    $timeout = 30
    $elapsed = 0
    while((Get-WebAppPoolState -Name $application_pool_name).Value -ne 'Stopped' -and $elapsed -lt $timeout){
        Start-Sleep -s 1
        $elapsed++
    }

    if($elapsed -ge $timeout){
        Write-Warning "Application pool $application_pool_name did not stop within 30 seconds"
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 11:43:22