Checking if another computer is turned on or off - c#

Is there anyway to check if a computer is turned on / off using C#?
I have tried using this.
private static bool IsMachineUp(string hostName)
{
bool retVal = false;
try
{
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
// Use the default Ttl value which is 128,
// but change the fragmentation behavior.
options.DontFragment = true;
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 120;
PingReply reply = pingSender.Send(hostName, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
retVal = true;
}
}
catch (Exception ex)
{
retVal = false;
Console.WriteLine(ex.Message);
}
return retVal;
}
But the problem is it always returns true when finding an ip of internal network and always returns false when finding by external network.
Is there any other way?? Just to determine whether a pc is turned on or off.
Or if external network is not available then is there a way to find if the ip of external network is actually used by a computer?

Related

c# use Ping.send or sendAsync always successful even without network

I was struggling with a problem for a long time. I was using unity and I want to ping my server and router. I was using UnityPing class at the beginning and it works fine for the most of devices, but when I testing on Google Pixel(Android 7.1) it always return -1. So I tried to use System.Net.NetworkInformation to ping my server. here is my code:
private void PingToServer()
{
AutoResetEvent waiter = new AutoResetEvent(false);
System.Net.NetworkInformation.Ping pingSender = new System.Net.NetworkInformation.Ping();
pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 10000;
PingOptions options = new PingOptions(64, true);
IPAddress address = IPAddress.Parse("119.81.194.57");
pingSender.SendAsync(address, timeout, buffer, options, waiter);
}
private void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
if (e.Cancelled)
{
Console.WriteLine("Ping canceled.");
((AutoResetEvent)e.UserState).Set();
}
if (e.Error != null)
{
Console.WriteLine("Ping failed:");
Console.WriteLine(e.Error.ToString());
((AutoResetEvent)e.UserState).Set();
}
PingReply reply = e.Reply;
int pingTime = (int)reply.RoundtripTime;
UnityEngine.Debug.Log(reply.RoundtripTime);
((AutoResetEvent)e.UserState).Set();
}
And It always return a RoundripTime which seems like a number make sense, but when I try to ping another ip address which is not available to reach or even turn off the internet it always return a RoundripTime with reply.status equals to IPStatus.Success. Now I'm confused, did I really ping to my remote server or not?
I did chekced some other similar questions, and it doesn't solved the problem. Some answers suggest to use SendPingAsync instead of SendAsync, but that is not possible for unity.
I have button.click event where i have this code ... and it works fine
AutoResetEvent waiter = new AutoResetEvent(false);
Ping pingSender = new Ping();
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 100;
PingOptions options = new PingOptions(64, true);
IPAddress address = IPAddress.Parse("YourTestIP");
PingReply reply = pingSender.Send(address, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
MessageBox.Show(reply.Address.ToString());
}

.NET Ping() giving false timeouts?

I have a script that is looping through and sending a ping to a host every second. The purpose of which is to test wireless performance on my home network. The issue is, I seem to be getting timeouts from my script, while a standard "ping -t" on either client (pingER and pingEE) have no such timeouts. In fact, not once in the last 30 minutes has either timed out, while my script has received timeout replies every few minutes.
My essential script is below. In all cases, when it does happen, my reply is TimedOut with a response time of 0ms. Is my script causing false timeouts? Thanks.
EDIT: updated code to reflect newest changes, still having same behavior.
while (true)
{
System.Threading.Thread.Sleep(delay);
var builder = new StringBuilder();
hosts.ForEach(h =>
{
var buffer = new byte[32];
var reply = ping.Send(h, 4000, buffer, new PingOptions(600, true));
var error = reply.Status != IPStatus.Success || reply.RoundtripTime > maxRoundTrip;
if (verbose || error)
{
builder.AppendFormat("{0}: {1} ({2}ms)", h, reply.Status, reply.RoundtripTime);
builder.Append(Environment.NewLine);
if (error)
{
WriteLog(h, reply);
SendEmail(h, reply);
}
}
});
Console.WriteLine(DateTime.Now);
Console.WriteLine(builder.ToString());
}
If your ping -t timeout value is less than 1000 or the value of maxRoundTrip is less than 1000 then you are checking against different timeouts in your two different pings (.NET Ping.Send vs. ping -t). The default Windows ping timeout is 4000 ms. http://technet.microsoft.com/en-us/library/bb490968.aspx
Also in your .NET code, you are sending the max buffer size of 65500 bytes. The default Windows ping command sends only 32 bytes of data.
So the difference between either the timeout or buffer size is likely what is causing the variance.
More info about the .NET Ping.Send method: http://msdn.microsoft.com/en-us/library/ms144956(v=vs.110).aspx
I might have figured it out. I was using the netbios name for the machine in question. I'm guessing that each time it did a ping, it was factoring in the IP lookup in the round trip and was timing out. When I used just the IP, it worked just fine and hasn't timed out.
Thanks for the input.
In my case, the byte array size is the main reason (I programmed a similar ping application)
When
var buffer = new byte[65500];
2014/3/30 11:29:26
8.8.8.8: TimedOut (0ms)
changed to
var buffer = new byte[32];
2014/3/30 11:32:50
8.8.8.8: Success (8ms)
I deduced that the ping buffer if too high then the ICMP echo message might be fragmented become more than one packets then only send out,therefore it cannot completed the ping within the timeout period. (But seem like OP mentioned in answer it is hostname resolve problem, then may be my deduction is wrong)
my sample code
using System;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;
namespace ConsoleApplication6
{
class Program
{
static void Main(string[] args)
{
int delay = 1000;
Ping ping = new Ping();
//OP using something else?
System.Net.IPAddress h = IPAddress.Parse("8.8.8.8");
while (true)
{
System.Threading.Thread.Sleep(delay);
var builder = new StringBuilder();
//change buffer size change the result...
//var buffer = new byte[65500];
var buffer = new byte[32];
var reply = ping.Send(h, 1000, buffer, new PingOptions(600, false));
var error = reply.Status != IPStatus.Success || reply.RoundtripTime > 3000;
if (error)
{
builder.AppendFormat("{0}: {1} ({2}ms)", h, reply.Status, reply.RoundtripTime);
builder.Append(Environment.NewLine);
}
else
{
builder.AppendFormat("{0}: {1} ({2}ms)", h, reply.Status, reply.RoundtripTime);
}
Console.WriteLine(DateTime.Now);
Console.WriteLine(builder.ToString());
}
}
}
}
var reply = ping.Send(h, 1000, buffer, new PingOptions(600, false));
1000 is timeout (ms) for the ping reply...
I'm seeing the same behavior as the OP. My ping.Send() is only sending a buffer of byte[30] and always uses the explicit IP so no DNS/NetBIOS involved. I've tried varying timeout values but consistently see regular timeout returns from Send() vs zero timeouts when using ping from the command-line.
public PingCheck(string address, int timeout = 250, int pingNbr = 1)
{
var rtn = IPAddress.TryParse(address, out IPAddress addr);
if (rtn)
{
IpAddress = addr;
var dataSend = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
var pinger = new Ping();
var pingerOptions = new PingOptions();
pingerOptions.DontFragment = true;
var buffer = Encoding.ASCII.GetBytes(dataSend);
var statusList = new List<IPStatus>();
var lossList = new List<bool>();
var tripList = new List<long>();
for (int i=0; i<pingNbr; i++)
{
var pingerReply = pinger.Send(addr, timeout, buffer, pingerOptions);
var bufback = pingerReply.Buffer;
var dataBack = Encoding.ASCII.GetString(bufback);
var status = pingerReply.Status;
var loss = (dataSend != dataBack);
var msecs = pingerReply.RoundtripTime;
statusList.Add(status);
lossList.Add(loss);
tripList.Add(msecs);
}
// TODO: Add statistics check
}
else
throw new PingException("No IP Address");
}

C# checking Internet connection [duplicate]

This question already has answers here:
What is the best way to check for Internet connectivity using .NET?
(27 answers)
Closed 8 years ago.
Can you please tell me if there is a way to check if there is a internet connection in my computer when my C# program is running. For a simple example, if internet is working, I would output a message box saying Internet is available. else I would output a message saying, Internet is unavailable.
Without using the library function to see if network is available (since this doesn't check internet connectivity)
System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable()
Or without opening a webpage and seeing if it's return data
using (WebClient client = new WebClient())
htmlCode = client.DownloadString("http://google.com");
Because both of these above methods don't suit my needs.
a little shorter version:
public static bool CheckForInternetConnection()
{
try
{
using (var client = new WebClient())
using (var stream = client.OpenRead("http://www.google.com"))
{
return true;
}
}
catch
{
return false;
}
}
Another option is:
Ping myPing = new Ping();
String host = "google.com";
byte[] buffer = new byte[32];
int timeout = 1000;
PingOptions pingOptions = new PingOptions();
PingReply reply = myPing.Send(host, timeout, buffer, pingOptions);
if (reply.Status == IPStatus.Success) {
// presumably online
}
You can find a broader discussion here
Consider the following code snippet...
Ping myPing = new Ping();
String host = "google.com";
byte[] buffer = new byte[32];
int timeout = 1000;
PingOptions pingOptions = new PingOptions();
PingReply reply = myPing.Send(host, timeout, buffer, pingOptions);
if (reply.Status == IPStatus.Success)
{
// presumably online
}
Good Luck!
just wrote async functions to do that:
private void myPingCompletedCallback(object sender, PingCompletedEventArgs e)
{
if (e.Cancelled)
return;
if (e.Error != null)
return;
if (e.Reply.Status == IPStatus.Success)
{
//ok connected to internet, do something...
}
}
private void checkInternet()
{
Ping myPing = new Ping();
myPing.PingCompleted += new PingCompletedEventHandler(myPingCompletedCallback);
try
{
myPing.SendAsync("google.com", 3000 /*3 secs timeout*/, new byte[32], new PingOptions(64, true));
}
catch
{
}
}
My NetworkMonitor class now provides this (based on other responses here):
public bool IsInternetAvailable
{
get { return IsNetworkAvailable && _CanPingGoogle(); }
}
private static bool _CanPingGoogle()
{
const int timeout = 1000;
const string host = "google.com";
var ping = new Ping();
var buffer = new byte[32];
var pingOptions = new PingOptions();
try {
var reply = ping.Send(host, timeout, buffer, pingOptions);
return (reply != null && reply.Status == IPStatus.Success);
}
catch (Exception) {
return false;
}
}
This is my approach;
Check that a network connection is available, if it isn't then we wont be able to connect to another host.
Check if we can connect to some major hosts. Use a fallback just in case that site isn't available.
public static bool ConnectToInternet(int timeout_per_host_millis = 1000, string[] hosts_to_ping = null)
{
bool network_available = System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
if (network_available)
{
string[] hosts = hosts_to_ping ?? new string[] { "www.google.com", "www.facebook.com" };
Ping p = new Ping();
foreach (string host in hosts)
{
try
{
PingReply r = p.Send(host, timeout_per_host_millis);
if (r.Status == IPStatus.Success)
return true;
}
catch { }
}
}
return false;
}
Notes:
Don't use too many hosts when reaching out, weigh up the cost in time of making all the pings against the diminishing likelihood of success.
If we send the ping to a certain that host we intend to connect to later (eg a http request) a returned ping doesn't mean we are connected to that particular host. Consider what would happen if the host is blocked. eg Facebook is blocked in Iran,China,... Does that ISP return the ping?
A DNS request wont be sufficient as it may be cached
public static bool HasConnection()
{
try
{
System.Net.IPHostEntry i = System.Net.Dns.GetHostEntry("www.google.com");
return true;
}
catch
{
return false;
}
}

How to know if MS Windows has alive red or internet connection? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
check whether internet connection is available with C#
I just want to know which methods we have to use to detect programmatically (C#) if MS Windows has alive Internet/red connection or doesn't.
Is it possible to do?
Thank you!
For example: if I put down WIFI how I can know that there is any connection?
Take a look at the Ping class
Ping pingSender = new Ping ();
PingOptions options = new PingOptions ();
// Use the default Ttl value which is 128,
// but change the fragmentation behavior.
options.DontFragment = true;
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes (data);
int timeout = 120;
PingReply reply = pingSender.Send ("www.google.com", timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
Console.WriteLine ("Address: {0}", reply.Address.ToString ());
Console.WriteLine ("RoundTrip time: {0}", reply.RoundtripTime);
Console.WriteLine ("Time to live: {0}", reply.Options.Ttl);
Console.WriteLine ("Don't fragment: {0}", reply.Options.DontFragment);
Console.WriteLine ("Buffer size: {0}", reply.Buffer.Length);
}
I use the following method to check for connectivity:
public bool CheckForInternetConnection()
{
try
{
using (var client = new WebClient())
using (var stream = client.OpenRead("http://www.google.com"))
{
Console.WriteLine("You Have connectity!");
return true;
}
}
catch
{
Console.WriteLine("No internet connection found.");
return false;
}
}
The method attempts to load Google's URL and returns true if it loads, false if it does not.

TraceRoute and Ping in C#

Does anyone have C# code handy for doing a ping and traceroute to a target computer? I am looking for a pure code solution, not what I'm doing now, which is invoking the ping.exe and tracert.exe program and parsing the output. I would like something more robust.
Given that I had to write a TraceRoute class today I figured I might as well share the source code.
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Text;
using System.Net;
namespace Answer
{
public class TraceRoute
{
private const string Data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
public static IEnumerable<IPAddress> GetTraceRoute(string hostNameOrAddress)
{
return GetTraceRoute(hostNameOrAddress, 1);
}
private static IEnumerable<IPAddress> GetTraceRoute(string hostNameOrAddress, int ttl)
{
Ping pinger = new Ping();
PingOptions pingerOptions = new PingOptions(ttl, true);
int timeout = 10000;
byte[] buffer = Encoding.ASCII.GetBytes(Data);
PingReply reply = default(PingReply);
reply = pinger.Send(hostNameOrAddress, timeout, buffer, pingerOptions);
List<IPAddress> result = new List<IPAddress>();
if (reply.Status == IPStatus.Success)
{
result.Add(reply.Address);
}
else if (reply.Status == IPStatus.TtlExpired || reply.Status == IPStatus.TimedOut)
{
//add the currently returned address if an address was found with this TTL
if (reply.Status == IPStatus.TtlExpired) result.Add(reply.Address);
//recurse to get the next address...
IEnumerable<IPAddress> tempResult = default(IEnumerable<IPAddress>);
tempResult = GetTraceRoute(hostNameOrAddress, ttl + 1);
result.AddRange(tempResult);
}
else
{
//failure
}
return result;
}
}
}
And a VB version for anyone that wants/needs it
Public Class TraceRoute
Private Const Data As String = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Public Shared Function GetTraceRoute(ByVal hostNameOrAddress As String) As IEnumerable(Of IPAddress)
Return GetTraceRoute(hostNameOrAddress, 1)
End Function
Private Shared Function GetTraceRoute(ByVal hostNameOrAddress As String, ByVal ttl As Integer) As IEnumerable(Of IPAddress)
Dim pinger As Ping = New Ping
Dim pingerOptions As PingOptions = New PingOptions(ttl, True)
Dim timeout As Integer = 10000
Dim buffer() As Byte = Encoding.ASCII.GetBytes(Data)
Dim reply As PingReply
reply = pinger.Send(hostNameOrAddress, timeout, buffer, pingerOptions)
Dim result As List(Of IPAddress) = New List(Of IPAddress)
If reply.Status = IPStatus.Success Then
result.Add(reply.Address)
ElseIf reply.Status = IPStatus.TtlExpired Then
'add the currently returned address
result.Add(reply.Address)
'recurse to get the next address...
Dim tempResult As IEnumerable(Of IPAddress)
tempResult = GetTraceRoute(hostNameOrAddress, ttl + 1)
result.AddRange(tempResult)
Else
'failure
End If
Return result
End Function
End Class
This implementation is simple, lazy (properly enumerable) and it will not go on searching forever (maxTTL) like some of the other answers.
public static IEnumerable<IPAddress> GetTraceRoute(string hostname)
{
// following are similar to the defaults in the "traceroute" unix command.
const int timeout = 10000;
const int maxTTL = 30;
const int bufferSize = 32;
byte[] buffer = new byte[bufferSize];
new Random().NextBytes(buffer);
using (var pinger = new Ping())
{
for (int ttl = 1; ttl <= maxTTL; ttl++)
{
PingOptions options = new PingOptions(ttl, true);
PingReply reply = pinger.Send(hostname, timeout, buffer, options);
// we've found a route at this ttl
if (reply.Status == IPStatus.Success || reply.Status == IPStatus.TtlExpired)
yield return reply.Address;
// if we reach a status other than expired or timed out, we're done searching or there has been an error
if (reply.Status != IPStatus.TtlExpired && reply.Status != IPStatus.TimedOut)
break;
}
}
}
Although the Base Class Library includes Ping, the BCL does not include any tracert functionality.
However, a quick search reveals two open-source attempts, the first in C# the second in C++:
http://www.codeproject.com/KB/IP/tracert.aspx
http://www.codeguru.com/Cpp/I-N/network/basicnetworkoperations/article.php/c5457/
For the ping part, take a look at the Ping class on MSDN.
This is the most efficient way I could think of.
Please vote it up if you like it so others can benefit.
using System;
using System.Collections.Generic;
using System.Net.NetworkInformation;
namespace NetRouteAnalysis
{
class Program
{
static void Main(string[] args)
{
var route = TraceRoute.GetTraceRoute("8.8.8.8")
foreach (var step in route)
{
Console.WriteLine($"{step.Address,-20} {step.Status,-20} \t{step.RoundtripTime} ms");
}
}
}
public static class TraceRoute
{
public static IEnumerable<PingReply> GetTraceRoute(string hostnameOrIp)
{
// Initial variables
var limit = 1000;
var buffer = new byte[32];
var pingOpts = new PingOptions(1, true);
var ping = new Ping();
// Result holder.
PingReply result = null;
do
{
result = ping.Send(hostnameOrIp, 4000, buffer, pingOpts);
pingOpts = new PingOptions(pingOpts.Ttl + 1, pingOpts.DontFragment);
if (result.Status != IPStatus.TimedOut)
{
yield return result;
}
}
while (result.Status != IPStatus.Success && pingOpts.Ttl < limit);
}
}
}
Ping: We can use the Ping class built into the .NET Framework.
Instantiate a Ping and subscribe to the PingCompleted event:
Ping pingSender = new Ping();
pingSender.PingCompleted += PingCompletedCallback;
Add code to configure and action the ping, e.g.:
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
string who = "www.google.com";
AutoResetEvent waiter = new AutoResetEvent(false);
int timeout = 12000;
PingOptions options = new PingOptions(64, true);
pingSender.SendAsync(who, timeout, buffer, options, waiter);
Add a PingCompletedEventHandler:
public static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
... Do stuff here
}
Code-dump of a full working example, based on MSDN's example:
public static void Main(string[] args)
{
string who = "www.google.com";
AutoResetEvent waiter = new AutoResetEvent(false);
Ping pingSender = new Ping();
// When the PingCompleted event is raised,
// the PingCompletedCallback method is called.
pingSender.PingCompleted += PingCompletedCallback;
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
// Wait 12 seconds for a reply.
int timeout = 12000;
// Set options for transmission:
// The data can go through 64 gateways or routers
// before it is destroyed, and the data packet
// cannot be fragmented.
PingOptions options = new PingOptions(64, true);
Console.WriteLine("Time to live: {0}", options.Ttl);
Console.WriteLine("Don't fragment: {0}", options.DontFragment);
// Send the ping asynchronously.
// Use the waiter as the user token.
// When the callback completes, it can wake up this thread.
pingSender.SendAsync(who, timeout, buffer, options, waiter);
// Prevent this example application from ending.
// A real application should do something useful
// when possible.
waiter.WaitOne();
Console.WriteLine("Ping example completed.");
}
public static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
// If the operation was canceled, display a message to the user.
if (e.Cancelled)
{
Console.WriteLine("Ping canceled.");
// Let the main thread resume.
// UserToken is the AutoResetEvent object that the main thread
// is waiting for.
((AutoResetEvent)e.UserState).Set();
}
// If an error occurred, display the exception to the user.
if (e.Error != null)
{
Console.WriteLine("Ping failed:");
Console.WriteLine(e.Error.ToString());
// Let the main thread resume.
((AutoResetEvent)e.UserState).Set();
}
Console.WriteLine($"Roundtrip Time: {e.Reply.RoundtripTime}");
// Let the main thread resume.
((AutoResetEvent)e.UserState).Set();
}
As am improvement to Scotts code answer above, I found that his solution doesn't work if the route tapers off into nothing before reaching the destination - it never returns. A better solution with at least a partial route could be this (which I've tested and it works well). You can change the '20' in the for loop to something bigger or smaller or try to detect if it's taking too long if you want to control the number of iterations some other way. Full credit to Scott for the original code - thanks.
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Text;
using System.Net;
...
public static void TraceRoute(string hostNameOrAddress)
{
for (int i = 1; i < 20; i++)
{
IPAddress ip = GetTraceRoute(hostNameOrAddress, i);
if(ip == null)
{
break;
}
Console.WriteLine(ip.ToString());
}
}
private static IPAddress GetTraceRoute(string hostNameOrAddress, int ttl)
{
const string Data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
Ping pinger = new Ping();
PingOptions pingerOptions = new PingOptions(ttl, true);
int timeout = 10000;
byte[] buffer = Encoding.ASCII.GetBytes(Data);
PingReply reply = default(PingReply);
reply = pinger.Send(hostNameOrAddress, timeout, buffer, pingerOptions);
List<IPAddress> result = new List<IPAddress>();
if (reply.Status == IPStatus.Success || reply.Status == IPStatus.TtlExpired)
{
return reply.Address;
}
else
{
return null;
}
}

Categories

Resources