使用TeamCity+MSDeploy部署ASP.NET应用时遇ERROR_FILE_IN_USE问题求助
解决ASP.NET 4.6.1部署时ERROR_FILE_IN_USE的方案
我之前也碰到过类似的棘手问题,给你几个经过实际验证的解决方案,按优先级排序推荐:
1. 改用Web Deploy(MSDeploy)部署(最推荐)
直接用MSBuild复制文件很容易踩文件锁定的坑,而Web Deploy是微软专门为IIS部署打造的工具,内置了文件冲突处理逻辑。你可以在TeamCity的MSBuild构建步骤中添加以下参数,让MSBuild直接调用Web Deploy完成部署:
/p:DeployOnBuild=true /p:WebPublishMethod=MSDeploy /p:MSDeployServiceUrl=你的远程IIS服务器地址(比如http://servername/MSDeployAgentService) /p:DeployIisAppPath=你的网站名称(比如Default Web Site/YourApp) /p:Username=有权限部署的IIS账户 /p:Password=账户密码 /p:AllowUntrustedCertificate=true(如果服务器用自签名证书的话)
Web Deploy会自动处理文件锁定:它会多次尝试替换被占用的文件,必要时会短暂触发应用池回收(这个过程通常只有几秒,用户几乎感知不到),部署完成后还会自动恢复应用,不用手动维护app_offline.htm。
2. 修复app_offline.htm的使用姿势
你之前用app_offline.htm没效果,大概率是时机或者文件本身的问题。正确的流程应该是:
- 部署开始前,先把
app_offline.htm上传到网站根目录(注意文件不能太小,至少1KB,比如写一段友好的维护提示文案) - 等待3-5秒,让IIS识别到这个文件并暂停应用(此时用户访问会看到维护页)
- 执行MSBuild部署操作
- 部署完成后,立即删除
app_offline.htm,IIS会自动重启应用
你可以在TeamCity中添加两个PowerShell步骤配合MSBuild:
- 第一步:上传
app_offline.htm到远程服务器(用Copy-Item或者Invoke-Command远程执行),然后执行Start-Sleep -Seconds 5 - 第二步:执行MSBuild构建部署
- 第三步:删除远程服务器上的
app_offline.htm
3. 用Robocopy带重试机制复制文件
如果不想切换到Web Deploy,可以用Robocopy替代普通的文件复制命令,它自带重试锁定文件的功能。在TeamCity中添加一个命令行步骤,执行类似这样的命令:
robocopy "本地编译输出目录" "\\远程服务器\网站根目录共享" /MIR /R:10 /W:3 /NP
参数说明:
/MIR:镜像复制(同步目录结构和文件)/R:10:每个锁定的文件重试10次/W:3:每次重试等待3秒/NP:不显示复制进度(可选)
Robocopy会持续尝试替换被锁定的文件,直到成功或者达到重试次数,适合你这种部署耗时较长的场景。
4. 调整IIS应用池设置
检查并修改以下应用池设置,可能会缓解文件锁定问题:
- 启用Load User Profile:在应用池的高级设置中,找到
Load User Profile,设置为True。有些情况下,禁用这个选项会导致文件句柄无法正确释放。 - 保留重叠回收:确保
Disable Overlapped Recycling设置为False(默认就是False)。这样当应用池回收时,新进程会先启动处理请求,旧进程在处理完现有请求后再退出,此时旧进程锁定的文件会被释放,你可以在回收触发后再进行文件替换。
5. 预编译网站
预编译ASP.NET网站可以减少部署时的文件锁定概率。在MSBuild参数中添加:
/p:PrecompileBeforePublish=true /p:EnableUpdateable=false
预编译后,网站的大部分逻辑会被编译成DLL,部署时这些文件被锁定的几率更低,而且整体部署速度也会更快。
内容的提问来源于stack exchange,提问作者Ryan V
相关产品推荐
相关产品推荐

