我正在编写一个自动化站点备份powershell脚本。
我在从appcmd.exe获取的[xml]转换变量中有以下xml:
<application path="/" applicationPool="komplus.ua-PROD">
<virtualDirectoryDefaults />
<virtualDirectory path="/" physicalPath="C:\WEB\PROD\komplus.ua" />
</application>
<application path="/kb" applicationPool="komplus.ua-PROD" enabledProtocols="http, https">
<virtualDirectoryDefaults />
<virtualDirectory path="/" physicalPath="C:\WEB\PROD\komplus.ua\kb" />
</application>
xml位于变量$ xmlInput。
中我需要在第一个应用程序元素中获取VirtualDirectory元素的physicalPath属性的值。
我尝试了多种选项,包括自定义Get-XmlElement功能,但似乎无法获得该值。
目前我有:
$selectResult = $xmlInput.application.virtualDirectory | Select physicalPath
但$ selectResult为null。
请协助解析正确以获得我需要的值。
更新
这是我用来获取完整路径的完整功能:
function GetPhysicalPath ([String]$siteName) {
function Get-PipelineInput
{
end {
$inputAsVar = 'Current input is:' + $input
write-host "##teamcity[message text='$inputAsVar']"
write-host "##teamcity[message text='About to cast to xml']"
$xmlInput = [xml]@"<root>$input</root>"@
write-host "##teamcity[message text='Cast to xml finished.']"
$selectResult = $xml.root.Application | Where-Object { $_.path -eq '/' } | ForEach-Object { $_.virtualDirectory.physicalPath }
write-host "##teamcity[message text='$selectResult']"
return $selectResult
#$node = Get-XmlNode -XmlDocument $xmlInput -NodePath "application.virtualDirectory"
#$nodeAsVar = 'Single node is:' + $node
#write-host "##teamcity[message text='$nodeAsVar']"
#if ($node -eq $null) { return $null }
#return $node.physicalPath
}
}
$appCmd = "$Env:SystemRoot\system32\inetsrv\appcmd.exe"
return & $appCmd list app /site.name:"$siteName" /config | Get-PipelineInput
}
答案 0 :(得分:2)
您的xml无效。 XML需要根元素。如果“xml”-file缺少它,那么将文件的内容自己包装在根元素中:
Get-ChildItem -Path C:\Users\Frode\Desktop -Filter "appcmd*" | ForEach-Object {
#Wrap "xml" in root element and convert to xml-type
$xml = [xml]@"
<root>
$([System.IO.File]::ReadAllText($_.FullName))
</root>
"@
#Get first physicalPath
$xml.root.Application[0].virtualDirectory.physicalPath
}
C:\WEB\PROD\komplus.ua
如果您使用PowerShell 3或更高版本,则可以将$([System.IO.File]::ReadAllText($_.FullName))
替换为更友好的$(Get-Content -Path $_.FullName -Raw))
。但是,ReadAllText()
通常更快,所以无论如何我都会使用它。
如果你想要root应用程序,你应该搜索它,而不是猜测它是第一个元素。你可以尝试这样的事情:
Get-ChildItem -Path C:\Users\Frode\Desktop -Filter "appcmd*" | ForEach-Object {
#Wrap "xml" in root element and convert to xml-type
$xml = [xml]@"
<root>
$(Get-Content -Path $_.FullName -Raw))
</root>
"@
#Get root app's physicalPath
$xml.root.Application | Where-Object { $_.path -eq '/' } | ForEach-Object { $_.virtualDirectory.physicalPath }
}
如果您直接从appcmd.exe(存储在变量中)获取xml内容,则修改如下:
$outputfromappcmd = appcmd.exe something something
#Wrap "xml" in root element and convert to xml-type
$xml = [xml]"<root>$outputfromappcmd </root>"
#Get first physicalPath
$xml.root.Application | Where-Object { $_.path -eq '/' } | ForEach-Object { $_.virtualDirectory.physicalPath }