How to continuously ping and result changes an image - c#

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";
}
}

Related

how to make progress bar work with functions in button event

i am new in C# so please be patient with me .
i want to make progress bar work with any functions i make in my program
i have class to check if INTERNET available and the connection of database status
and i have "progressBar1" , style is "Marquee"
i just want to indicate that there is a process work "Function" in the program and i don't need to have step or timer to increment it
just make the progress work until the function finish its code and the functions will work in button event (when i push button)
this is my code
class checkInternet
{
[DllImport("wininet.dll")]
private extern static bool InternetGetConnectedState(out int Description, int ReservedValue);
public bool checkInternetAvailable()
{
int Desc;
bool result = false;
if (InternetGetConnectedState(out Desc, 0) == true)
{
try
{
dbConnection StartConn = new dbConnection();
SqlConnection MyConnetion = StartConn.GetConnection();
MyConnetion.Open();
if (MyConnetion.State == ConnectionState.Open)
{
result = true;
}
MyConnetion.Close();
}
catch (Exception)
{
result = false;
MessageBox.Show("The database connection does not available, May be because of this reasons: \n\n1- there is a new version of the program avalible. \n2- database has some maintenance. \n\n Please check later :)", "Conection status");
}
}
else
{
result = false;
MessageBox.Show("No internet connection avalible , Please check later :) \nThanks.", "Conection status");
}
return result;
}
}
and this is what i have in my button event
private void button1_Click(object sender, EventArgs e)
{
checkInternet check = new checkInternet();
progressBar1.Value = 0;
do
{
progressBar1.PerformStep();
} while (check.checkInternetAvailable());
}
how can i implement that ?
thanks
As I understand you want user to see progressbar while your check connection task executes in background. checkInternetAvailable would be your background operation and I wouldn't suggest showing messages directly form it. Instead return a custom struct :
public struct ConnectionCheckResult
{
public bool Success;
public string Message;
}
And this will be your button click event handler :
private void button1_Click(object sender, EventArgs e)
{
progressBar1.Style = ProgressBarStyle.Marquee;
progressBar1.Visible = true;
//add code here to be executed on UI thread before connection check
Task.Run(new Action(() =>
{
//Task.Run this code on the thread pool instead of your UI thread. So your code is checking connection while progress bar is still rendering
ConnectionCheckResult res = new checkInternet().checkInternetAvailable();
this.Invoke(new Action(() =>
{
//this.Invoke executes following delegate on UI thread. All UI changes - like progressBar1.Visible = false; need to be made in UI thread.
//add code here to be executed on the UI thread after connection check.
progressBar1.Visible = false;
if (!string.IsNullOrEmpty(res.Message))
MessageBox.Show(res.Message);
}));
}));
//add code to be executed on UI thread at the same time as connection check
}
I know multi-threading is difficult to wrap your head around at first, here's good tutorial with code samples.
Also when your progressbar style is Marquee you don't need to call PerformStep. It will just roll by itself.
EDIT: You should also modify checkInternetAvailable() like so :
public ConnectionCheckResult checkInternetAvailable()
{
int Desc;
ConnectionCheckResult result = new ConnectionCheckResult();
if (InternetGetConnectedState(out Desc, 0) == true)
{
try
{
dbConnection StartConn = new dbConnection();
SqlConnection MyConnetion = StartConn.GetConnection();
MyConnetion.Open();
if (MyConnetion.State == ConnectionState.Open)
{
result.Success = true;
}
MyConnetion.Close();
}
catch (Exception)
{
result.Success = false;
result.Message = "The database connection does not available, May be because of this reasons: \n\n1- there is a new version of the program available. \n2- database has some maintenance. \n\n Please check later :)";
}
}
else
{
result.Success = false;
result.Message = "No internet connection available , Please check later :) \nThanks.";
}
return result;
}

writeBytes returning -1025 using LibNoDave

I have a weird problem with my Connection from C# to my Simatic S7-1200.
I am using LibNoDave to connect and i want to set bits of my SPS with the C#-program.
This is working just fine but it only works 9 times and then the writeBytes(..) function returns -1025 and not 0 as it should and it is not setting the byte anymore.
I then have to restart the application and it will work 9 times again.
This is my LibNoDave class.
static class LibNoDave
{
static libnodave.daveConnection dc;
static bool connection = false;
public static bool CreateConnection()
{
const string IP = "192.168.1.250";
const int Rack = 0;
const int Slot = 0;
libnodave.daveOSserialType fds;
libnodave.daveInterface di;
try
{
fds.rfd = libnodave.openSocket(102, IP);
fds.wfd = fds.rfd;
if (fds.rfd > 0)
{
di = new libnodave.daveInterface(fds, "IF1",
0, libnodave.daveProtoISOTCP,
libnodave.daveSpeed187k);
di.setTimeout(1000000);
int res = di.initAdapter();
if (res == 0)
{
dc = new libnodave.daveConnection(di, 0,
Rack, Slot);
res = dc.connectPLC();
if (res == 0)
{
connection = true;
return true;
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return false;
}
public static void DisconnectPLC()
{
if (connection)
{
dc.disconnectPLC();
libnodave.closeSocket(102);
connection = false;
}
}
public static void WritePLC(int anfangswert, byte wert)
{
if (connection)
{
byte[] buf = new Byte[1];
buf[0] = wert;
int res = dc.writeBytes(libnodave.daveFlags, 0, anfangswert, 1, buf);
MessageBox.Show(res.ToString());
}
}
}
Here I am calling the functions:
private void frmAuslagerung_Load(object sender, EventArgs e)
{
if (!LibNoDave.CreateConnection())
{
finished = true;
this.Close();
}
LibNoDave.WritePLC(1, Byte.Parse(auto.Position.Lade.ToString()));
}
private void frmAuslagerung_FormClosing(object sender, FormClosingEventArgs e)
{
if (!finished)
{
//e.Cancel = true; //Not in code for testing
LibNoDave.DisconnectPLC(); //Only for testing
}
else
LibNoDave.DisconnectPLC();
}
I don´t see any problem in code and I don´t know neither your device nor LibNoDave, but the problem may be related to:
1- Is some receiver an "One single digit" (like 0 to 9) address or container ?
2- The position is being truly reseted as I see in WritePLC function?
3- The "LibNoDave.WritePLC" is incrementing its pointer?
Good luck.
it can be problem closing the connection try with:
public static void DisconnectPLC()
{
if (connection)
{
dc.disconnectPLC();
di.disconnectAdapter();
libnodave.closePort(fds.rfd);
connection = false;
}
}
It's old, but for others to find: in my case it was the declaration of fds and di: they had to be class members and not local to the connect method, or the timeout value was being lost later on.

Ping Multiple IP Addresses and Show Green Completion

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;
}
}

System.Timers.Timer Usage

For the purposes of this question I'm including a class of mine in its entirety:
public class SerialPortConnection
{
private SerialPort serialPort;
private string ping;
double failOut;
bool isReceiving;
public SerialPortConnection(string comPort = "Com1", int baud = 9600, System.IO.Ports.Parity parity = System.IO.Ports.Parity.None, int dataBits = 8, System.IO.Ports.StopBits stopBits = System.IO.Ports.StopBits.One, string ping = "*IDN?", double failOut = 2)
{
this.ping = ping;
this.failOut = failOut * 1000;
try
{
serialPort = new SerialPort(comPort, baud, parity, dataBits, stopBits);
}
catch (Exception e)
{
throw e;
}
}
//Open Serial Connection. Returns False If Unable To Open.
public bool OpenSerialConnection()
{
//Opens Initial Connection:
try
{
serialPort.Open();
serialPort.Write("REMOTE\r");
}
catch (Exception e)
{
throw e;
}
serialPort.Write(ping + "\r");
var testReceived = "";
isReceiving = true;
Timer StopWatch = new Timer(failOut);
StopWatch.Elapsed += new ElapsedEventHandler(OnTimedEvent);
StopWatch.Interval = failOut;
StopWatch.Enabled = true;
while (isReceiving == true)
{
try
{
testReceived += serialPort.ReadExisting();
}
catch (Exception e)
{
throw e;
}
}
StopWatch.Dispose();
if (testReceived.Contains('>'))
{
return true;
}
else
{
return false;
}
}
public string WriteSerialConnection(string SerialCommand)
{
try
{
serialPort.Write(String.Format(SerialCommand + "\r"));
var received = "";
bool isReceiving = true;
Timer StopWatch = new Timer(failOut);
StopWatch.Elapsed += new ElapsedEventHandler(OnTimedEvent);
StopWatch.Interval = failOut;
StopWatch.Enabled = true;
while (isReceiving == true)
{
try
{
received += serialPort.ReadExisting();
}
catch (Exception e)
{
throw e;
}
}
if (received.Contains('>'))
{
return received;
}
else
{
received = "Error: No Data Received From Device";
return received;
}
StopWatch.Dispose();
}
catch (Exception e)
{
throw e;
}
}
//Closes Serial Connection. Returns False If Unable To Close.
public bool CloseSerialConnection()
{
try
{
serialPort.Write("LOCAL\r");
serialPort.Close();
return true;
}
catch (Exception e)
{
throw e;
}
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
isReceiving = false;
}
}
What I'm attempting to do here is keep a loop running for a set amount of time (two seconds in this case) because the device connected to the serial port I'm working with is unpredictable. I don't know what data I will receive from it and I don't know how long it will take. That can't be fixed and is something I have to work with. My best option, currently, is to wait a set amount of time and check the data I've received for an end token (">"). I've tried wiring up a timer even in the class like so:
Timer StopWatch = new Timer(failOut * 1000);
StopWatch.Elapsed += new ElapsedEventHandler(OnTimedEvent);
StopWatch.Interval = failOut;
StopWatch.Enabled = true;
But it doesn't appear to work. The event itself looks like so:
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
isReceiving = false;
}
My objective is to cut the loop isReceiving is tied to:
(while isReceiving == true)
{
//Do Something
}
But it doesn't appear to work. I assume I've completely misunderstood the function of the timer but I've had suggestions before to implement it. What am I doing wrong? If I'm just completely misusing it, what can I use instead of a timer? As I've said, I've no choice but to wait a set amount of time and check what I've received. That can't be avoided or handled in any way other than waiting and hoping I get something.
EDIT:
Maybe it's best I clarify this. The OnTimedEvent event is firing and the variable is set to false but it doesn't cut the loop as isReceiving isn't getting set to false.
EDIT 2:
Mr. Passant's answer works beautifully barring a strange error I'm encountering. As I don't believe it's a problem within his answer, it's more likely that it's a hardware flaw, or something else strange and obscure along those lines, I'm leaving his answer marked as accepted. I recommend anyone that chooses to implement his answer also view the question I have submitted here:
Apparent IO.Ports.SerialPort Flaw in C# or Possible Hardware Flaw
You are making it too difficult on yourself. Simply change the SerialPort.NewLine property to ">". And use SerialPort.ReadLine() to read the response. You can still use a timeout if you need it, assign the SerialPort.ReadTimeout property and be prepared to catch the TimeoutException.

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