使用 PowerShell 在 XML 文件中的 ForEach [英] ForEach in XML file with PowerShell
问题描述
我在 $DSConfigPath
有一个 XML 文件,其中包含如下信息:
<add id="DataSource1" type="Fixed" distance="1"><参数><姓名/><address>10.1.1.10</address><otherIdentifiers>DataSource1</otherIdentifiers><activeStatus>true</activeStatus><ip>10.1.1.10</ip><端口>952</端口></参数></添加><add id="DataSource2" type="Fixed" distance="2"><参数><姓名/><address>10.1.1.11</address><otherIdentifiers>DataSource2</otherIdentifiers><activeStatus>true</activeStatus><ip>10.1.1.11</ip><端口>952</端口></参数></添加><add id="DataSource3" type="Fixed" distance="3"><参数><姓名/><address>10.1.1.12</address><otherIdentifiers>DataSource1</otherIdentifiers><activeStatus>false</activeStatus><ip>10.1.1.12</ip><端口>952</端口></参数></添加></数据源>
我的目标是对
为true"的任何 IP/端口进行端口连接测试.
我有以下函数,当我输入特定的 $hostname
和 $port
时,我已经验证了它会给我正确的结果:>
function Test-Port($hostname, $port) {# 无论我们以哪种形式获得 $host - 主机名或 IP 地址,这都有效尝试 {$ip = [System.Net.Dns]::GetHostAddresses($hostname) |选择对象 IPAddressToString -ExpandProperty IPAddressToStringif ($ip.GetType().Name -eq "Object[]") {#如果该地址有多个ip,我们取第一个$ip = $ip[0]}} 抓住 {写主机可能 $hostname 是错误的主机名或 IP"返回}$t = 新对象 Net.Sockets.TcpClient# 如果无法连接,我们使用 Try\Catch 从控制台中删除异常信息尝试 {$t.Connect($ip,$port)} 抓住 {}如果 ($t.Connected) {$t.Close()$msg = "端口 $port 可用"} 别的 {$msg = "$ip 上的端口 $port 已关闭,"$msg += "您可能需要联系您的 IT 团队才能打开它."}写主机 $msg}
所以现在当我添加以下变量时:
[xml]$DSConfig = gc "$DSConfigPath"$DS = $dsconfig.datasources.add.parameters$DSName = $DS.otherIdentifiers$DSIP = $DS.ip$DSPort = $DS.port$DSActive = $DS |Where-Object {$_.activeStatus -eq 'True'}$hostname = $DSIP # 是的,我意识到这是多余的$port = $DSPORT # 是的,我意识到这也是多余的
然后运行:
foreach ($DSActive in $DSConfig) {Test-Port $hostname $port}
我得到了结果:
<前>可能 10.1.1.10 10.1.1.11 是错误的主机名或 IP有什么建议可以让我测试与 10.1.1.10:952 的连接,给出该结果,然后测试与 10.1.1.11:952 的连接,然后给出该结果?
使用SelectNodes()
从xml文档中抓取
节点:>
# 读取 XML 文档[xml]$DSConfig = gc "$DSConfigPath"# 选择<参数>节点$ParametersNode = $DSConfig.SelectNodes('//参数')# 循环选中节点foreach($ParametersNode 中的$Node){# 测试是否 activeStatus == 'true'if($Node.activeStatus -eq 'true') {# 运行测试端口命令测试端口 $Node.ip -port $Node.port}}
I have an XML file at $DSConfigPath
that contains information as such:
<dataSources>
<add id="DataSource1" type="Fixed" distance="1">
<parameters>
<name />
<address>10.1.1.10</address>
<otherIdentifiers>DataSource1</otherIdentifiers>
<activeStatus>true</activeStatus>
<ip>10.1.1.10</ip>
<port>952</port>
</parameters>
</add>
<add id="DataSource2" type="Fixed" distance="2">
<parameters>
<name />
<address>10.1.1.11</address>
<otherIdentifiers>DataSource2</otherIdentifiers>
<activeStatus>true</activeStatus>
<ip>10.1.1.11</ip>
<port>952</port>
</parameters>
</add>
<add id="DataSource3" type="Fixed" distance="3">
<parameters>
<name />
<address>10.1.1.12</address>
<otherIdentifiers>DataSource1</otherIdentifiers>
<activeStatus>false</activeStatus>
<ip>10.1.1.12</ip>
<port>952</port>
</parameters>
</add>
</dataSources>
My goal is to do a do a port connection test to any IP/port where the <activeStatus>
is 'true.'
I've got the following function, which I've verified will give me the correct results when I put in a specific $hostname
and $port
:
function Test-Port($hostname, $port) {
# This works no matter in which form we get $host - hostname or ip address
try {
$ip = [System.Net.Dns]::GetHostAddresses($hostname) |
Select-Object IPAddressToString -ExpandProperty IPAddressToString
if ($ip.GetType().Name -eq "Object[]") {
#If we have several ip's for that address, let's take first one
$ip = $ip[0]
}
} catch {
Write-Host "Possibly $hostname is wrong hostname or IP"
return
}
$t = New-Object Net.Sockets.TcpClient
# We use Try\Catch to remove exception info from console if we can't connect
try {
$t.Connect($ip,$port)
} catch {}
if ($t.Connected) {
$t.Close()
$msg = "Port $port is operational"
} else {
$msg = "Port $port on $ip is closed, "
$msg += "You may need to contact your IT team to open it. "
}
Write-Host $msg
}
So now when I add the following variables:
[xml]$DSConfig = gc "$DSConfigPath"
$DS = $dsconfig.datasources.add.parameters
$DSName = $DS.otherIdentifiers
$DSIP = $DS.ip
$DSPort = $DS.port
$DSActive = $DS | Where-Object {$_.activeStatus -eq 'True'}
$hostname = $DSIP # yes I realize this is redundant
$port = $DSPORT # and yes, I realize this is redundant as well
Then run:
foreach ($DSActive in $DSConfig) {Test-Port $hostname $port}
I get the result:
Possibly 10.1.1.10 10.1.1.11is wrong hostname or IP
Any suggestion how I can get it to test the connection to 10.1.1.10:952, give that result, then test the connection to 10.1.1.11:952 and then give that result?
Use SelectNodes()
to grab the <parameters>
nodes from the xml document:
# Read XML document
[xml]$DSConfig = gc "$DSConfigPath"
# Select <parameters> nodes
$ParametersNode = $DSConfig.SelectNodes('//parameters')
# Loop over selected nodes
foreach($Node in $ParametersNode){
# Test if activeStatus == 'true'
if($Node.activeStatus -eq 'true') {
# Run the Test-Port command
Test-Port $Node.ip -port $Node.port
}
}
这篇关于使用 PowerShell 在 XML 文件中的 ForEach的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!