使用 PowerShell 在 XML 文件中的 ForEach [英] ForEach in XML file with PowerShell

查看:30
本文介绍了使用 PowerShell 在 XML 文件中的 ForEach的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 $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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆