October 2009 - Posts

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

PowerShell i Sysinternals alati - dobitna kombinacija

Verujem da ne postoji administrator Windows sistema koji u svom radu ne koristi neki alat iz moćne Windows Sysinternals kolekcije. Pre nešto više od godinu dana zaživeo je i Sysinternals Live, servis koji omogućava da pokrenete Sysinternals alate direktno sa web linka, bez potrebe da ga preuzmete na vaš računar. Sve što treba da uradite je da unesete putanju do alata, bilo u Windows Explorer/Internet Explorer ili command prompt kao http://live.sysinternals.com/<toolname> ili \\live.sysinternals.com\tools\<toolname>. Posebno je interesantan drugi link koji Sysinternals Live nudi kao file share. Ako koristimo PowerShell možemo:

1. pokrenuti alat direktno

PS C:\> \\live.sysinternals.com\tools\autoruns.exe

2. kreirati novi PSDrive (shvatite to kao mapirani deljeni folder, ali vidljiv samo u PowerShell sesiji)

PS C:\> New-PSDrive -Name S -PSProvider filesystem -Root \\live.sysinternals.com\tools
PS C:\> cd s:
PS S:\> .\autoruns.exe

3. ako ipak želite da Sysinternals alate imate lokalno na svom disku, preporučujem Get-Sysinternals funkciju koju je napisao Shay Levy, PowerShell MVP kako bi uvek imao najnovije verzije na svom računaru. Za one koji su već prešli na PowerShell V2, preuzimanje svih alata je znatno jednostavnije korišćenjem Start-BitsTransfer komandleta koji za prenos datoteka koristi isti protokol kao i Windows Update sistem.

# prvo učitamo BitsTransfer modul
PS C:\> Import-Module BitsTransfer
# i zatim preuzmemo sve alate u lokalni folder
PS> Start-BitsTransfer -Source \\live.sysinternals.com\tools\*.* -Destination c:\sysint\

Komandu nisam "opteretio" dodatnim parametrima, pošto količina podataka koju treba preneti nije velika (~30MB), ali bi za veći prenos bilo poželjno pokrenuti asinhrono preuzimanje (kako bi odmah oslobodili prompt za unos novih komandi) i definisati prioritet (recimo, Normal: Transfers the job in the background with a normal priority. Background transfers use the idle network bandwidth of the client computer to transfer files.) O dodatnim parametrima Start-BitsTransfer komandleta uskoro će biti nešto više reči.

PowerShell timu potrebna pomoć

Marco Shaw, PowerShell MVP i jedan od "direktora" PowerShellCommunity.org me zamolio da pronađem PowerShell početnika kome je srpski maternji jezik, ali bi želeo da pomogne recenzijom PowerShell dokumentacije na engleskom jeziku. Zvuči neobično, ali to je ono što trenutno treba PowerShell timu. Više detalja možete pročitati na Marcovom blogu http://marcoshaw.blogspot.com/2009/09/call-to-action-please-read-if-you-want.html

Ako ste sami zainteresovani ili znate nekoga ko bi mogao biti, javite se na adresu doc_reviews@powershellcommunity.org

 

Posted by aleksandar with no comments