Sorry for new thread--i have this code,basically a loop to ping a list of ip's return the results and save them to an access db:
Code:
Public Class SwitchMonitor
Dim Ping As Net.NetworkInformation.Ping
Dim pReply As Net.NetworkInformation.PingReply
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim i As Integer
Dim ds As New DataSet
Dim da As OleDb.OleDbDataAdapter
Dim sql As String
Dim con As New OleDb.OleDbConnection
Label1.Visible = True 'sets the visible properties to advice labels that display after clicking ping button
Label2.Visible = True
Label3.Visible = True
Label4.Visible = True
con.ConnectionString = "PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source = C:\Documents and Settings\mhorgan\Desktop\Network Map.mdb"
con.Open()
sql = "SELECT * FROM tblSwitch"
da = New OleDb.OleDbDataAdapter(sql, con)
da.Fill(ds, "monitor")
Dim cb As New OleDb.OleDbCommandBuilder(da)
Ping = New Net.NetworkInformation.Ping
Dim dgvr As DataGridViewRow
ProgressBar1.Minimum = 0 'sets minimum value of progress bar
ProgressBar1.Maximum = ds.Tables("monitor").Rows.Count - 1 'sets maximum value of progress bar
For i = 0 To ds.Tables("monitor").Rows.Count - 1
Application.DoEvents()
' Set up the progress bar's properties
ProgressBar1.Value = i
dgvr = New DataGridViewRow 'Creates a new row
DataGridView1.Rows.Add(dgvr) 'Add the row
Try
pReply = Ping.Send(ds.Tables("monitor").Rows(i).Item(5)) 'Sends the ping to the current item
DataGridView1.Rows.Item(i).Cells(0).Value = ds.Tables("monitor").Rows(i).Item(1) 'read in switch name from column 2 in network map db
DataGridView1.Rows.Item(i).Cells(1).Value = ds.Tables("monitor").Rows(i).Item(5) 'Updates the value of the new Item
DataGridView1.Rows.Item(i).Cells(2).Value = pReply.Status 'The value of the status returned
DataGridView1.Rows.Item(i).Cells(3).Value = Now.ToString() 'show the last time checked with Now.ToString() method
If pReply.Status <> Net.NetworkInformation.IPStatus.Success Then 'Sets the color of the cell based on ping result
DataGridView1.Rows.Item(i).Cells(2).Style.BackColor = Color.Red
Else
DataGridView1.Rows.Item(i).Cells(2).Style.BackColor = Color.Green
End If
ds.Tables("monitor").Rows(i).Item(6) = pReply.Status 'Write in the original datatable
ds.Tables("monitor").Rows(i).Item(7) = Now.ToString() 'added code for date/time
da.Update(ds, "monitor") 'Updates the database
Catch ex As Exception 'Error Handling
MessageBox.Show(ex.ToString())
End Try
Next
End Sub
Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExit.Click
Dim con As New OleDb.OleDbConnection
con.ConnectionString = "PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source = C:\Documents and Settings\mhorgan\Desktop\Network Map.mdb"
con.Close()
End
End Sub
Private Sub SwitchMonitor_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
End Class
The problem is that for some reason when i first run the code in the morning all the switches time out and as there are over 400 switches this takes over 25mins during which the program remains unresponsive, but if i then run the code a second time it works perfectly and all the switches that are up ping back and it only takes around 4mins (the reason it takes 4mins is because there are a number of switches in the db which i know are down and each of these take 5secs to time out). Its as if the program needs a warm up run ? anyone able to offer an explanation ?? - i have been told to use multiplethreads and background threads but im new to coding and my skills are very limited so im hoping if im just able to identify the problem i might be able to find an easier way around it-besides from what i gather the two suggestions mentioned above will only speed up the program which is not what im looking for,im just wondering WHY the code behaves differently the first time i run it ??-cant figure it out would appreciate any ideas cheers
I could have sworn I showed you how to do it using background threads last time you posted this same question. In fact I even remember taking the time to create an example database and complete working example program... did I dream that?
i know chris you did and thank you for that and i tried adapting it to my project but failed miserably , but for the moment im not so much looking for a solution to the problem im just looking for the CAUSE of the problem , why does the program need to run through once before it behaves correctly
im guessing that some procedure needs to be run only the first time the code runs(or for some reason takes longer the first time) and this takes longer than 5secs(as all ips time-out) , is it the pinging itself ? the datagridview ? vb loading the dataset ??-dataset is quite large 500+entries the fact that it is such a long procedure with only very basic coding operating in a single thread ?? - im guessing its the latter as everyone is suggesting background/multiplethreads but id like to identify the problem before i try and solve it.
any idea what this procedure might be ??
Last edited by markhorgan1; Aug 7th, 2009 at 04:44 AM.
ive taken another look at that post chris and the error im getting is at this line:
UpdateCommand.ExecuteNonQuery() 'Execute the command that updates the database
and it reads: No value given for one or more required parameters.
the db was never attatched so i had to make my own, im also trying to make sure its not a mismatch of data types i have tried changing result from bolean to string as all i could use in the access db was yes/no which i didnt think would be compatible with type bolean
also i have changed ipaddress to IP (the column name in the pingDB)
Last edited by markhorgan1; Aug 7th, 2009 at 03:56 AM.
That message you are getting means that you have specified a command string that has a parameter in it but then havent assigned a value for that parameter. So for example in this code:
vb Code:
Dim UpdateCommand As New OleDBCommand("UPDATE sometable SET column1=@parameter1 WHERE column2=@parameter2", MyConnection)
the @parameter1 and @parameter2 bits are parameters that it is expecting you to fill with a value, and to do that you have to do something like this (off the top of my head so syntax may not be 100% correct):
then the same for @parameter2.
So go through the code you are using and look for any command strings that are using parameters and make sure you fill all of those with the relevant values before you call ExecuteNonQuery
runs now, is very fast too results show up in logbox, one problem though it doesnt update the db. any ideas ? -im only familiar with connections using datasets so im kinda lost when it comes to your code
it reads in perfectly from db so its not a problem with the connection or anythin like its gotta be solely to do with the update commands, il try play around with them in the mean time
Last edited by markhorgan1; Aug 7th, 2009 at 05:25 AM.
well it runs perfectly but it only reads the ip's from the db ,unfortunately it doesnt write the result or the current time to the db which is the most important part for the project im working on , must be the update commands , was it working when you made it with your sample db ?
Imports System.Data.OleDb
Public Class Form1
''' <summary>
''' Represents a network switch (or any device with an IP) that is in the database
''' </summary>
Private Class NetworkSwitch
Private _IPAddress As String
Private _ID As Integer
Private _Result As Boolean
Public Property IPAddress() As String
Get
Return _IPAddress
End Get
Set(ByVal value As String)
_IPAddress = value
End Set
End Property
Public Property ID() As Integer
Get
Return _ID
End Get
Set(ByVal value As Integer)
_ID = value
End Set
End Property
Public Property Result() As Boolean
Get
Return _Result
End Get
Set(ByVal value As Boolean)
_Result = value
End Set
End Property
End Class
'Set up some variables that we will use from various functions/subs
Private PingList As List(Of NetworkSwitch)
Private Counter As Integer = 0
Private ConnString As New OleDbConnectionStringBuilder("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\test\pingDB.mdb;User Id=admin;Password=;")
'This is the Delegate that will be used to pass data between the threads safely
Private Delegate Sub PingComplete(ByVal sw As NetworkSwitch)
Private Sub Pingbtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Pingbtn.Click
Counter = 0 'reset the counter in case this is not the first time the ping button has been clicked
Pingbtn.Enabled = False 'Disable the ping button so it cannot be pressed again yet
btnExit.Enabled = False
Dim bgthread As New Threading.Thread(AddressOf BG_CollectData) 'Create a new background thread
bgthread.IsBackground = True 'Make the thread end if the program is closed
bgthread.Start() 'Start the background thread
End Sub
''' <summary>
''' This is the routine that is executed when bgthread.Start() is called in the event handler above
''' It collects information from the Access database and stores it in a list, then kicks off another
''' background thread (from the ThreadPool) that sends the ping
''' </summary>
Private Sub BG_CollectData()
'Create our connection that will be used to connect to the Access database
Dim AccessConnection As New OleDbConnection(ConnString.ConnectionString)
'Create the command that will be used to select all of the data in the IP and ID columns
Dim SelectCommand As New OleDbCommand("SELECT * FROM PingTable", AccessConnection)
'Create a new instance of a list of our NetworkSwitch class
PingList = New List(Of NetworkSwitch)
'Open the connection to the database
AccessConnection.Open()
'Use a DataReader to access the data that the SELECT command returns
Dim Reader As OleDbDataReader = SelectCommand.ExecuteReader
'Start to loop through the results
'This loop will be restarted for each row in the database
Do While Reader.Read
'Create a new instance of our NetworkSwitch class and populate the ID and IP properties
'with data from the current row in the database that we are looping through
Dim CurrentSwitch As New NetworkSwitch
With CurrentSwitch
.ID = Reader("ID")
.IPAddress = Reader("IPAddress")
End With
'Add the new instance of the NetworkSwitch to our list
PingList.Add(CurrentSwitch)
Loop 'Start the loop again for the next record in the database
'Close the connection because we have now processed all rows in the database
AccessConnection.Close()
'Give the threadpool a limit so that no more than 30 threads are running at the same time
Threading.ThreadPool.SetMaxThreads(30, 400)
'Loop through our list of NetworkSwitch instances and start (well, queue up) a new background
'thread for each item in the list and passes it the current item in the loop (which is a NetworkSwitch object)
For Each switchobject As NetworkSwitch In PingList
Threading.ThreadPool.QueueUserWorkItem(New Threading.WaitCallback(AddressOf DoPing), switchobject)
Next
End Sub
''' <summary>
''' Performs the ping and updates the Result property of the NetworkSwitch object that was passed to this
''' </summary>
Private Sub DoPing(ByVal Switch As NetworkSwitch)
Dim Result As Net.NetworkInformation.PingReply
Dim SendPing As New Net.NetworkInformation.Ping
Result = SendPing.Send(Switch.IPAddress)
If Result.Status = Net.NetworkInformation.IPStatus.Success Then
Switch.Result = True
Else
Switch.Result = False
End If
UpdateDatabase(Switch)
Counter += 1
Me.Invoke(New PingComplete(AddressOf UI_PingComplete), Switch)
End Sub
''' <summary>
''' This is executed each time a ping completes and the database has been updated.
''' It is executed on the UI thread because we used Me.Invoke to call it so it can access
''' controls on the UI thread without a problem
''' </summary>
Private Sub UI_PingComplete(ByVal sw As NetworkSwitch)
logbox.AppendText(sw.IPAddress & " ping complete - " & sw.Result & vbNewLine) 'update our log textbox
If Counter = PingList.Count Then
logbox.AppendText("Finished all tests" & vbNewLine)
Pingbtn.Enabled = True 're-enable the ping button
btnExit.Enabled = True
PingList = Nothing 'clean up
End If
End Sub
''' <summary>
''' Updates the relevant row in the database for the switch that is passed to this method
''' </summary>
Private Sub UpdateDatabase(ByVal sw As NetworkSwitch)
Dim AccessConnection As New OleDbConnection(ConnString.ConnectionString)
Dim UpdateCommand As New OleDbCommand("UPDATE PingTable SET Result=@Result, LastTested=@CurrentTime WHERE ID=@ID", AccessConnection)
With UpdateCommand.Parameters
.Add("@Result", OleDbType.Boolean).Value = sw.Result
.Add("@CurrentTime", OleDbType.Char).Value = Now.ToString
.Add("@ID", OleDbType.Integer).Value = sw.ID
End With
AccessConnection.Open()
UpdateCommand.Parameters.Add("@parameter1", OleDbType.Boolean).Value = True'Execute the command that updates the database
AccessConnection.Close()
End Sub
Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExit.Click
End
End Sub
End Class
and these are all the columns in access db (access 2000 format)
Keep in mind that some ISPs block Pings due to security.
If your ISP or any other ISP for some of your users does block the Ping(s) you won't get the expected or desired results.
okay nevermind ! found the problem , the access column was named currenttime instead of LastTested , can the text in the logbox be conditionally formatted like in datagridview ? ie red for false green for true ?
okay thanks will try that ! what about adding a progress bar ? could this be easily done ?
im guessing its something like this but not sure what to set value to, also not sure where to put code because everywhere i try i get crossthread errors ?
Code:
ProgressBar1.Minimum = 0 'sets minimum value of progress bar
ProgressBar1.Maximum = Counter 'maximum value of progres
ProgressBar1.Value = ?? ' Set up the progress bar's properties
also tried changing from richtextbox to datagridview but im having trouble with the loop.
heres code:
Code:
Imports System.Data.OleDb
Public Class Form1
''' <summary>
''' Represents a network switch (or any device with an IP) that is in the database
''' </summary>
Private Class NetworkSwitch
Private _IPAddress As String
Private _ID As Integer
Private _Result As Boolean
Public Property IPAddress() As String
Get
Return _IPAddress
End Get
Set(ByVal value As String)
_IPAddress = value
End Set
End Property
Public Property ID() As Integer
Get
Return _ID
End Get
Set(ByVal value As Integer)
_ID = value
End Set
End Property
Public Property Result() As Boolean
Get
Return _Result
End Get
Set(ByVal value As Boolean)
_Result = value
End Set
End Property
End Class
'Set up some variables that we will use from various functions/subs
Dim i As Integer
Private PingList As List(Of NetworkSwitch)
Private Counter As Integer = 0
Private ConnString As New OleDbConnectionStringBuilder("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\test\pingDB.mdb;User Id=admin;Password=;")
'This is the Delegate that will be used to pass data between the threads safely
Private Delegate Sub PingComplete(ByVal sw As NetworkSwitch)
Private Sub Pingbtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Pingbtn.Click
Counter = 0 'reset the counter in case this is not the first time the ping button has been clicked
Pingbtn.Enabled = False 'Disable the ping button so it cannot be pressed again yet
btnExit.Enabled = False
Dim bgthread As New Threading.Thread(AddressOf BG_CollectData) 'Create a new background thread
bgthread.IsBackground = True 'Make the thread end if the program is closed
bgthread.Start() 'Start the background thread
End Sub
''' <summary>
''' This is the routine that is executed when bgthread.Start() is called in the event handler above
''' It collects information from the Access database and stores it in a list, then kicks off another
''' background thread (from the ThreadPool) that sends the ping
''' </summary>
Private Sub BG_CollectData()
'Create our connection that will be used to connect to the Access database
Dim AccessConnection As New OleDbConnection(ConnString.ConnectionString)
'Create the command that will be used to select all of the data in the IP and ID columns
Dim SelectCommand As New OleDbCommand("SELECT * FROM PingTable", AccessConnection)
'Create a new instance of a list of our NetworkSwitch class
PingList = New List(Of NetworkSwitch)
'Open the connection to the database
AccessConnection.Open()
'Use a DataReader to access the data that the SELECT command returns
Dim Reader As OleDbDataReader = SelectCommand.ExecuteReader
'Start to loop through the results
'This loop will be restarted for each row in the database
Do While Reader.Read
'Create a new instance of our NetworkSwitch class and populate the ID and IP properties
'with data from the current row in the database that we are looping through
Dim CurrentSwitch As New NetworkSwitch
With CurrentSwitch
.ID = Reader("ID")
.IPAddress = Reader("IPAddress")
End With
'Add the new instance of the NetworkSwitch to our list
PingList.Add(CurrentSwitch)
Loop 'Start the loop again for the next record in the database
'Close the connection because we have now processed all rows in the database
AccessConnection.Close()
'Give the threadpool a limit so that no more than 30 threads are running at the same time
Threading.ThreadPool.SetMaxThreads(30, 400)
'Loop through our list of NetworkSwitch instances and start (well, queue up) a new background
'thread for each item in the list and passes it the current item in the loop (which is a NetworkSwitch object)
For Each switchobject As NetworkSwitch In PingList
Threading.ThreadPool.QueueUserWorkItem(New Threading.WaitCallback(AddressOf DoPing), switchobject)
Next
End Sub
''' <summary>
''' Performs the ping and updates the Result property of the NetworkSwitch object that was passed to this
''' </summary>
Private Sub DoPing(ByVal Switch As NetworkSwitch)
Dim Result As Net.NetworkInformation.PingReply
Dim SendPing As New Net.NetworkInformation.Ping
Result = SendPing.Send(Switch.IPAddress)
If Result.Status = Net.NetworkInformation.IPStatus.Success Then
Switch.Result = True
' <<<<<<----change Font Color to green/red ??
Else
Switch.Result = False
End If
UpdateDatabase(Switch)
Counter += 1
Me.Invoke(New PingComplete(AddressOf UI_PingComplete), Switch)
End Sub
''' <summary>
''' This is executed each time a ping completes and the database has been updated.
''' It is executed on the UI thread because we used Me.Invoke to call it so it can access
''' controls on the UI thread without a problem
''' </summary>
Private Sub UI_PingComplete(ByVal sw As NetworkSwitch)
Dim dgvr As DataGridViewRow
Dim i As Integer
For i = 0 To PingList.Count
Application.DoEvents()
dgvr = New DataGridViewRow 'Creates a new row
DataGridView1.Rows.Add(dgvr) 'Add the row
DataGridView1.Rows.Item(i).Cells(0).Value = sw.IPAddress
DataGridView1.Rows.Item(i).Cells(1).Value = sw.ID
DataGridView1.Rows.Item(i).Cells(2).Value = sw.Result
DataGridView1.Rows.Item(i).Cells(3).Value = Now.ToString() 'show the last time checked with Now.ToString() method
' logbox.AppendText(sw.IPAddress & " ping complete - " & sw.Result & vbNewLine) 'update our log textbox
If Counter = PingList.Count Then
' logbox.AppendText("Finished all tests" & vbNewLine)
Pingbtn.Enabled = True 're-enable the ping button
btnExit.Enabled = True
PingList = Nothing 'clean up
End If
Next
End Sub
''' <summary>
''' Updates the relevant row in the database for the switch that is passed to this method
''' </summary>
Private Sub UpdateDatabase(ByVal sw As NetworkSwitch)
Dim AccessConnection As New OleDbConnection(ConnString.ConnectionString)
Dim UpdateCommand As New OleDbCommand("UPDATE PingTable SET Result=@Result, LastTested=@CurrentTime WHERE ID=@ID", AccessConnection)
With UpdateCommand.Parameters
.Add("@Result", OleDbType.Boolean).Value = sw.Result
.Add("@CurrentTime", OleDbType.Char).Value = Now.ToString
.Add("@ID", OleDbType.Integer).Value = sw.ID
End With
AccessConnection.Open()
UpdateCommand.ExecuteNonQuery() 'Execute the command that updates the database
AccessConnection.Close()
End Sub
Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExit.Click
End
End Sub
End Class
Last edited by markhorgan1; Aug 11th, 2009 at 05:53 AM.
okay i think im a bit closer now but ders still a problem with the loop , or the multiple threads , or the datagridview ,
Code:
Imports System.Data.OleDb
Public Class Form1
''' <summary>
''' Represents a network switch (or any device with an IP) that is in the database
''' </summary>
Private Class NetworkSwitch
Private _IPAddress As String
Private _ID As Integer
Private _Result As Boolean
Public Property IPAddress() As String
Get
Return _IPAddress
End Get
Set(ByVal value As String)
_IPAddress = value
End Set
End Property
Public Property ID() As Integer
Get
Return _ID
End Get
Set(ByVal value As Integer)
_ID = value
End Set
End Property
Public Property Result() As Boolean
Get
Return _Result
End Get
Set(ByVal value As Boolean)
_Result = value
End Set
End Property
End Class
'Set up some variables that we will use from various functions/subs
Dim i As Integer
Private PingList As List(Of NetworkSwitch)
Private Counter As Integer = 0
Private ConnString As New OleDbConnectionStringBuilder("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\test\pingDB.mdb;User Id=admin;Password=;")
'This is the Delegate that will be used to pass data between the threads safely
Private Delegate Sub PingComplete(ByVal sw As NetworkSwitch)
Private Sub Pingbtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Pingbtn.Click
Counter = 0 'reset the counter in case this is not the first time the ping button has been clicked
Pingbtn.Enabled = False 'Disable the ping button so it cannot be pressed again yet
btnExit.Enabled = False
Dim bgthread As New Threading.Thread(AddressOf BG_CollectData) 'Create a new background thread
bgthread.IsBackground = True 'Make the thread end if the program is closed
bgthread.Start() 'Start the background thread
End Sub
''' <summary>
''' This is the routine that is executed when bgthread.Start() is called in the event handler above
''' It collects information from the Access database and stores it in a list, then kicks off another
''' background thread (from the ThreadPool) that sends the ping
''' </summary>
Private Sub BG_CollectData()
'Create our connection that will be used to connect to the Access database
Dim AccessConnection As New OleDbConnection(ConnString.ConnectionString)
'Create the command that will be used to select all of the data in the IP and ID columns
Dim SelectCommand As New OleDbCommand("SELECT * FROM PingTable", AccessConnection)
'Create a new instance of a list of our NetworkSwitch class
PingList = New List(Of NetworkSwitch)
'Open the connection to the database
AccessConnection.Open()
'Use a DataReader to access the data that the SELECT command returns
Dim Reader As OleDbDataReader = SelectCommand.ExecuteReader
'Start to loop through the results
'This loop will be restarted for each row in the database
Do While Reader.Read
'Create a new instance of our NetworkSwitch class and populate the ID and IP properties
'with data from the current row in the database that we are looping through
Dim CurrentSwitch As New NetworkSwitch
With CurrentSwitch
.ID = Reader("ID")
.IPAddress = Reader("IPAddress")
End With
'Add the new instance of the NetworkSwitch to our list
PingList.Add(CurrentSwitch)
Loop 'Start the loop again for the next record in the database
'Close the connection because we have now processed all rows in the database
AccessConnection.Close()
'Give the threadpool a limit so that no more than 30 threads are running at the same time
Threading.ThreadPool.SetMaxThreads(30, 400)
'Loop through our list of NetworkSwitch instances and start (well, queue up) a new background
'thread for each item in the list and passes it the current item in the loop (which is a NetworkSwitch object)
For Each switchobject As NetworkSwitch In PingList
Threading.ThreadPool.QueueUserWorkItem(New Threading.WaitCallback(AddressOf DoPing), switchobject)
Next
End Sub
''' <summary>
''' Performs the ping and updates the Result property of the NetworkSwitch object that was passed to this
''' </summary>
Private Sub DoPing(ByVal Switch As NetworkSwitch)
Dim Result As Net.NetworkInformation.PingReply
Dim SendPing As New Net.NetworkInformation.Ping
Result = SendPing.Send(Switch.IPAddress)
If Result.Status = Net.NetworkInformation.IPStatus.Success Then
Switch.Result = True
DataGridView1.Rows.Item(i).Cells(2).Style.BackColor = Color.Green
' <<----change Font Color to green/red ??
Else
Switch.Result = False
DataGridView1.Rows.Item(i).Cells(2).Style.BackColor = Color.Red
End If
UpdateDatabase(Switch)
Counter += 1
Me.Invoke(New PingComplete(AddressOf UI_PingComplete), Switch)
End Sub
''' <summary>
''' This is executed each time a ping completes and the database has been updated.
''' It is executed on the UI thread because we used Me.Invoke to call it so it can access
''' controls on the UI thread without a problem
''' </summary>
Private Sub UI_PingComplete(ByVal sw As NetworkSwitch)
Dim dgvr As DataGridViewRow
dgvr = New DataGridViewRow 'Creates a new row
DataGridView1.Rows.Add(dgvr) 'Add the row
Try
DataGridView1.Rows.Item(i).Cells(0).Value = sw.ID 'read in switch name from column 2 in network map db
DataGridView1.Rows.Item(i).Cells(1).Value = sw.IPAddress 'Updates the value of the new Item
DataGridView1.Rows.Item(i).Cells(2).Value = sw.Result 'The value of the status returned
DataGridView1.Rows.Item(i).Cells(3).Value = Now.ToString() 'show the last time checked with Now.ToString() method
If Counter = PingList.Count Then
Pingbtn.Enabled = True 're-enable the ping button
btnExit.Enabled = True
PingList = Nothing 'clean up
End If
Catch ex As Exception 'Error Handling
MessageBox.Show(ex.ToString())
End Try
End Sub
''' <summary>
''' Updates the relevant row in the database for the switch that is passed to this method
''' </summary>
Private Sub UpdateDatabase(ByVal sw As NetworkSwitch)
Dim AccessConnection As New OleDbConnection(ConnString.ConnectionString)
Dim UpdateCommand As New OleDbCommand("UPDATE PingTable SET Result=@Result, LastTested=@CurrentTime WHERE ID=@ID", AccessConnection)
With UpdateCommand.Parameters
.Add("@Result", OleDbType.Boolean).Value = sw.Result
.Add("@CurrentTime", OleDbType.Char).Value = Now.ToString
.Add("@ID", OleDbType.Integer).Value = sw.ID
End With
AccessConnection.Open()
UpdateCommand.ExecuteNonQuery() 'Execute the command that updates the database
AccessConnection.Close()
End Sub
Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExit.Click
End
End Sub
End Class
Last edited by markhorgan1; Aug 11th, 2009 at 10:13 AM.
okay sorry for all the postS but i cant figure out how to delete them !! anyway ive gone back to the richtextbox way of displaying results and also added a column SwitchName.
i cant seem to format the text in the richtextbox called "logbox" based on result of ping ive tried adding the following code:
Code:
If Result.Status = Net.NetworkInformation.IPStatus.Success Then
Switch.Result = True
logbox.SelectionColor = Color.Green
Else
Switch.Result = False
logbox.SelectionColor = Color.Red
End If
but i keep getting cross thread issues , im new to mulit-threading so was wondering if anyone could help me out ?
im also having the same problem tryin to add a progressbar "progressbar1" , tried adding the following code but its not working:
Code:
ProgressBar1.Minimum = 0 'set minimum value
ProgressBar1.Maximum = PingList.Count 'set maximum value
' Set up the progress bar's properties
ProgressBar1.Value = ??
heres all the code:
Code:
Imports System.Data.OleDb
Public Class Form1
''' <summary>
''' Represents a network switch (or any device with an IP) that is in the database
''' </summary>
Private Class NetworkSwitch
Private _IPAddress As String
Private _ID As Integer
Private _SwitchName As String
Private _Result As Boolean
Public Property IPAddress() As String
Get
Return _IPAddress
End Get
Set(ByVal value As String)
_IPAddress = value
End Set
End Property
Public Property SwitchName() As String
Get
Return _SwitchName
End Get
Set(ByVal value As String)
_SwitchName = value
End Set
End Property
Public Property ID() As Integer
Get
Return _ID
End Get
Set(ByVal value As Integer)
_ID = value
End Set
End Property
Public Property Result() As Boolean
Get
Return _Result
End Get
Set(ByVal value As Boolean)
_Result = value
End Set
End Property
End Class
'Set up some variables that we will use from various functions/subs
Private PingList As List(Of NetworkSwitch)
Private Counter As Integer = 0
Private ConnString As New OleDbConnectionStringBuilder("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\test\pingDB.mdb;User Id=admin;Password=;")
'This is the Delegate that will be used to pass data between the threads safely
Private Delegate Sub PingComplete(ByVal sw As NetworkSwitch)
Private Sub Pingbtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Pingbtn.Click
Counter = 0 'reset the counter in case this is not the first time the ping button has been clicked
Pingbtn.Enabled = False 'Disable the ping button so it cannot be pressed again yet
btnExit.Enabled = False
Dim bgthread As New Threading.Thread(AddressOf BG_CollectData) 'Create a new background thread
bgthread.IsBackground = True 'Make the thread end if the program is closed
bgthread.Start() 'Start the background thread
End Sub
''' <summary>
''' This is the routine that is executed when bgthread.Start() is called in the event handler above
''' It collects information from the Access database and stores it in a list, then kicks off another
''' background thread (from the ThreadPool) that sends the ping
''' </summary>
Private Sub BG_CollectData()
'Create our connection that will be used to connect to the Access database
Dim AccessConnection As New OleDbConnection(ConnString.ConnectionString)
'Create the command that will be used to select all of the data in the IP and ID columns
Dim SelectCommand As New OleDbCommand("SELECT * FROM PingTable", AccessConnection)
'Create a new instance of a list of our NetworkSwitch class
PingList = New List(Of NetworkSwitch)
'Open the connection to the database
AccessConnection.Open()
'Use a DataReader to access the data that the SELECT command returns
Dim Reader As OleDbDataReader = SelectCommand.ExecuteReader
'Start to loop through the results
'This loop will be restarted for each row in the database
Do While Reader.Read
'Create a new instance of our NetworkSwitch class and populate the ID and IP properties
'with data from the current row in the database that we are looping through
Dim CurrentSwitch As New NetworkSwitch
With CurrentSwitch
.ID = Reader("ID")
.SwitchName = Reader("SwitchName")
.IPAddress = Reader("IPAddress")
End With
'Add the new instance of the NetworkSwitch to our list
PingList.Add(CurrentSwitch)
Loop 'Start the loop again for the next record in the database
'Close the connection because we have now processed all rows in the database
AccessConnection.Close()
'Give the threadpool a limit so that no more than 30 threads are running at the same time
Threading.ThreadPool.SetMaxThreads(30, 400)
'Loop through our list of NetworkSwitch instances and start (well, queue up) a new background
'thread for each item in the list and passes it the current item in the loop (which is a NetworkSwitch object)
For Each switchobject As NetworkSwitch In PingList
Threading.ThreadPool.QueueUserWorkItem(New Threading.WaitCallback(AddressOf DoPing), switchobject)
Next
End Sub
''' <summary>
''' Performs the ping and updates the Result property of the NetworkSwitch object that was passed to this
''' </summary>
Private Sub DoPing(ByVal Switch As NetworkSwitch)
Dim Result As Net.NetworkInformation.PingReply
Dim SendPing As New Net.NetworkInformation.Ping
Result = SendPing.Send(Switch.IPAddress)
If Result.Status = Net.NetworkInformation.IPStatus.Success Then
Switch.Result = True
' <<<<<<----change Font Color to green/red ??
Else
Switch.Result = False
End If
UpdateDatabase(Switch)
Counter += 1
Me.Invoke(New PingComplete(AddressOf UI_PingComplete), Switch)
End Sub
''' <summary>
''' This is executed each time a ping completes and the database has been updated.
''' It is executed on the UI thread because we used Me.Invoke to call it so it can access
''' controls on the UI thread without a problem
''' </summary>
Private Sub UI_PingComplete(ByVal sw As NetworkSwitch)
logbox.AppendText(sw.SwitchName & " - " & sw.IPAddress & " - ping complete - " & sw.Result & vbNewLine) 'update our log textbox
If Counter = PingList.Count Then
logbox.AppendText("Finished all tests" & vbNewLine)
Pingbtn.Enabled = True 're-enable the ping button
btnExit.Enabled = True
PingList = Nothing 'clean up
End If
End Sub
''' <summary>
''' Updates the relevant row in the database for the switch that is passed to this method
''' </summary>
Private Sub UpdateDatabase(ByVal sw As NetworkSwitch)
Dim AccessConnection As New OleDbConnection(ConnString.ConnectionString)
Dim UpdateCommand As New OleDbCommand("UPDATE PingTable SET Result=@Result, LastTested=@CurrentTime WHERE ID=@ID", AccessConnection)
With UpdateCommand.Parameters
.Add("@Result", OleDbType.Boolean).Value = sw.Result
.Add("@CurrentTime", OleDbType.Char).Value = Now.ToString
.Add("@ID", OleDbType.Integer).Value = sw.ID
' .Add("SwitchName", OleDbType.Char).Value = sw.SwitchName
End With
AccessConnection.Open()
UpdateCommand.ExecuteNonQuery() 'Execute the command that updates the database
AccessConnection.Close()
End Sub
Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExit.Click
End
End Sub
End Class
Last edited by markhorgan1; Aug 12th, 2009 at 08:46 AM.
OK I've attached an example project that uses a datagridview and I have attached the database. It is by no means perfect and you should add plenty of error handling etc as I have merely added enough to make it functional.
The way I have done it now is quite different in that you click the Reload button and it loads each row from the Access database into the DGV, then when you do the pings it actually just reads the data from the DGV and updates the DGV (but still updates the Access database as well with the results). Its probably not the best way to do it, especially as you would have to make sure you do the Reload after any changes are made to the database, but it works and at least gives you something to go on.
This is what it looks like:
I've also attached a WPF version for anyone who is interested, which uses data binding (because I find it much easier to do databinding in WPF) so doesnt require quite as much code - of course it also has the advantage of being a lot more visually flexible. For example, you can click the Change View button to switch from this view:
to this view:
Obviously just a very basic example but you get the idea
Note that I have changed quite a few things in the code compared to that example project I gave you before. For example the LastTested column is now a Date column not a text column and as a result when the app is loading the data into the DGV it will display something like 01/01/0001 00:00:00 as the last tested date if there is no value in that column. You could stick some extra If statements in there to 'convert' it from that date into a string that just says "Never" or something and then do the opposite when reading the data from the DGV but I havent bothered as its just an example.
Read the comments in the code and feel free to ask any questions - also just to clarify, this is not meant to be a working program that you can just start using (although it does work), its more to help you see how you can do things. As I said though, there is probably a better way of doing things, its just my own example
Last edited by chris128; Aug 12th, 2009 at 05:03 PM.
thanks chris , one more thing im trying to open this program using another vb program as in have a command button in another vb app open up the pinging application but , from what i gather shell is the way to go
ive tried the following:
Code:
Private Sub Ping_Click()
Shell "C:\Documents and Settings\mhorgan\Desktop\example ping\ExamplePingProgram\ExamplePingProgram"
End Sub
but no luck, is it maybe the space in between the documents_and_settings in the directory ? or am i way off here ? or aproblem with a missing file extension ?
Last edited by markhorgan1; Aug 14th, 2009 at 08:38 AM.
Imports System.Data.OleDb
Public Class Form1
''' <summary>
''' Represents a network switch (or any device with an IP) that is in the database
''' </summary>
Private Class NetworkSwitch
Private _IPAddress As String
Private _SwitchID As Integer
Private _SwitchName As String
Private _Result As Boolean
Public Property IPAddress() As String
Get
Return _IPAddress
End Get
Set(ByVal value As String)
_IPAddress = value
End Set
End Property
Public Property SwitchName() As String
Get
Return _SwitchName
End Get
Set(ByVal value As String)
_SwitchName = value
End Set
End Property
Public Property SwitchID() As Integer
Get
Return _SwitchID
End Get
Set(ByVal value As Integer)
_SwitchID = value
End Set
End Property
Public Property Result() As Boolean
Get
Return _Result
End Get
Set(ByVal value As Boolean)
_Result = value
End Set
End Property
End Class
'Set up some variables that we will use from various functions/subs
Private PingList As List(Of NetworkSwitch)
Private Counter As Integer = 0
Private ConnString As New OleDbConnectionStringBuilder("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Documents and Settings\mhorgan\Desktop\Network Map.mdb;User Id=admin;Password=;")
'This is the Delegate that will be used to pass data between the threads safely
Private Delegate Sub PingComplete(ByVal sw As NetworkSwitch)
Private Sub Pingbtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Pingbtn.Click
Label1.Visible = True
Counter = 0 'reset the counter in case this is not the first time the ping button has been clicked
Pingbtn.Enabled = False 'Disable the ping button so it cannot be pressed again yet
btnExit.Enabled = False
btnMap.Enabled = False
btnDB.Enabled = False
Dim bgthread As New Threading.Thread(AddressOf BG_CollectData) 'Create a new background thread
bgthread.IsBackground = True 'Make the thread end if the program is closed
bgthread.Start() 'Start the background thread
End Sub
''' <summary>
''' This is the routine that is executed when bgthread.Start() is called in the event handler above
''' It collects information from the Access database and stores it in a list, then kicks off another
''' background thread (from the ThreadPool) that sends the ping
''' </summary>
Private Sub BG_CollectData()
'Create our connection that will be used to connect to the Access database
Dim AccessConnection As New OleDbConnection(ConnString.ConnectionString)
'Create the command that will be used to select all of the data in the IP and ID columns
Dim SelectCommand As New OleDbCommand("SELECT * FROM tblSwitch", AccessConnection)
'Create a new instance of a list of our NetworkSwitch class
PingList = New List(Of NetworkSwitch)
'Open the connection to the database
AccessConnection.Open()
'Use a DataReader to access the data that the SELECT command returns
Dim Reader As OleDbDataReader = SelectCommand.ExecuteReader
'Start to loop through the results
'This loop will be restarted for each row in the database
Do While Reader.Read
'Create a new instance of our NetworkSwitch class and populate the ID and IP properties
'with data from the current row in the database that we are looping through
Dim CurrentSwitch As New NetworkSwitch
With CurrentSwitch
.SwitchID = Reader("SwitchID")
.SwitchName = Reader("SwitchName")
.IPAddress = Reader("IPAddress")
End With
'Add the new instance of the NetworkSwitch to our list
PingList.Add(CurrentSwitch)
Loop 'Start the loop again for the next record in the database
'Close the connection because we have now processed all rows in the database
AccessConnection.Close()
'Give the threadpool a limit so that no more than 30 threads are running at the same time
Threading.ThreadPool.SetMaxThreads(30, 400)
'Loop through our list of NetworkSwitch instances and start (well, queue up) a new background
'thread for each item in the list and passes it the current item in the loop (which is a NetworkSwitch object)
For Each switchobject As NetworkSwitch In PingList
Threading.ThreadPool.QueueUserWorkItem(New Threading.WaitCallback(AddressOf DoPing), switchobject)
Next
End Sub
''' <summary>
''' Performs the ping and updates the Result property of the NetworkSwitch object that was passed to this
''' </summary>
Private Sub DoPing(ByVal Switch As NetworkSwitch)
Dim Result As Net.NetworkInformation.PingReply
Dim SendPing As New Net.NetworkInformation.Ping
Result = SendPing.Send(Switch.IPAddress)
If Result.Status = Net.NetworkInformation.IPStatus.Success Then
Switch.Result = True
Else
Switch.Result = False
End If
UpdateDatabase(Switch)
Counter += 1
Me.Invoke(New PingComplete(AddressOf UI_PingComplete), Switch)
End Sub
''' <summary>
''' This is executed each time a ping completes and the database has been updated.
''' It is executed on the UI thread because we used Me.Invoke to call it so it can access
''' controls on the UI thread without a problem
''' </summary>
Private Sub UI_PingComplete(ByVal sw As NetworkSwitch)
If sw.Result = True Then
logbox.SelectionColor = Color.DarkBlue
ElseIf sw.Result = False Then
logbox.SelectionColor = Color.Red
End If
logbox.AppendText(sw.SwitchID & "--" & sw.SwitchName & " -- " & sw.IPAddress & " -- ping complete -- " & sw.Result & vbNewLine) 'update our log textbox
If Counter = PingList.Count Then
logbox.AppendText(vbNewLine & vbNewLine & "Finished all tests" & vbNewLine)
Pingbtn.Enabled = True 're-enable the ping button
btnExit.Enabled = True
btnMap.Enabled = True
btnDB.Enabled = True
PingList = Nothing 'clean up
End If
End Sub
''' <summary>
''' Updates the relevant row in the database for the switch that is passed to this method
''' </summary>
Private Sub UpdateDatabase(ByVal sw As NetworkSwitch)
Dim AccessConnection As New OleDbConnection(ConnString.ConnectionString)
Dim UpdateCommand As New OleDbCommand("UPDATE tblSwitch SET Result=@Result, LastTested=@CurrentTime WHERE SwitchID=@SwitchID", AccessConnection)
With UpdateCommand.Parameters
.Add("@Result", OleDbType.Boolean).Value = sw.Result
.Add("@CurrentTime", OleDbType.Char).Value = Now.ToString
.Add("@SwitchID", OleDbType.Integer).Value = sw.SwitchID
End With
AccessConnection.Open()
UpdateCommand.ExecuteNonQuery() 'Execute the command that updates the database
AccessConnection.Close()
End Sub
Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExit.Click
End ' closes application
End Sub
Private Sub btnMap_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMap.Click
Process.Start("C:\Documents and Settings\mhorgan\Desktop\NewEffort.vsd") ' opens Network Map
End Sub
Private Sub btnDB_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDB.Click
Process.Start("C:\Documents and Settings\mhorgan\Desktop\Network Map.mdb") 'opens AccessDB
End Sub
End Class