2015-09-07 29 views
10

Używam PSVersion 2.0 i zastanawiałem się, czy istnieje odpowiednik dla ?Czy istnieje mechanizm tracertowy PowerShell, który działa w wersji 2?

Jestem świadomy, że na PowerShell v4 znajduje się cmdlet Test-NetConnection, aby wykonać polecenie tracert, ale v2 ?! Można to zrobić tak:

Test-NetConnection "IPaddress/HOSTaname" -TraceRoute 

Dzięki

+1

Można używać oryginalnego 'tracert.exe' z PowerShell, wystarczy przeanalizować wyjście samemu –

+0

Dzięki stary, masz bardzo mi pomogło !!! – Sylca

Odpowiedz

17

Jak wspomniano w komentarzu, można dokonać własnych "poor-Mans PowerShell-tracert" przez parsowania wyjście z tracert.exe:

function Invoke-Tracert { 
    param([string]$RemoteHost) 

    tracert $RemoteHost |ForEach-Object{ 
     if($_.Trim() -match "Tracing route to .*") { 
      Write-Host $_ -ForegroundColor Green 
     } elseif ($_.Trim() -match "^\d{1,2}\s+") { 
      $n,$a1,$a2,$a3,$target,$null = $_.Trim()-split"\s{2,}" 
      $Properties = @{ 
       Hop = $n; 
       First = $a1; 
       Second = $a2; 
       Third = $a3; 
       Node = $target 
      } 
      New-Object psobject -Property $Properties 
     } 
    } 
} 

domyślnie formaty PowerShell obiektów z 5 lub więcej właściwości na liście, ale można dostać tracert -Jak wyjście z Format-Table:

enter image description here

+0

Zdecydowanie przeszedłeś tutaj. Dobra robota! –

+0

Dzięki! Zgadzam się z @MikeShepard – Sylca

3

Muszę przyznać, że chciałem sprawdzić, czy ktoś już to zrobił.

Można użyć .NET Framework wdrożyć nie tak niskiej Mans traceroute jako PowerShell Script

Tutaj grunt, że działa szybko, ale niebezpieczne. Również brak statystyk.

# 
# Mid-Waged-Mans-Tracert 
# 

$ping = new-object System.Net.NetworkInformation.Ping 
$timeout = 5000 
$maxttl = 64 
$address = [string]$args 
$message = [System.Text.Encoding]::Default.GetBytes("MESSAGE") 
$dontfragment = false 
$success = [System.Net.NetworkInformation.IPStatus]::Success 

echo "Tracing $address" 
for ($ttl=1;$i -le $maxttl; $ttl++) { 
    $popt = new-object System.Net.NetworkInformation.PingOptions($ttl, $dontfragment) 
    $reply = $ping.Send($address, $timeout, $message, $popt) 


    $addr = $reply.Address 
    $rtt = $reply.RoundtripTime 
    try { 
     $dns = [System.Net.Dns]::GetHostByAddress($addr) 
    } catch { 
     $dns = "-" 
    } 

    $name = $dns.HostName 

    echo "Hop: $ttl`t= $addr`t($name)" 
    if($reply.Status -eq $success) {break} 
} 

Edit:

Usunięto niektóre niebezpieczeństwie dodając oświadczenie catch. Jedynym niebezpieczeństwo że wciąż jest obecny, jest fakt, że możemy wysłać tylko jeden wniosek za hopu, co może oznaczać, że nie dotrzeć hop powodu niewinny opakowania kropli. Rozwiązanie tego problemu pozostaje ćwiczeniem dla czytelników. Podpowiedź: (Pomyśl o pętlach w pętlach)

Bonus: Teraz próbujemy uzyskać wpis dns każdego skoku!

+0

Ładne podejście "native", niesamowite! Może tłumaczysz "niebezpieczeństwo"? :-) –

+1

Niebezpieczeństwo związane z brakiem redundancji (jeśli jedna wiadomość icmp zostanie utracona, nie otrzymamy wyniku dla tego konkretnego skoku) + nie złapaliśmy wyjątku PingException. – MrPaulch

4

Naprawiono kilka błędów w wersji "Mid-Waged-Mans-Tracert", modularyzowałem je i dodawałem kilka elementów dostosowujących. @MrPaulch miał świetny PoC.

function Invoke-Traceroute{ 
    [CmdletBinding()] 
    Param(
     [Parameter(Mandatory=$true,Position=1)] 
     [string]$Destination, 

     [Parameter(Mandatory=$false)] 
     [int]$MaxTTL=16, 

     [Parameter(Mandatory=$false)] 
     [bool]$Fragmentation=$false, 

     [Parameter(Mandatory=$false)] 
     [bool]$VerboseOutput=$true, 

     [Parameter(Mandatory=$false)] 
     [int]$Timeout=5000 
    ) 

    $ping = new-object System.Net.NetworkInformation.Ping 
    $success = [System.Net.NetworkInformation.IPStatus]::Success 
    $results = @() 

    if($VerboseOutput){Write-Host "Tracing to $Destination"} 
    for ($i=1; $i -le $MaxTTL; $i++) { 
     $popt = new-object System.Net.NetworkInformation.PingOptions($i, $Fragmentation) 
     $reply = $ping.Send($Destination, $Timeout, [System.Text.Encoding]::Default.GetBytes("MESSAGE"), $popt) 
     $addr = $reply.Address 

     try{$dns = [System.Net.Dns]::GetHostByAddress($addr)} 
     catch{$dns = "-"} 

     $name = $dns.HostName 

     $obj = New-Object -TypeName PSObject 
     $obj | Add-Member -MemberType NoteProperty -Name hop -Value $i 
     $obj | Add-Member -MemberType NoteProperty -Name address -Value $addr 
     $obj | Add-Member -MemberType NoteProperty -Name dns_name -Value $name 
     $obj | Add-Member -MemberType NoteProperty -Name latency -Value $reply.RoundTripTime 

     if($VerboseOutput){Write-Host "Hop: $i`t= $addr`t($name)"} 
     $results += $obj 

     if($reply.Status -eq $success){break} 
    } 

    Return $results 
}