Azure发布阶段用PowerShell更新web.config报错求助
Azure Release中修改Zip包内web.config的问题修复
问题场景
在Azure Release发布流程中,需要更新部署包(zip文件)内的web.config,在<system.webServer>节点下添加子节点,但执行PowerShell任务时出现报错,报错信息如下:
Exception calling "Open" with "2" argument(s): "Empty path name is not legal."
At C:\AzureAgents\Agent1_work_temp\aad4d934-d9ac-485c-9511-d8cb4e50e6d4.ps1:14 char:1
- $zip = [System.IO.Compression.ZipFile]::Open($zipfileName.FullName," ...
+ CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : ArgumentException
原使用的PowerShell脚本如下:
# cd to the agent artifacts directory (where the zip file exist) cd $env:Agent_ReleaseDirectory cd _Your.Project-CI\drop $fileToEdit = "web.config" [Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem"); # Open zip and find the particular file (assumes only one inside the Zip file) $zipfileName = dir -filter '*.zip' $zip = [System.IO.Compression.ZipFile]::Open($zipfileName.FullName,"Update") $configFile = $zip.Entries.Where({$_.name -like $fileToEdit}) # Read the contents of the file $desiredFile = [System.IO.StreamReader]($configFile).Open() $text = $desiredFile.ReadToEnd() $desiredFile.Close() $desiredFile.Dispose() $contentToAdd1 = @' <system.webServer> <modules> <albert> <remove name="WebDAVModule" /> </modules> '@ #$text[3] = $text[3] -replace '<system.webServer>',$contentToAdd1 $text = $text -replace '<system.webServer>',$contentToAdd1 #update file with new content $desiredFile = [System.IO.StreamWriter]($configFile).Open() $desiredFile.BaseStream.SetLength(0) # Insert the $text to the file and close $desiredFile.Write($text) $desiredFile.Flush() $desiredFile.Close() # Write the changes and close the zip file $zip.Dispose()
错误原因分析
- Zip文件路径获取问题:
dir -filter '*.zip'可能返回多个文件或者未找到目标zip,导致$zipfileName.FullName为空,触发"Empty path name is not legal"错误。 - XML处理方式不合理:使用字符串替换修改XML内容容易破坏XML结构,比如存在多个
<system.webServer>节点或者节点带有属性时会出错。 - 流处理不规范:直接操作流时未正确处理异常,且未确保只选中一个目标文件。
修正后的脚本
# 切换到 artifacts 目录 $dropPath = Join-Path -Path $env:Agent_ReleaseDirectory -ChildPath "_Your.Project-CI\drop" Set-Location -Path $dropPath # 获取唯一的zip文件(如果有多个需要调整过滤条件) $zipFile = Get-ChildItem -Filter '*.zip' | Select-Object -First 1 if (-not $zipFile) { throw "未找到目标zip文件" } $webConfigName = "web.config" # 打开zip包 $zip = [System.IO.Compression.ZipFile]::Open($zipFile.FullName, "Update") try { # 查找zip内的web.config(确保只找到一个) $configEntry = $zip.Entries | Where-Object { $_.Name -eq $webConfigName } | Select-Object -First 1 if (-not $configEntry) { throw "zip包内未找到$webConfigName文件" } # 读取并解析XML内容 $xmlDoc = New-Object System.Xml.XmlDocument $stream = $configEntry.Open() try { $xmlDoc.Load($stream) } finally { $stream.Close() } # 找到system.webServer节点 $webServerNode = $xmlDoc.SelectSingleNode("//system.webServer") if ($webServerNode) { # 创建modules节点(如果不存在则创建) $modulesNode = $webServerNode.SelectSingleNode("modules") if (-not $modulesNode) { $modulesNode = $xmlDoc.CreateElement("modules") $webServerNode.AppendChild($modulesNode) | Out-Null } # 创建remove节点并添加到modules下 $removeNode = $xmlDoc.CreateElement("remove") $removeNode.SetAttribute("name", "WebDAVModule") $modulesNode.AppendChild($removeNode) | Out-Null } else { throw "未找到<system.webServer>节点" } # 将修改后的XML写回zip包 $stream = $configEntry.Open() try { $stream.SetLength(0) # 清空原有内容 $xmlDoc.Save($stream) } finally { $stream.Close() } } finally { $zip.Dispose() # 确保zip包被正确关闭 }
修正说明
- 确保Zip文件唯一:使用
Select-Object -First 1确保只获取一个zip文件,同时添加判断避免未找到文件的情况。 - 用XML对象操作:通过XmlDocument解析和修改XML,避免字符串替换带来的结构破坏问题,操作更可靠。
- 规范流处理:使用try/finally确保流和zip包被正确关闭,避免资源泄漏。
- 节点存在性判断:创建节点前先检查是否存在,避免重复添加。
内容的提问来源于stack exchange,提问作者Morelli
相关产品推荐
相关产品推荐

