using System;
using System.IO;
using System.Net;
using System.Xml;
using System.Threading;
using System.Diagnostics;
using System.Net.NetworkInformation;
using System.Collections.Generic;
using System.Windows.Forms;
using CodeProjectSamples;
namespace NetworkMonitor
{
public partial class MainForm : Form
{
private List<NetworkLocation> LocationList;
private ListView LocationListView;
private delegate void nlss(NetworkLocation nl);
private Thread PingSender;
LogWriter writer;
public MainForm()
{
writer = new LogWriter();
InitializeComponent();
LocationList = new List<NetworkLocation>();
PingSender = new Thread(this.CheckIpAsync);
AddNetworkLocation("localhost", "127.0.0.1");
PingSender.Start();
}
public bool AddNetworkLocation(string name, string address)
{
NetworkLocation temp;
if (name.Length == 0)
{
MessageBox.Show("Enter a name", "Network Monitor", MessageBoxButtons.OK);
return false;
}
else if (!ValidIp(address))
{
MessageBox.Show("Enter a valid ip/hostname", "Network Monitor", MessageBoxButtons.OK);
return false;
}
temp = new NetworkLocation(name, address);
LocationList.Add(temp);
return true;
}
private bool ValidIp(string address)
{
string[] parts = address.Split(new char[] { '.' }, StringSplitOptions.None);
if (parts.Length != 4)
return false;
else if (parts[0].Length == 0 || parts[1].Length == 0 || parts[2].Length == 0 || parts[3].Length == 0)
return false;
else
{
try
{
int a, b, c, d;
a = int.Parse(parts[0]);
b = int.Parse(parts[1]);
c = int.Parse(parts[2]);
d = int.Parse(parts[3]);
if ((a < 0 || a > 255) || (b < 0 || b > 255) || (c < 0 || c > 255) || (d < 0 || d > 255))
return false;
else
return true;
}
catch (Exception)
{
return false;
}
}
}
public void CheckIpAsync()
{
try
{
while (true)
{
NetworkLocation[] all_locations = new NetworkLocation[LocationList.Count];
LocationList.CopyTo(all_locations);
foreach (NetworkLocation nl in all_locations)
{
this.BeginInvoke(new nlss(this.NetworkLocationSetStatus), new Object[] { nl });
}
Thread.Sleep(1000);
}
}
catch (Exception)
{
}
}
public void NetworkLocationSetStatus(NetworkLocation nl)
{
try
{
Ping ipchecker = new Ping();
PingReply reply = ipchecker.Send(nl.Address, 1000);
if (reply.Status == IPStatus.Success && nl.IsAlive == false)
{
MessageBox.Show(nl.Name + "[" + nl.Address + "] went alive at " + DateTime.Now);
writer.WriteLine(nl.Name + "[" + nl.Address + "] went alive at " + DateTime.Now);
nl.IsAlive = true;
}
else if (reply.Status != IPStatus.Success && nl.IsAlive == true)
{
writer.WriteLine(nl.Name + "[" + nl.Address + "] went dead at " + DateTime.Now);
nl.IsAlive = false;
}
}
catch (Exception)
{
writer.WriteLine(nl.Name + "[" + nl.Address + "] went dead at " + DateTime.Now);
}
}
private void AddLocationButton_Click(object sender, EventArgs e)
{
}
private void AboutButton_Click(object sender, EventArgs e)
{
}
private void Watchmantimer_Tick(object sender, EventArgs e)
{
int index = -1;
try
{
index = LocationListView.SelectedIndices[0];
}
catch (Exception)
{
}
finally
{
LocationListView.Items.Clear();
foreach (NetworkLocation l in LocationList)
{
ListViewItem li = LocationListView.Items.Add(l.Name);
li.SubItems.Add(l.Address);
li.ImageIndex = l.IsAlive ? 0 : 1;
}
if (index >= LocationListView.Items.Count)
index = -1;
if (index != -1)
LocationListView.Items[index].Selected = true;
}
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
DialogResult rs = MessageBox.Show("Click Yes to close application \nClick No to minimize\n& Click Cancel to close this dialog", "Network Monitor", MessageBoxButtons.YesNoCancel);
if (rs == DialogResult.Yes)
{
if (PingSender.IsAlive)
{
PingSender.Abort();
}
try
{
File.Delete("NetworkMonitor.xml");
XmlTextWriter xmlWriter = new XmlTextWriter("NetworkMonitor.xml", System.Text.Encoding.UTF8);
xmlWriter.Formatting = Formatting.Indented;
xmlWriter.WriteProcessingInstruction("xml", "version='1.0' encoding='UTF-8'");
xmlWriter.WriteStartElement("NetworkLocationList");
xmlWriter.Close();
XmlDocument doc = new XmlDocument();
doc.Load("NetworkMonitor.xml");
foreach (NetworkLocation nl in LocationList)
{
XmlElement newlocation = doc.CreateElement("NetworkLocation");
XmlElement newname = doc.CreateElement("Name");
XmlElement newaddress = doc.CreateElement("Address");
newname.InnerText = nl.Name;
newaddress.InnerText = nl.Address;
newlocation.AppendChild(newname);
newlocation.AppendChild(newaddress);
doc.DocumentElement.AppendChild(newlocation);
}
XmlTextWriter tr = new XmlTextWriter("NetworkMonitor.xml", null);
tr.Formatting = Formatting.Indented;
doc.WriteContentTo(tr);
tr.Close();
}
catch (Exception)
{
MessageBox.Show("Could not save entries while closing form", "Network Monitor", MessageBoxButtons.OK);
}
}
else if (rs == DialogResult.No)
{
this.WindowState = FormWindowState.Minimized;
this.MainForm_Resize(this, null);
}
else
e.Cancel = true;
}
private void ApplicationNotifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
{
this.Show();
this.WindowState = FormWindowState.Normal;
}
private void MainForm_Resize(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
}
else if (FormWindowState.Normal == this.WindowState)
{
}
}
private void ShowLogButton_Click(object sender, EventArgs e)
{
if (File.Exists(Environment.CurrentDirectory + "\\" + DateTime.Now.ToString("ddMMyyyy") + ".log"))
{
Process showlog = new Process();
showlog.StartInfo.FileName = "notepad.exe";
showlog.StartInfo.Arguments = Environment.CurrentDirectory + "\\" + DateTime.Now.ToString("ddMMyyyy") + ".log";
showlog.Start();
}
else
MessageBox.Show("No Log created for today. Try again later.", "Network Monitor", MessageBoxButtons.OK);
}
private void RemoveLocationButton_Click(object sender, EventArgs e)
{
try
{
int index = LocationListView.SelectedIndices[0];
LocationList.RemoveAt(index);
}
catch (Exception)
{
MessageBox.Show("Select a location from the list and then click Remove", "Network Monitor", MessageBoxButtons.OK);
}
}
private void MainForm_Load(object sender, EventArgs e)
{
writer.WriteLine("Application started at " + DateTime.Now);
XmlDocument doc = new XmlDocument();
doc.Load("NetworkMonitor.xml");
XmlNodeList nodelst = doc.GetElementsByTagName("NetworkLocation");
foreach (XmlNode nd in nodelst)
{
this.AddNetworkLocation(nd.FirstChild.InnerText, nd.LastChild.InnerText);
}
PingSender.Priority = ThreadPriority.BelowNormal;
PingSender.Start();
}
private void InitializeComponent()
{
this.LocationListView = new System.Windows.Forms.ListView();
this.SuspendLayout();
this.LocationListView.Location = new System.Drawing.Point(32, 27);
this.LocationListView.Name = "LocationListView";
this.LocationListView.Size = new System.Drawing.Size(504, 282);
this.LocationListView.TabIndex = 0;
this.LocationListView.UseCompatibleStateImageBehavior = false;
this.ClientSize = new System.Drawing.Size(669, 365);
this.Controls.Add(this.LocationListView);
this.Name = "MainForm";
this.ResumeLayout(false);
}
}
}
The above is his main form and here is NetworkLocation class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CodeProjectSamples
{
public class NetworkLocation
{
public string Address;
public string Name;
public bool IsAlive;
public NetworkLocation(string name, string address)
{
this.Address = address;
this.Name = name;
}
}
}
Now if you execute the code ( It crashed my system twice. So be careful), you will see that the MessageBox I have placed inside CheckIpAsync() never gets called. As against if you comment while(true), expectantly once the MessageBox will appear. Why?
OP assumes that by invoking CheckIpAsync from an Asynchronous callback aspect fixes everything for him. No. In LogWriter class there is a shared variable
_messagelist
.
So every time you call WriteLine() you are trying to write in _messagelist. Result? Two asynchronous instances at some instance will write to access the _messagelist memory.
Now do a simple test:
Change the foreach statement with
this.Invoke((MethodInvoker)delegate
{
this.BeginInvoke(new nlss(this.NetworkLocationSetStatus), new Object[] { nl });
});
You will see many instances of MessageBox. So either you need to use a BackgroundWorker and modify your while with that or take a timer and call CheckIpAsync from timer tick ( no while remember). In either cases protect _messagelist by proper locking ( eg. above code).
In my discussion in comments I took an example of Label because UI elements are better way of understanding the flow of your execution. calling BeginInvoke from a loop with a shared variable is as good as calling it serially due to lock problem.