Welcome to Powergui.org - an open source community for Windows Powershell

PowerGUI.org PowerGUI.org and blogs

Forums » Active Directory and PowerShell

Thread: IF condition check pingable machines

This question is answered.


Permlink Replies: 14 - Pages: 1 - Last Post: Nov 18, 2009 10:09 AM by: seaJhawk
fabrigatti

Posts: 33
Registered: 10/1/09
IF condition check pingable machines
Posted: Nov 10, 2009 10:14 AM
 
  Click to reply to this thread Reply


Hello,

I am working on this piece of script (kindly provided by Mr. Levy):

get-content machines.txt | foreach{

 $os = gwmi win32_operatingsystem -computer $_
 $uptime = (Get-Date) - $os.ConvertToDateTime($os.LastBootUpTime)
 
 if($uptime.days -ge XX)
 {
  #Forced Shutdown
  $os.Win32Shutdown(5)
 
  #Forced Reboot
  # $os.Win32Shutdown(6)
  
  }
}

How can I add an IF condition which checks if the ping on each PC is successfull or not (i.e. the PC is up and running)?
I'd prefer to launch the shutdown command only in case the PC is actually reachable over the LAN and I would like to log (append) this kind of info on a txt file.

Thanks a lot!
Fabrizio




seaJhawk


Posts: 414
Registered: 12/15/08
Re: IF condition check pingable machines
Posted: Nov 10, 2009 11:13 AM   in response to: fabrigatti
 
  Click to reply to this thread Reply

Hi Fabrizio,

If the machines are not seperated by a firewall you can usually just use a simple ping. I wrote a function that allows you to specify a timeout and provides an error message rather than just an error status code:

# ping-host function

function ping-host ($server, [int] $timeout = 7000){

$ping = gwmi Win32_PingStatus -filter "Address='$($server)' and timeout=$($timeout)"

$ping = $ping | Add-Member -passThru -force -memberType NoteProperty -name "StatusText" -value ""

switch ($ping.statusCode){

0 {$ping.StatusText = "Success"}11001 {

$ping.StatusText = "Buffer Too Small"}

11002 {$ping.StatusText = "Destination Net Unreachable"}11003 {

$ping.StatusText = "Destination Host Unreachable"}

11004 {$ping.StatusText = "Destination Protocol Unreachable"}11005 {

$ping.StatusText = "Destination Port Unreachable"}

11006 {$ping.StatusText = "No Resources"}11007 {

$ping.StatusText = "Bad Option"}

11008 {$ping.StatusText = "Hardware Error"}11009 {

$ping.StatusText = "Packet Too Big"}

11010 {$ping.StatusText = "Request Timed Out"}11011 {

$ping.StatusText = "Bad Request"}

11012 {$ping.StatusText = "Bad Route"}11013 {

$ping.StatusText = "TimeToLive Expired Transit"}

11014 {$ping.StatusText = "TimeToLive Expired Reassembly"}11015 {

$ping.StatusText = "Parameter Problem"}

11016 {$ping.StatusText = "Source Quench"}11017 {

$ping.StatusText = "Option Too Big"}

11018 {$ping.StatusText = "Bad Destination"}11032 {

$ping.StatusText = "Negotiating IPSEC"}

11050 {$ping.StatusText = "General Failure"}

default {$ping.StatusText = "Unknown"}

}

$ping

}


You can use it like this:

get-content machines.txt | foreach{

 If (ping-host $_){
 $os = gwmi win32_operatingsystem -computer $_
 $uptime = (Get-Date) - $os.ConvertToDateTime($os.LastBootUpTime)
 
 if($uptime.days -ge XX)
 {
  #Forced Shutdown
  $os.Win32Shutdown(5)
 
  #Forced Reboot
  # $os.Win32Shutdown(6)
  
  }
  }
Else {
 # Log error to file here
}
}




fabrigatti

Posts: 33
Registered: 10/1/09
Re: IF condition check pingable machines
Posted: Nov 11, 2009 8:32 AM   in response to: seaJhawk
 
  Click to reply to this thread Reply


Hi,

I used the function part as it is, but I changed the remaing part of the script like this:

get-content ShutdownMachines.txt | foreach{

If (ping-host $_){

$os = gwmi win32_operatingsystem -computer $_

$uptime = (Get-Date) - $os.ConvertToDateTime($os.LastBootUpTime)
if($uptime.days -ge 1)

{

#Forced Shutdown

$os.Win32Shutdown(5)

#Forced Reboot

# $os.Win32Shutdown(6)


}

}

Else {

# Log error to file here


Out-File LogShutdownNotPingable.txt -Append


}

}

I should get a file with a list of not-reachable machines, right?

None of the running PCs have been shutdown and I got no log files either.
These are the error messages I received:

The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)

At :line:54 char:11

+ $os = gwmi <<<< win32_operatingsystem -computer $_

You cannot call a method on a null-valued expression.

At :line:55 char:45

+ $uptime = (Get-Date) - $os.ConvertToDateTime <<<< ($os.LastBootUpTime)

I cannot understand that "RPC server is unavailable". The connected PC should be perfectly reachable. I can browse it from a different PC.




seaJhawk


Posts: 414
Registered: 12/15/08
Re: IF condition check pingable machines
Posted: Nov 11, 2009 1:32 PM   in response to: fabrigatti
 
  Click to reply to this thread Reply

Is the remote computer sitting on the other side of a firewall? Can you ping RPC ports?

Try this:

function Ping-Port([string]$server, [int]$port) {
 $tcpClient = New-Object System.Net.Sockets.TcpClient
 trap { # Generic trap object, we don't care what the error is, the check still fails.
  $False
  continue;
 }
 $tcpClient.Connect($server,$port)
 if ($tcpClient.Connected) {$True}          
}


ping-port RemoteComputer 135
ping-port RemoteComputer 445




fabrigatti

Posts: 33
Registered: 10/1/09
Re: IF condition check pingable machines
Posted: Nov 12, 2009 2:45 AM   in response to: seaJhawk
 
  Click to reply to this thread Reply


The PCs are not behind a firewall. I can ping them from a DOS prompt.

The script above works fine. I get 2 "True" which means that the client is reachable on both ports.
In spite of this the first script you attached still ends up with the error I sent.


seaJhawk


Posts: 414
Registered: 12/15/08
Re: IF condition check pingable machines
Posted: Nov 12, 2009 8:12 AM   in response to: fabrigatti
 
  Click to reply to this thread Reply

In that case I'd say you have an issue with WMI on the remote computer.

Can you run the following on the remote computer:

gwmi win32_operatingsystem

If not then make sure that the WMI service is running on the computer.

If the command does work then
* make sure that the Local firewall is not blocking the connection
* make sure that the Remote Procedure Call (RPC) service is running


If these are all ok then try running gwmi win32_operatingsystem -computer 192.168.1.2

where the IP address is the IP of the remote computer.

-Chris


fabrigatti

Posts: 33
Registered: 10/1/09
Re: IF condition check pingable machines
Posted: Nov 12, 2009 10:14 AM   in response to: seaJhawk
 
  Click to reply to this thread Reply


Windows Firewall has been disabled and the PC is not running different local firewalls.
RPC is also running.

I ran "gwmi win32_operatingsystem -ComputerName Ipaddress" and I actually got all details of the remote OS.

Then I changed the last part of the script like this (I just changed the -computer parameter into -ComputerName):

get-content ShutdownMachines.txt | foreach{

If (ping-host $_){

$os = gwmi win32_operatingsystem -ComputerName $_

$uptime = (Get-Date) - $os.ConvertToDateTime($os.LastBootUpTime)
if($uptime.days -ge 01)

{

#Forced Shutdown

$os.Win32Shutdown(5)

#Forced Reboot

# $os.Win32Shutdown(6)


}

}

Else {

# Log error to file here


Out-File LogShutdownNotPingable.txt -Append


}

}

...But I get the same error I mentioned above.
Why does the variable $os seems to be empty?

The out-File command may also be wrong. On the test file "LogShutdownNotPingable.txt" I cannot see any entries, but the file "ShutdownMachines.txtcontains the name of an online machine (to be shutdown) and the name of an offline machine (which should appear in the log file).




seaJhawk


Posts: 414
Registered: 12/15/08
Re: IF condition check pingable machines
Posted: Nov 12, 2009 10:24 AM   in response to: fabrigatti
 
  Click to reply to this thread Reply

ok - let's take this one step at a time.

So you can do this:

gwmi win32_operatingsystem -computername ipaddress

But you can't do this:

gwmi win32_operatingsystem -computername computername

Correct?

That means you've got a name resolution issue. Do you have "Enable NetBIOS over TCP/IP" on the WINS tab of your network connection IPv4 settings?


fabrigatti

Posts: 33
Registered: 10/1/09
Re: IF condition check pingable machines
Posted: Nov 12, 2009 12:47 PM   in response to: seaJhawk
 
  Click to reply to this thread Reply

Both commands works. The one with the IP address but also the one with the Computername.
It's strange that if inserted in the script they cannot set a value to the variable $os..


fabrigatti

Posts: 33
Registered: 10/1/09
Re: IF condition check pingable machines
Posted: Nov 13, 2009 7:56 AM   in response to: seaJhawk
 
  Click to reply to this thread Reply


Dear seaJhawk,

I think that the problem is on the following lines:

If (ping-host $_){

$os = gwmi win32_operatingsystem -ComputerName $_

$uptime = (Get-Date) - $os.ConvertToDateTime($os.LastBootUpTime)

if($uptime.days -ge 1)

{

#Forced Shutdown

$os.Win32Shutdown(5)

}

}


If I explicitly write the computername (as you can see below) the PC is powered off correctly!
 

If (ping-host $_){

#$os = gwmi win32_operatingsystem -ComputerName $_

$os = gwmi win32_operatingsystem -ComputerName usrl000111

$uptime = (Get-Date) - $os.ConvertToDateTime($os.LastBootUpTime)

...


What's wrong with the "ping-host" function then?




seaJhawk


Posts: 414
Registered: 12/15/08
Re: IF condition check pingable machines
Posted: Nov 17, 2009 11:49 AM   in response to: fabrigatti
 
  Click to reply to this thread Reply

Do this to find out what $_ contains after the ping-host:

If (ping-host $_){

$_

}




fabrigatti

Posts: 33
Registered: 10/1/09
Re: IF condition check pingable machines
Posted: Nov 18, 2009 3:36 AM   in response to: seaJhawk
 
  Click to reply to this thread Reply


Including $_ into the IF I have been using actually shows the name of the machines which is going to be shut down.
The script seems to work. I think there were some problems with WINS and/or DNS resolution.
What a shame...

However, for not pingable machines, the ELSE part is not executed.
Apart from the fact that probably the Out-File command I inserted is wrong, I put a breakpoint on it and it's actually never executed.
Whenever I get the error "The WriteObject and WriteError methods cannot be called after the pipeline has been closed. Please contact Microsoft Support Services.

At :line:71 char:11

+ $os = gwmi <<<< win32_operatingsystem -ComputerName $_" or RPC not available the script execution fails and anything is appended to the log file.




seaJhawk


Posts: 414
Registered: 12/15/08
Re: IF condition check pingable machines
Posted: Nov 18, 2009 5:21 AM   in response to: fabrigatti
 
  Click to reply to this thread Reply

ok, so I really should have taken my anti-ID10T medicine.

I specifically added a property to the object returned by ping-host so I could see what was going on, but then I neglected to check it.

Try this:

If ((ping-host $_).statusText -eq "success"){

Write-host "Success: $_"

}

Else{

Write-Host "Failure: $_"

}

}





fabrigatti

Posts: 33
Registered: 10/1/09
Re: IF condition check pingable machines
Posted: Nov 18, 2009 9:53 AM   in response to: seaJhawk
 
  Click to reply to this thread Reply

The commands above work fine!
I get "Success: computername" in the console is the computer is pingable and "Failure: computername" if it's not.

Last step: I need to export these details into an incremental (i.e. appending) log file.
Shouldn't this command work?

Write-host "Success: $_" | Out-File "Pingable.txt" -Append




seaJhawk


Posts: 414
Registered: 12/15/08
Re: IF condition check pingable machines
Posted: Nov 18, 2009 10:09 AM   in response to: fabrigatti
Answered
  Click to reply to this thread Reply

Whew!

All you need to do to write to the log file is drop Write-Host.

-Chris




Legend
MVP: 2501 + pts
Guru: 2001 - 2500 pts
Expert: 751 - 2000 pts
Enthusiast: 31 - 750 pts
Novice: 0 - 30 pts
Moderators
Helpful answer (5 pts)
Answered (10 pts)

Point your RSS reader here for a feed of the latest messages in all forums