从命令提示符调用PowerShell脚本更新XML文件遇报错求助
问题解决:PowerShell更新XML节点报错“The property '#text' cannot be found on this object”
问题背景
编写了用于更新XML节点的PowerShell脚本,通过cmd调用pwsh或PowerShell.exe执行时失败,报错:
The property '#text' cannot be found on this object. Verify that the property exists and can be set.
示例XML文件
<Job> <ProcFile name="jobName" /> <Category name="Indicative"> <Item name="rbfVersion">versionname</Item> <Item name="rbfRelease">releaseNumber</Item> </Category> <Category name="Parameters"> <Item name="MmsPzapAppId">Value1</Item> </Category> </Job>
原PowerShell脚本
param ($workingDir, $fileName, $arrayOfObject) if (!$workingDir) { throw "Working Directory Parameter is missing" }elseif(!$fileName){ throw "File name or Runbook name Parameter is missing" }elseif(!$arrayOfObject){ throw "Input parameters are missing" } $keyVauleHash = $arrayOfObject #concatenating two parameters to get full path $filePath = "$workingDir\$fileName" #Reading Values Write-Host "Working Directory: $workingDir" Write-Host "File Name : $fileName" Write-Host "Full Path : $filePath" Write-Host "Number of Nodes to be updated:"$keyVauleHash.Count #Get Content of XML file and store it in $xml file [xml]$xml = Get-Content $filePath #Looping through each key:value pair from array of object and updating respective nodes foreach($item in $keyVauleHash.GetEnumerator()){ $key = $item.key $value = $item.value $parametersNode = $xml.Job.Category | where {$_.Name -eq 'Parameters'} $foundNode = $parametersNode.Item | where {$_.Name -eq $key} Write-Output $foundNode $foundNode.'#text' = $value Write-Output $foundNode } #Saving the changes $xml.Save($filePath)
原调用命令
1. pwsh -command C:\Path\To\PowerShellScript\UpdateXML.ps1 -workingDir 'C:\Path\To\xmlFile' -fileName 'xmlFileName.xml' -arrayOfObject '@{InputFile="Value"}' 2. PowerShell.exe C:\Path\To\PowerShellScript\UpdateXML.ps1 -workingDir 'C:\Path\To\xmlFile' -fileName 'xmlFileName.xml' -arrayOfObject '@{InputFile="Value"}'
报错原因
- 参数传递错误:在cmd中直接传递
@{InputFile="Value"}时,该值会被解析为字符串而非哈希表。脚本中$keyVauleHash.GetEnumerator()执行后无法正确遍历键值对,导致后续找不到目标XML节点,$foundNode为$null或非预期对象,访问#text属性时报错。 - XML节点修改方式错误:PowerShell处理XML节点文本内容时,不应直接访问
'#text'属性,该属性并非所有XML节点都存在,正确方式是使用.InnerText或直接给节点赋值。 - 缺少节点存在性检查:当目标节点不存在时,直接执行赋值操作会触发报错。
解决方案
1. 修正参数传递方式
在cmd中调用PowerShell脚本传递哈希表,需用-Command包裹整个执行逻辑,并用&调用脚本,确保哈希表被正确解析:
# pwsh 调用 pwsh -Command "& 'C:\Path\To\PowerShellScript\UpdateXML.ps1' -workingDir 'C:\Path\To\xmlFile' -fileName 'xmlFileName.xml' -arrayOfObject @{InputFile='Value'}" # PowerShell.exe 调用 PowerShell.exe -Command "& 'C:\Path\To\PowerShellScript\UpdateXML.ps1' -workingDir 'C:\Path\To\xmlFile' -fileName 'xmlFileName.xml' -arrayOfObject @{InputFile='Value'}"
如果需要传递更复杂的参数,建议用JSON格式传递,脚本内再转换为哈希表:
# 调用命令 pwsh -Command "& 'C:\Path\To\PowerShellScript\UpdateXML.ps1' -workingDir 'C:\Path\To\xmlFile' -fileName 'xmlFileName.xml' -arrayOfObject '{\"InputFile\":\"Value\",\"AnotherKey\":\"AnotherValue\"}'"
脚本内添加JSON转换逻辑:
$keyVauleHash = if ($arrayOfObject -is [string]) { ConvertFrom-Json $arrayOfObject -AsHashtable } else { $arrayOfObject }
2. 修正XML节点修改逻辑
将$foundNode.'#text' = $value替换为$foundNode.InnerText = $value,或直接赋值$foundNode = $value(PowerShell会自动处理XML节点文本)。同时添加节点存在性检查,避免空对象报错。
3. 修改后的完整脚本
param ($workingDir, $fileName, $arrayOfObject) if (!$workingDir) { throw "Working Directory Parameter is missing" } elseif (!$fileName) { throw "File name or Runbook name Parameter is missing" } elseif (!$arrayOfObject) { throw "Input parameters are missing" } # 处理参数:如果是字符串则尝试转为哈希表 $keyVauleHash = if ($arrayOfObject -is [string]) { try { ConvertFrom-Json $arrayOfObject -AsHashtable } catch { throw "Invalid input format for arrayOfObject, expected hashtable or JSON string" } } else { $arrayOfObject } # 拼接文件路径 $filePath = Join-Path -Path $workingDir -ChildPath $fileName # 输出调试信息 Write-Host "Working Directory: $workingDir" Write-Host "File Name : $fileName" Write-Host "Full Path : $filePath" Write-Host "Number of Nodes to be updated: $($keyVauleHash.Count)" # 读取XML文件 [xml]$xml = Get-Content -Path $filePath -Raw # 获取Parameters分类节点 $parametersNode = $xml.Job.Category | Where-Object { $_.Name -eq 'Parameters' } if (!$parametersNode) { throw "Category node 'Parameters' not found in XML" } # 遍历键值对更新节点 foreach ($item in $keyVauleHash.GetEnumerator()) { $key = $item.Key $value = $item.Value $foundNode = $parametersNode.Item | Where-Object { $_.Name -eq $key } if ($foundNode) { Write-Output "Updating node '$key' from '$($foundNode.InnerText)' to '$value'" $foundNode.InnerText = $value Write-Output "Updated node: $foundNode" } else { Write-Warning "Node with name '$key' not found in Parameters category" } } # 保存修改 $xml.Save($filePath) Write-Host "XML file updated successfully"
验证执行
执行修正后的调用命令,脚本会正确找到目标节点并更新文本内容,不会再出现#text属性不存在的报错。
内容的提问来源于stack exchange,提问作者New Progrommer
相关产品推荐
相关产品推荐

