我是PowerShell的新手,我想从多个XML文件中读取每个文件,每个文件都有服务器和服务。这些XML文件的结构各不相同。
<application name="AutoCAD">
<server name="server1">
<services>
<service name="Flexlm Service 1" />
</services>
</server>
<server name="server2">
<services>
<service name="Flexlm Service 1" />
</services>
</server>
<server name="server3">
<services>
<service name="Flexlm Service 1" />
</services>
</server>
</application>
我想阅读每个XML文件并提取服务器名称以及我想要检查它是否正在运行的服务。
我目前的代码几乎正常运行,但它认为每台服务器有3项服务。我尝试了很多东西,但现在卡住了。
$stopped = "ERROR"
$running = "RUNNING"
Get-ChildItem "C:\Users\rjohnso1\Desktop\Reports\XML" -Filter *.xml |
Foreach-Object {
$content = [xml](Get-Content $_.FullName)
$servicesReport = @()
$computer = $content.application.server.name
$appName = $content.application.name
$service = $content.application.server.services.service.name
foreach ($computers in $computer){
foreach ($services in $service){
$serviceName = Invoke-Command -ComputerName $computers -ScriptBlock {Get-WmiObject -Class Win32_Service}
if ($serviceName.State -eq 'Running'){
$row = "$($appName) $($computers) $($services) $($running) "
}
elseif ($serviceName.State -eq 'Stopped'){
$row = "$($appName) $($services) $($stopped) "
$error = "$($appName) $($service) "
}
$row += $servicesReport
Write-Host $row
}
}
}
任何帮助将不胜感激,谢谢。
答案 0 :(得分:0)
由于您已经在xml文档中的第一个循环之前已经使用所有服务节点填充了$service
,因此您将在每个循环中循环遍历所有这些服务节点服务器。将其更改为:
$content = [xml](Get-Content $_.FullName)
$servicesReport = @()
$appName = $content.application.name
foreach ($computer in $content.application.server){
foreach ($service in $computer.services.service){
$serviceName = $service.Name
Write-Host $serviceName
$serviceInstance = Invoke-Command -ComputerName $computer.name -ScriptBlock {Get-WmiObject -Class Win32_Service -Filter "DisplayName = '$serviceName'"}
if ($serviceInstance.State -eq 'Running'){
$row = "$($appName) $($computer) $($service) $($running) "
}
elseif ($serviceName.State -eq 'Stopped'){
$row = "$($appName) $($service) $($stopped) "
$error = "$($appName) $($service) "
}
$servicesReport += $row
Write-Host $row
}
}
现在,如果$row
或$appName
中包含任何空格,则每个$serviceName
作为单个字符串并不是非常有用。要让它输出结构化数据,请改为创建一堆对象:
$stopped = "ERROR"
$running = "RUNNING"
Get-ChildItem "C:\Users\rjohnso1\Desktop\Reports\XML" -Filter *.xml | ForEach-Object {
$content = [xml](Get-Content $_.FullName)
$servicesReport = @()
$appName = $content.application.name
foreach ($computer in $content.application.server){
foreach ($service in $computer.services.service){
$serviceName = $service.name
Write-Host $serviceName
$serviceInstance = Invoke-Command -ComputerName $computer.name -ScriptBlock {Get-WmiObject -Class Win32_Service -Filter "DisplayName = '$serviceName'"}
$row = [pscustomobject]@{
AppName = $appName
Server = $computer.name
Service = $serviceName
State = if($serviceInstance.State -eq 'Running'){$running}else{$stopped}
}
$servicesReport += $row
}
}
# Here you could export your $servicesReport to CSV or HTML with Export-Csv or ConvertTo-Html |Out-File
}