1

所以我写了一个简单的 pinger 来 ping 一个网络。我正在使用测试连接,但我也得到了设计名称。

所以我使用 cmd 的 nbtstat 来获取名称,但是(可以说它不干净)

有没有办法做到这一点更清洁?

这就是我所拥有的

$a = New-Object System.Collections.ArrayList

for ($i =0;$i -le 225; $i++){
    if (Test-Connection 192.168.1.$i -Count 1 -Quiet){
        echo "live 192.168.1.$i"
        $a.add("192.168.1.$i")
    }else {
        echo "dead 192.168.1.$i"
    }
}
echo $a
foreach ($i in $a){
    Test-Connection $i -Count 1

}

foreach ($i in $a){
    nbtstat -a $i
}
4

3 回答 3

3

做某事总是有很多方法,一个这样的例子:

$Pinger = New-Object system.Net.NetworkInformation.Ping
$PC = "192.168.1.$i"

try{
            $ErrorActionPreference = "Stop"
            $PingResult = $Pinger.send($PC)
            $ResultAddress = $PingResult.Address
            $PingStatus = $PingResult.Status

            $DNSObject = [System.Net.Dns]::GetHostEntry($PC).HostName

    }
    catch
    {

    }
    finally
    {
        Write-Host "$PC $PingStatus $PingHost $? $DNSObject"
    }

这比您要求的要多,但我认为它也可能给您一些想法:

  • .NET 供您使用,而不仅仅是本机 cmdlet 和 Windows 命令
  • 是否使用 $ 之类的内置运算符?
于 2013-07-24T14:55:11.073 回答
3

我会做的有点不同。每次联系主机时,都会创建一个 ARP 条目。为什么不利用它?

Get-WmiObject Win32_PingStatus -Filter "Address='192.168.1.2' AND ResolveAddressNames='true'" | 
Select IPV4Address, ProtocolAddressResolved, @{
    Name="PhysicalAddress";Expression={
        ([regex]::Matches($(arp -a $_.IPV4Address),"[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}",@('MultiLine', 'Ignorecase'))).value
    }
}
于 2013-07-24T14:59:10.653 回答
1

Test-Connection现在Test-NetConnection支持返回更多信息,包括名称。后者需要 Power Shell 5。

测试连接

EXAMPLES
Example 1: Send echo requests to a remote computer

PS C:\> Test-Connection "Server01"

Source        Destination     IPV4Address     IPV6Address  Bytes    Time(ms)
------        -----------     -----------     -----------  -----    --------
ADMIN1        Server01         10.59.137.44                32       0
ADMIN1        Server01         10.59.137.44                32       0
ADMIN1        Server01         10.59.137.44                32       0
ADMIN1        Server01         10.59.137.44                32       1

资源

测试网络连接

Test ping connectivity with detailed results

PS C:\> Test-NetConnection -InformationLevel "Detailed"
ComputerName           : internetbeacon.msedge.net

RemoteAddress          : 2a01:111:2003::52

NameResolutionResults  : 2a01:111:2003::52

                         13.107.4.52

InterfaceAlias         : Ethernet

SourceAddress          : 2001:4898:d8:33:81e8:7b49:8bf5:8710

NetRoute (NextHop)     : fe80::200:5eff:fe00:203

PingSucceeded          : True

PingReplyDetails (RTT) : 6 ms

资源

此外,您提到您正在 ping 整个网络。这就是你的问题(以及其他问题)的发现方式,因为我也试图进行 ping 扫描。我选择了这个剧本。这家伙称它为Fast Ping Sweep Asynchronous

即使是 Power Shell n00b,我也能够通过管道传输其输出,然后修改其输出以仅包含我想要的内容。我遇到了其他脚本,但无法破译它们的脚本来修改它们以达到我的目的。

我不确定这需要什么版本的 Power Shell,但它适用于 v4 和 v5。

我见过大多数 Powershell IP 扫描器,ping 扫描脚本,但没有一个使用 PingASync 方法。同步脚本的“问题”是它们必须等到节点回复或超时才能继续下一个地址。使用这种方法可能需要

function Global:Ping-IPRange {
    <#
    .SYNOPSIS
        Sends ICMP echo request packets to a range of IPv4 addresses between two given addresses.

    .DESCRIPTION
        This function lets you sends ICMP echo request packets ("pings") to 
        a range of IPv4 addresses using an asynchronous method.

        Therefore this technique is very fast but comes with a warning.
        Ping sweeping a large subnet or network with many swithes may result in 
        a peak of broadcast traffic.
        Use the -Interval parameter to adjust the time between each ping request.
        For example, an interval of 60 milliseconds is suitable for wireless networks.
        The RawOutput parameter switches the output to an unformated
        [System.Net.NetworkInformation.PingReply[]].

    .INPUTS
        None
        You cannot pipe input to this funcion.

    .OUTPUTS
        The function only returns output from successful pings.

        Type: System.Net.NetworkInformation.PingReply

        The RawOutput parameter switches the output to an unformated
        [System.Net.NetworkInformation.PingReply[]].

    .NOTES
        Author  : G.A.F.F. Jakobs
        Created : August 30, 2014
        Version : 6

    .EXAMPLE
        Ping-IPRange -StartAddress 192.168.1.1 -EndAddress 192.168.1.254 -Interval 20

        IPAddress                                 Bytes                     Ttl           ResponseTime
        ---------                                 -----                     ---           ------------
        192.168.1.41                                 32                      64                    371
        192.168.1.57                                 32                     128                      0
        192.168.1.64                                 32                     128                      1
        192.168.1.63                                 32                      64                     88
        192.168.1.254                                32                      64                      0

        In this example all the ip addresses between 192.168.1.1 and 192.168.1.254 are pinged using 
        a 20 millisecond interval between each request.
        All the addresses that reply the ping request are listed.

    .LINK
        http://gallery.technet.microsoft.com/Fast-asynchronous-ping-IP-d0a5cf0e

    #>
    [CmdletBinding(ConfirmImpact='Low')]
    Param(
        [parameter(Mandatory = $true, Position = 0)]
        [System.Net.IPAddress]$StartAddress,
        [parameter(Mandatory = $true, Position = 1)]
        [System.Net.IPAddress]$EndAddress,
        [int]$Interval = 30,
        [Switch]$RawOutput = $false
    )

    $timeout = 2000

    function New-Range ($start, $end) {

        [byte[]]$BySt = $start.GetAddressBytes()
        [Array]::Reverse($BySt)
        [byte[]]$ByEn = $end.GetAddressBytes()
        [Array]::Reverse($ByEn)
        $i1 = [System.BitConverter]::ToUInt32($BySt,0)
        $i2 = [System.BitConverter]::ToUInt32($ByEn,0)
        for($x = $i1;$x -le $i2;$x++){
            $ip = ([System.Net.IPAddress]$x).GetAddressBytes()
            [Array]::Reverse($ip)
            [System.Net.IPAddress]::Parse($($ip -join '.'))
        }
    }

    $IPrange = New-Range $StartAddress $EndAddress

    $IpTotal = $IPrange.Count

    Get-Event -SourceIdentifier "ID-Ping*" | Remove-Event
    Get-EventSubscriber -SourceIdentifier "ID-Ping*" | Unregister-Event

    $IPrange | foreach{

        [string]$VarName = "Ping_" + $_.Address

        New-Variable -Name $VarName -Value (New-Object System.Net.NetworkInformation.Ping)

        Register-ObjectEvent -InputObject (Get-Variable $VarName -ValueOnly) -EventName PingCompleted -SourceIdentifier "ID-$VarName"

        (Get-Variable $VarName -ValueOnly).SendAsync($_,$timeout,$VarName)

        Remove-Variable $VarName

        try{

            $pending = (Get-Event -SourceIdentifier "ID-Ping*").Count

        }catch [System.InvalidOperationException]{}

        $index = [array]::indexof($IPrange,$_)

        Write-Progress -Activity "Sending ping to" -Id 1 -status $_.IPAddressToString -PercentComplete (($index / $IpTotal)  * 100)

        Write-Progress -Activity "ICMP requests pending" -Id 2 -ParentId 1 -Status ($index - $pending) -PercentComplete (($index - $pending)/$IpTotal * 100)

        Start-Sleep -Milliseconds $Interval
    }

    Write-Progress -Activity "Done sending ping requests" -Id 1 -Status 'Waiting' -PercentComplete 100 

    While($pending -lt $IpTotal){

        Wait-Event -SourceIdentifier "ID-Ping*" | Out-Null

        Start-Sleep -Milliseconds 10

        $pending = (Get-Event -SourceIdentifier "ID-Ping*").Count

        Write-Progress -Activity "ICMP requests pending" -Id 2 -ParentId 1 -Status ($IpTotal - $pending) -PercentComplete (($IpTotal - $pending)/$IpTotal * 100)
    }

    if($RawOutput){

        $Reply = Get-Event -SourceIdentifier "ID-Ping*" | ForEach { 
            If($_.SourceEventArgs.Reply.Status -eq "Success"){
                $_.SourceEventArgs.Reply
            }
            Unregister-Event $_.SourceIdentifier
            Remove-Event $_.SourceIdentifier
        }

    }else{

        $Reply = Get-Event -SourceIdentifier "ID-Ping*" | ForEach { 
            If($_.SourceEventArgs.Reply.Status -eq "Success"){
                $_.SourceEventArgs.Reply | select @{
                      Name="IPAddress"   ; Expression={$_.Address}},
                    @{Name="Bytes"       ; Expression={$_.Buffer.Length}},
                    @{Name="Ttl"         ; Expression={$_.Options.Ttl}},
                    @{Name="ResponseTime"; Expression={$_.RoundtripTime}}
            }
            Unregister-Event $_.SourceIdentifier
            Remove-Event $_.SourceIdentifier
        }
    }
    if($Reply -eq $Null){
        Write-Verbose "Ping-IPrange : No ip address responded" -Verbose
    }

    return $Reply
}
于 2017-07-29T14:18:28.550 回答