Ping Multiple IP Addresses and Show Green Completion - c#

I am trying to ping multiple IP Addresses and if those multiple ip addresses ping successfully I want it to change the label color to green. If 1 out of 2 ip addresses that it is pinging fails then I want to show the label as a red color. How do I do this?
This is what I've tried but I get the error Expected catch or finally....
Ping Sender = new Ping();
// A buffer of 32 bytes of data to be transmitted.
String Data = "[012345678901234567890123456789]";
const int Timeout = 120;
bool Started = false;
String Hostname1 = "www.google.com";
String Hostname2 = "www.432446236236.com";
private void Ping()
{
PingReply Reply;
byte[] Buffer = Encoding.ASCII.GetBytes(Data);
try { Reply = Sender.Send(Hostname1, Timeout, Buffer); }
try { Reply = Sender.Send(Hostname2, Timeout, Buffer);}
catch (Exception ex)
{
label1.ForeColor = System.Drawing.Color.Red;
return;
}
if (Reply.Status == IPStatus.Success)
{
label1.ForeColor = System.Drawing.Color.Green;
return;
}
label1.ForeColor = System.Drawing.Color.Red;
}
Thank you.

First of all, to answer your question about the error: the reason you're getting that error is that you don't have a catch{} block after your first try{}.
I would do a couple of things:
Use camel case for private variable names
Put the hosts into a list, in case you want to add or remove some later
Use a variable to track your success
Fail quickly: Stop pinging as soon as one fails (no need to waste time on pinging any others)
code:
public static void PingTest()
{
const int timeout = 120;
const string data = "[012345678901234567890123456789]";
var buffer = Encoding.ASCII.GetBytes(data);
PingReply reply;
var success = true; // Start out optimistic!
var sender = new Ping();
// Add as many hosts as you want to ping to this list
var hosts = new List<string> {"www.google.com", "www.432446236236.com"};
// Ping each host and set the success to false if any fail or there's an exception
foreach (var host in hosts)
{
try
{
reply = sender.Send(host, timeout, buffer);
if (reply == null || reply.Status != IPStatus.Success)
{
// We failed on this attempt - no need to try any others
success = false;
break;
}
}
catch
{
success = false;
}
}
if (success)
{
label1.ForeColor = System.Drawing.Color.Green;
}
else
{
label1.ForeColor = System.Drawing.Color.Red;
}
}

Related

Connection Reset by Peer C#

So I have windows task scheduler that runs my executable every x minutes.
The executable does the following:
See if any new messages need to sent to the server using sockets.
If there are new messages then make a connection to the server
and send each message.
If there are no new messages then exit the
executable.
Problem:
My executable does not exit and keeps running. So the when windows task scheduler runs again it can't execute because an instance of the executable is still running.
The server where I sent the message told me in the error log they see this:
11-12-19 15:34:09 TCP/IP receive failed; errno 73 - Connection reset by peer.
My code:
namespace TransportMessage
{
class Program
{
static void Main(string[] args)
{
var systemUserId = 1
try
{
using (var dbContext = new DBContext())
{
var unsentRecords = dbContext.Records.Where(x => x.status == "QUEUED").ToList();
if (unsentRecords != null && unsentRecords.Count > 0)
{
var portNumber = 45454;
var dnsName = "xxxx.xxx.xxx.xxx";
IPAddress[] ipAddresses = Dns.GetHostAddresses(dnsName);
Socket soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ipAdd = System.Net.IPAddress.Parse(ipAddresses[0].ToString());
IPEndPoint remoteEP = new IPEndPoint(ipAdd, portNumber);
soc.Connect(remoteEP);
foreach (var rec in unsentRecords)
{
try
{
byte[] byData = System.Text.Encoding.ASCII.GetBytes(rec.message_text);
var numberOfBytesSent = soc.Send(byData);
byte[] buffer = new byte[8000];
int iRx = soc.Receive(buffer);
char[] chars = new char[iRx];
Decoder d = Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(buffer, 0, iRx, chars, 0);
string recv = new string(chars);
rec.sent_ack_message = recv;
rec.number_of_bytes_sent = numberOfBytesSent;
var ackMessageStatus = rec.AckMessageStatus();
if (!String.IsNullOrEmpty(ackMessageStatus))
{
if (ackMessageStatus == "NNN")
{
//Sent successfully. NNN= Good
rec.status = Status.SENT.ToString();
}
else
{
//User received anything else which means something bad in the message.
rec.status = Status.FAILED.ToString();
rec.last_failed_date = DateTime.Now;
rec.last_failed_reason = "Message format incorrect. Please contact IT Operations. Ack Message status " + ackMessageStatus + ".";
}
}
else
{
rec.status = Status.QUEUED.ToString();
rec.last_failed_date = DateTime.Now;
rec.last_failed_reason = "Message sent but no acknowledgment message was received. Message sent back to queued state to try again.";
}
rec.last_modified_by = systemUserId;
rec.last_modified_date = DateTime.Now;
rec.status_date = DateTime.Now;
rec.sent_date = DateTime.Now;
rec.sent_attempt_count = rec.sent_attempt_count + 1;
dbContext.SaveChanges();
}
catch (Exception e)
{
rec.status = Status.FAILED.ToString();
rec.last_modified_by = systemUserId;
rec.last_modified_date = DateTime.Now;
rec.status_date = DateTime.Now;
rec.last_failed_date = DateTime.Now;
rec.last_failed_reason = e.ToString();
rec.sent_attempt_count = rec.sent_attempt_count + 1;
dbContext.SaveChanges();
}
}
}
}
}
catch (System.Net.Sockets.SocketException e)
{
Util.LogError(LogType.FAILED_CONNECTION, e.Message, e.StackTrace);
}
catch (System.Data.DataException e)
{
Util.LogError(LogType.FAILED_TO_CONNECT_TO_DATABASE, e.Message, e.StackTrace);
}
catch (Exception e)
{
//General error if its not database or a socket exception issue.
Util.LogError(LogType.ERROR, e.Message, e.StackTrace);
}
}
}
}
Question:
How do I handle when I get a connection reset by the peer?
I was thinking maybe after I call soc.Connect(remoteEP). I check to see if soc.Connected is false. If so then I disconnect.
if (!soc.Connected)
{
soc.Disconnect(true);
}
Note:
I was disconnecting the socket after I sent my messages but the admin working on the server told me not to do that. Also the executable has been running fine for 3 weeks. No errors or anything.

How to continuously ping and result changes an image

Hoping you can help me out here.
I am having a issue figuring out how to loop a piece of ping code and result ( if true or false ) changes an image.
here is my code running on a button click,
My aim here is to basically automise the app so the user does not have to click the refresh icon,
I have read a bit and am thinking I could use a while loop, But am unsure on how to use sleep with it.
The other method would be to use a thread with sleep?
I have also asked on MSDN to get the most feedback possible.
//Declaration of Global Variables (IP's)
public static string IP1, IP2, IP3;
//Method Setting Variables(IP's)
public static void setIP()
{
IP1 = Properties.Settings.Default.settingIP1;
IP2 = Properties.Settings.Default.settingIP2;
IP3 = Properties.Settings.Default.settingIP3;
}
//Method running Ping command
public static bool PingTest(string toPing)
{
string host = toPing;
bool result = false;
Ping p = new Ping();
try
{
PingReply reply = p.Send(host, 3000);
if (reply.Status == IPStatus.Success)
return true;
}
catch { }
return result;
}
//Refreshes IP1 then changes label to result
private void btnRefreshIP1_Click(object sender, RoutedEventArgs e)
{
setIP();
bool isConnected = false;
isConnected = PingTest(IP1);
if(isConnected == true)
{
lblsIP1.Foreground = Brushes.White;
lblsIP1.Content = "Online";
}
else
{
lblsIP1.Foreground = Brushes.Red;
lblsIP1.Content = "Offline";
}
}

Using Threads in a C# function for Excel

I am writing a ping function for Excel. This function suppose to take a column of IP address (about 200 address) and ping each one of them.
To avoid Excel getting stuck, I have decided to use a thread that will send the pings instead of the main thread. The problem is that the thread can't access the cell values and the Excel crashes.
I hope that someone could help me with this.
Here is the code :
private LinkedList<string> Iplist;
private Thread t;
public NetworkPing()
{
}
public int CalcPingColumn(Range IPcells, Range ANScells)
{
CreateIpList(IPcells);
this.t = new Thread(() => CalcPing_method(ANScells));
this.t.Start();
return 1;
}
//THE PROBLEM IS PREOBBLY HERE
private void CalcPing_method(Range ANScells)
{
foreach (Range ans in ANScells.Cells)
{
ans.Value2 = Ping(Iplist.Last.Value);
Iplist.RemoveLast();
Thread.Sleep(50);
}
}
private void CreateIpList(Range IPcells)
{
Iplist = new LinkedList<string>();
foreach (Range ip in IPcells.Cells)
{
Iplist.AddFirst(ip.Value2);
}
}
Try to use the BackgroundWorker-class instead of the regular Thread. It makes it more easy to "send" objects/instances between threads. From that you can also get progress: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.110).aspx
why not one function?
public string PingIpadress(string ipadress)
{
var pingSender = new Ping();
var 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(ipadress, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
return "alive " + reply.Options.Ttl;
}
return "no response";
}

C# change color of textbox lines using a string builder

I'm implementing a ping test that will see if remote computers are online or not. I have a text box where you put the computers IP in and then a button that when pressed, pings all the computers to see if they are online. I would like to change the color of the line to reflect online or offline ( green or red ). My current code changes the entire textbox color to red if one fails.
My goal is if one of the computers fails the ping test, it would show up as red while the others would stay green if they receive a ping back.
Thanks.
private void button_Click(object sender, EventArgs e)
{
var sb = new StringBuilder();
foreach (var line in txtcomputers.Lines)
{
string strhost = line;
if (strhost.Length > 0)
{
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
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;
try
{
PingReply reply = pingSender.Send(strhost, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
txtcomputers.ForeColor = Color.Green;
else
txtcomputers.ForeColor = Color.Red;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
In using a RichTextBox as Jon suggested you will need to use SelectionStart, SelectionLength, SelectionColor and GetFirstCharIndexFromLine to get the starting character index of each of your lines. See if this will work for you.
private void button_Click(object sender, EventArgs e)
{
var sb = new StringBuilder();
Color originalColor = txtcomputers.SelectionColor; ;
for (int i = 0; i < txtcomputers.Lines.Count(); i++)
{
var line = txtcomputers.Lines[i];
string strhost = line;
if (strhost.Length > 0)
{
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
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;
try
{
PingReply reply = pingSender.Send(strhost, timeout, buffer, options);
txtcomputers.SelectionStart = txtcomputers.GetFirstCharIndexFromLine(i);
txtcomputers.SelectionLength = strhost.Length;
if (reply.Status == IPStatus.Success)
{
txtcomputers.SelectionColor = Color.Green;
}
else
{
txtcomputers.SelectionColor = Color.Red;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
txtcomputers.SelectionLength = 0;
}
}
txtcomputers.SelectionColor = originalColor;
}
I believe that a TextBox can't have multiple colours of text in it. (At least in Windows Forms. You haven't specified what platform your GUI is using.)
You should look at RichTextBox instead, which definitely does allow for that.

The fastest way to ping a large list of IP adresses?

I have a large list of IP addresses in a datatable and i have to ping them so quickly,
I used this code :
public bool PingIP(string IP)
{
bool result = false;
try
{
Ping ping = new Ping();
PingReply pingReply = ping.Send(IP);
if (pingReply.Status == IPStatus.Success)
result = true;
}
catch
{
result = false;
}
return result;
}
then i call it in while loop :
private void CheckNetworkState()
{
while (rowindexping > -1)
{
if (rowindexping == tbl_ClientInfo.Rows.Count)
{
rowindexping = -1;
return;
}
string ip = tbl_ClientInfo.Rows[rowindexping]["clientip"].ToString();
if (!PingIP(ip))
{
do something
}
rowindexping++;
Thread.Sleep(100);
}
}
Since i want to do this work at the background of my project i call the class in a thread:
threadping = new Thread(CheckNetworkState);
threadping.IsBackground = true;
threadping.Start();
my problem is that it takes so many time and does not work at the background. i mean the system is busy till all ip addresses in tbl_clientinfo go through the ping class.
i want that system check all rows since i'm working with other part of my project.
Did i do correctly?
Your code is running all the code on a single thread; you're not using multiple threads. Also, why do you have a Thread.Sleep in there?
Try the following:
Query the database and get all the IPs
In a loop, spin up a new thread that will run PingIP for each IP address
Note: You can also spin up a new thread every time you get a new row from the database
Sample:
static void Main(string[] args)
{
// get the IPs from the database so you can iterate over them
List<string> ips = new List<string>()
{
"google.com",
"127.0.0.1",
"stackoverflow.com"
};
foreach (var ip in ips)
{
// See http://stackoverflow.com/questions/4744630/unexpected-behaviour-for-threadpool-queueuserworkitem
// for reason to use another variable in the loop
string loopIp = ip;
WaitCallback func = delegate(object state)
{
if (PingIP(loopIp))
{
Console.WriteLine("Ping Success");
}
else
{
Console.WriteLine("Ping Failed");
}
};
ThreadPool.QueueUserWorkItem(func);
}
Console.ReadLine();
}
public static bool PingIP(string IP)
{
bool result = false;
try
{
Ping ping = new Ping();
PingReply pingReply = ping.Send(IP);
if (pingReply.Status == IPStatus.Success)
result = true;
}
catch
{
result = false;
}
return result;
}
What I would do is have a separate multi-threaded daemon running in the background, doing the pings, and putting the results in a database. Have a page that loads results via AJAX later.
Consider making a system call to the fping utility. Granted, it's not managed code, but fping is very well optimized for your specific task and would simplify your problem down to a single call followed by the processing of a text-based list of results.
you can use powershell
private string resultat(string s)
{
Runspace space = RunspaceFactory.CreateRunspace();
space.Open();
Pipeline pipeline = space.CreatePipeline();
pipeline.Commands.AddScript(s);
pipeline.Commands.Add("Out-String");
Collection<PSObject> results = pipeline.Invoke();
StringBuilder stringBuilder = new StringBuilder();
foreach (PSObject obj in results)
{
stringBuilder.AppendLine(obj.ToString());
}
return stringBuilder.ToString();
}
and then use resultat("ping -l 10 -n 2 " + your_ip);

Categories