PowerShell i .NET odgovor na pitanje - Da li je računar dostupan?

Kada koristite PowerShell možete na više načina proveriti da li je neki računar dostupan. PowerShell V2 nudi novi komandlet Test-Connection, a ako još uvek koristite V1 na raspolaganju vam je dobra stara ping komanda, WMI klasa Win32_PingStatus ili .Net klasa System.Net.NetworkInformation.Ping. Pozabavimo se malo .Net rešenjem. Prvo kreiramo novi objekt:

$Ping = New-Object System.Net.NetworkInformation.Ping

Objekt $Ping ima Send metod. Evo kako možemo videti validne načine za kreiranje instance:

$Ping | Get-Member Send | Format-List *
TypeName   : System.Net.NetworkInformation.Ping
Name       : Send
MemberType : Method
Definition : System.Net.NetworkInformation.PingReply Send(String hostNameOrAddress), System.Net.NetworkInformation.Ping
             Reply Send(String hostNameOrAddress, Int32 timeout), System.Net.NetworkInformation.PingReply Send(IPAddres
             s address), System.Net.NetworkInformation.PingReply Send(IPAddress address, Int32 timeout), System.Net.Net
             workInformation.PingReply Send(String hostNameOrAddress, Int32 timeout, Byte[] buffer), System.Net.Network
             Information.PingReply Send(IPAddress address, Int32 timeout, Byte[] buffer), System.Net.NetworkInformation
             .PingReply Send(String hostNameOrAddress, Int32 timeout, Byte[] buffer, PingOptions options), System.Net.N
             etworkInformation.PingReply Send(IPAddress address, Int32 timeout, Byte[] buffer, PingOptions options)

Koristićemo, recimo, Send(String hostNameOrAddress, Int32 timeout) konstruktor.

$Ping.Send($hostNameOrAddress,$timeout) vraća PingReply objekt (System.Net.NetworkInformation.PingReply). Ako pogledamo njegove metode i osobine, uočićemo da nedostaje podatak o imenu računara čiju dostupnost proveravamo:

$Ping.Send('localhost',1000) | Get-Member

   TypeName: System.Net.NetworkInformation.PingReply

Name              MemberType Definition
----              ---------- ----------
Equals            Method     System.Boolean Equals(Object obj)
GetHashCode       Method     System.Int32 GetHashCode()
GetType           Method     System.Type GetType()
get_Address       Method     System.Net.IPAddress get_Address()
get_Buffer        Method     System.Byte[] get_Buffer()
get_Options       Method     System.Net.NetworkInformation.PingOptions get_Options()
get_RoundtripTime Method     System.Int64 get_RoundtripTime()
get_Status        Method     System.Net.NetworkInformation.IPStatus get_Status()
ToString          Method     System.String ToString()
Address           Property   System.Net.IPAddress Address {get;}
Buffer            Property   System.Byte[] Buffer {get;}
Options           Property   System.Net.NetworkInformation.PingOptions Options {get;}
RoundtripTime     Property   System.Int64 RoundtripTime {get;}
Status            Property   System.Net.NetworkInformation.IPStatus Status {get;}

Ako bi želeli da proverimo veći broj računara, podatak o imenu pingovanog računara u finalnom objektu nam je neophodan. Možemo dodati ComputerName NoteProperty koristeći Add-Member komandlet. PassThru parameter je nužan, pošto, po default-u, Add-Member ne generiše nikakav izlaz. Neka je $Computers niz koji sadrži imena računara. Do imena računara i kreiranja niza možemo doći upitom u Active Directory, učitavanjem tekstualne datoteke/CSV datoteke ili direktnim navođenjem članova:

$Computers = 'localhost','10.10.0.4'

 

# prvo inicijalizujemo niz koji će postati naš finalni objekt
$Replies = @()

# obrađujemo svaki računar koji se nalazi u nizu $Computers
$Computers | ForEach-Object {
# prikazujemo poruku o računaru čija se dostupnost trenutno proverava
Write-Host "Proveravamo računar: $_" -foregroundcolor Yellow
# objektu $Ping.Send($_,1000) koji nastaje pingovanjem računara $_
# dodajemo ComputerName osobinu čija je vrednost ime računara $_
$Replies += Add-Member -InputObject $($Ping.Send($_,1000)) -MemberType NoteProperty -Name ComputerName -Value $_ -passthru
}

Proverimo osobine novokreiranog izlaznog objekta $Replies:

$Replies | Get-Member -type *Property

   TypeName: System.Net.NetworkInformation.PingReply

Name          MemberType   Definition
----          ----------   ----------
ComputerName  NoteProperty System.Management.Automation.PSObject ComputerName=localhost
Address       Property     System.Net.IPAddress Address {get;}
Buffer        Property     System.Byte[] Buffer {get;}
Options       Property     System.Net.NetworkInformation.PingOptions Options {get;}
RoundtripTime Property     System.Int64 RoundtripTime {get;}
Status        Property     System.Net.NetworkInformation.IPStatus Status {get;}

PingReply objekt je proširen ComputerName NoteProperty-jem kako smo i želeli.

Sve je ovo divno i krasno dok proveravamo dostupnost računara na osnovu IP adresa i validnih imena, ali kada naletimo na ime računara koje Send metod ne može da razreši, dolazi do greške. Zato nam je potreban Trap blok kako bi "uhvatili" grešku, upisali informaciju o grešci u log datoteku i nastavili sa izvršenjem. Spakujmo sada sve ovo u funkciju Test-OnlineStatus.

function Test-OnlineStatus {
   param (
   [string[]]$ComputerName = $env:computername, # ComputerName parameter je niz; default vrednost je lokalni računar
   [string]$LogFile = 'c:\OnlineStatus.log'
   )

 


   BEGIN {
      $Ping = New-Object System.Net.NetworkInformation.Ping
      # inicijalizujemo niz koji će postati naš finalni objekt
      $Replies = @()
      # $LogFile će sadržavati informaciju o imenima računara koja nisu mogla biti razrešena
      # ako $LogFile već postoji, obriši je
      if (Test-Path $LogFile) {Remove-Item $LogFile}
   }

   PROCESS {
      # da bi prihvatili i vrednosti preko pipeline-a, dodajemo nizu $ComputerName i ime računara koji stiže putem pipeline-a
      if ($_) {$ComputerName += $_}
      $ComputerName | ForEach-Object {
         # ovo je potrebno pošto se scope menja u okviru trap bloka
         $computer = $_
         trap {
            Write-Host "Ime računara $computer nije moglo biti razrešeno." -foregroundcolor Red
            "Ime računara $computer nije moglo biti razrešeno." | Out-File $LogFile -append
            continue
         }

         . {
            Write-Host "Proveravamo računar: $_" -foregroundcolor Yellow
            $Replies += Add-Member -InputObject $($Ping.Send($_,1000)) -MemberType NoteProperty -Name ComputerName -Value $_ -passthru
         }
      }
      # praznimo niz $ComputerName kako bi prihvatio sledeću vrednost preko pipeline-a
      $ComputerName = $null
   }

   END {
      Write-Output $Replies
   }
}

Test-OnlineStatus funkcija ima dva parametra - ComputerName (niz imena računara) i LogFile (putanja do log datotekeu koju se upisuju informacije o imenima računara koja nisu mogla biti razrešena). Funkcija prihvata ulazne vrednosti i preko pipeline-a i kao vrednosti parametara. Čak se mogu istovremeno koristiti. Za kraj evo par primera kako se funkcija koristi:

PS C:\> $computers | Test-OnlineStatus | Select ComputerName,Status,Address | Export-Csv c:\OnlineStatus.csv -noTypeInformation
PS C:\> Test-OnlineStatus $computers -LogFile c:\izvestaj.log | Format-Table ComputerName,Status,Address -AutoSize
PS C:\> $computers | Test-OnlineStatus Server01,Server02 | Format-Table ComputerName,Status
PS C:\> 'Server01','Server02' | Test-OnlineStatus $computers | Format-Table ComputerName,Status
Published Saturday, October 24, 2009 4:59 PM by aleksandar

Leave a Comment

(required) 
(required) 
(optional)
(required) 
Are you a human?