unable to parse value of selected item in a listview object - vb.net

OK my dilemma is the following, whenever i try to parse a selected item in a listview object it will not pass that value to a function, i know if i use .text or .tostring it will work fine parsing the selected item, but the parsed item will be used as a socket connection, an example of a value selected 127.0.0.1:5688 and for ended the error string cannot be converted to system.net.socket.sockets is trigger when debugging the app if i use listview1.items.item(I).text or tostring
Here is the problematic part
For I As Integer = 0 To ListView1.Items.Count - 1
If ListView1.Items(I).selected = True Then
send(RichTextBox2.Text & vbNewLine, ListView1.Items.Item(I).Tag)
End If
Next
and here is the function where the parsed value is supposed to be passed along
Private Sub Send(ByVal msg As String, ByVal client As Socket)
Dim sendBytes As Byte() = System.Text.ASCIIEncoding.ASCII.GetBytes(msg)
client.BeginSend(sendBytes, 0, sendBytes.Length, SocketFlags.None, New AsyncCallback(AddressOf OnSend), client)
End Sub

Related

Ping multiple device names (hostname) on the Network

A DataGridView displays hostnames at Column index 0, computer / printer names on the network.
pc1
pc2
print3
pc5
print
....
There are more than 500 such names.
I know how to ping them:
For i = 0 To DataGridView1.Rows.Count - 1
Try
If My.Computer.Network.Ping(DataGridView1.Item(0, i).Value) = True Then
DataGridView1.Rows(i).DefaultCellStyle.BackColor = Color.Lime
Else
DataGridView1.Rows(i).DefaultCellStyle.BackColor = Color.Red
End If
Catch ex As Exception
DataGridView1.Rows(i).DefaultCellStyle.BackColor = Color.Red
End Try
Next
The problem is that the Ping takes a very long time and the application freezes.
How can you speed up this procedure?
And let's say if the node is not available, then simply remove it from the list.
An example to Ping multiple addresses at the same time, using the async version of provided by the Ping class, Ping.SendPingAsync().
This version is await-able, not the same as the Ping.SendAsync() method, still asynchronous but event-driven.
Since you're using a DataGridView to both store the IpAddress/HostName and to present the PingReply results, you need to determine a way to match the Ping result to correct Cell of the DataGridView from which the Ip/Host address was taken.
Here, I'm passing to the method the Row's Index, so when the Ping result comes back, asynchronously, we can match the response to a specific Cell in the DataGridView.
To make the initialization method more generic, I'm passing also the index of the Column where the Ip/Host address is stored and the index of the Column that will show the result (you could also just pass all indexes, not a DataGridView Control reference to the method and handle the results in a different way).
A loop extracts the addresses from the the DataGridView and creates a List(Of Task), adding a PingAsync() Task for each address found.
When the collection is completed, the List(Of Task) is passed to the Task.WhenAll() method, which is then awaited.
This method starts all the Task in the list and returns when all Task have a result.
► Note that the Ping procedure sets a TimeOut, to 5000ms here, so all the Tasks will return before or within that interval, successful or not.
You can then decide if you want to reschedule the failed Pings or not.
The UI update is handled using a Progress delegate. It's just a method (Action delegate) that is called when the Ping procedure has a result to show.
It can also be used when the method that updates the UI runs in a different Thread: the Report() method will call the Progress object delegate in the Thread that created the delegate: the UI Thread, here (in the example, we're not actually ever leaving it, though).
This is how it works:
Assume you're starting the ping sequence from Button.Click event handler.
Note that the handler is declared async.
Private Async Sub btnMassPing_Click(sender As Object, e As EventArgs) Handles btnMassPing.Click
Await MassPing(DataGridView1, 1, 2)
End Sub
Initialization method and IProgress<T> report handler:
Imports System.Drawing
Imports System.Net.NetworkInformation
Imports System.Net.Sockets
Imports System.Threading.Tasks
Private Async Function MassPing(dgv As DataGridView, statusColumn As Integer, addressColumn As Integer) As Task
Dim obj = New Object()
Dim tasks = New List(Of Task)()
Dim progress = New Progress(Of (sequence As Integer, reply As Object))(
Sub(report)
SyncLock obj
Dim status = IPStatus.Unknown
If TypeOf report.reply Is PingReply Then
status = DirectCast(report.reply, PingReply).Status
ElseIf TypeOf report.reply Is SocketError Then
Dim socErr = DirectCast(report.reply, SocketError)
status = If(socErr = SocketError.HostNotFound,
IPStatus.DestinationHostUnreachable,
IPStatus.Unknown)
End If
Dim color As Color = If(status = IPStatus.Success, Color.Green, Color.Red)
Dim cell = dgv(statusColumn, report.sequence)
cell.Style.BackColor = color
cell.Value = If(status = IPStatus.Success, "Online", status.ToString())
End SyncLock
End Sub)
For row As Integer = 0 To dgv.Rows.Count - 1
If row = dgv.NewRowIndex Then Continue For
Dim ipAddr = dgv(addressColumn, row).Value.ToString()
tasks.Add(PingAsync(ipAddr, 5000, row, progress))
Next
Try
Await Task.WhenAll(tasks)
Catch ex As Exception
' Log / report the exception
Console.WriteLine(ex.Message)
End Try
End Function
PingAsync worker method:
Private Async Function PingAsync(ipAddress As String, timeOut As Integer, sequence As Integer, progress As IProgress(Of (seq As Integer, reply As Object))) As Task
Dim buffer As Byte() = New Byte(32) {}
Dim ping = New Ping()
Try
Dim options = New PingOptions(64, True)
Dim reply = Await ping.SendPingAsync(ipAddress, timeOut, buffer, options)
progress.Report((sequence, reply))
Catch pex As PingException
If TypeOf pex.InnerException Is SocketException Then
Dim socEx = DirectCast(pex.InnerException, SocketException)
progress.Report((sequence, socEx.SocketErrorCode))
End If
Finally
ping.Dispose()
End Try
End Function

visual basic .NET get user input without pressing enter

I know of the existence of the code character = System.Console.ReadKey().tostring.
This will read one character.
Also in another stack overflow post I found:
Public Shared Function ReadPipedInfo() As StreamReader
'call with a default value of 5 milliseconds
Return ReadPipedInfo(5000)
End Function
Public Shared Function ReadPipedInfo(waitTimeInMilliseconds As Integer) As StreamReader
'allocate the class we're going to callback to
Dim callbackClass As New ReadPipedInfoCallback()
'to indicate read complete or timeout
Dim readCompleteEvent As New AutoResetEvent(False)
'open the StdIn so that we can read against it asynchronously
Dim stdIn As Stream = Console.OpenStandardInput()
'allocate a one-byte buffer, we're going to read off the stream one byte at a time
Dim singleByteBuffer As Byte() = New Byte(0) {}
'allocate a list of an arbitary size to store the read bytes
Dim byteStorage As New List(Of Byte)(4096)
Dim asyncRead As IAsyncResult = Nothing
Dim readLength As Integer = 0
'the bytes we have successfully read
Do
'perform the read and wait until it finishes, unless it's already finished
asyncRead = stdIn.BeginRead(singleByteBuffer, 0, singleByteBuffer.Length, New AsyncCallback(AddressOf callbackClass.ReadCallback), readCompleteEvent)
If Not asyncRead.CompletedSynchronously Then
readCompleteEvent.WaitOne(waitTimeInMilliseconds)
End If
'end the async call, one way or another
'if our read succeeded we store the byte we read
If asyncRead.IsCompleted Then
readLength = stdIn.EndRead(asyncRead)
'If readLength > 0 Then
byteStorage.Add(singleByteBuffer(0))
'End If
End If
Loop While asyncRead.IsCompleted AndAlso readLength > 0
'we keep reading until we fail or read nothing
'return results, if we read zero bytes the buffer will return empty
Return New StreamReader(New MemoryStream(byteStorage.ToArray(), 0, byteStorage.Count))
End Function
Private Class ReadPipedInfoCallback
Public Sub ReadCallback(asyncResult As IAsyncResult)
'pull the user-defined variable and strobe the event, the read finished successfully
Dim readCompleteEvent As AutoResetEvent = TryCast(asyncResult.AsyncState, AutoResetEvent)
readCompleteEvent.[Set]()
End Sub
End Class
which reads input if the user pressed enter
how could I make some code that reads (multiple) character(s) without letting the user press enter all the time? But instead use time as the indicator to stop reading the console?
You can use System.Console.Read() here. It reads as character from standard input stream. https://msdn.microsoft.com/en-us/library/system.console.read(v=vs.110).aspx
According to here I found out how to deal with it:
Public Module ConsoleHelper
Sub Main()
msgbox(ReadKeyWithTimeOut(10000).key.ToString)
End Sub
Public Function ReadKeyWithTimeOut(timeOutMS As Integer) As ConsoleKeyInfo
Dim timeoutvalue As DateTime = DateTime.Now.AddMilliseconds(timeOutMS)
While DateTime.Now < timeoutvalue
If Console.KeyAvailable Then
Dim cki As ConsoleKeyInfo = Console.ReadKey()
Return cki
Else
System.Threading.Thread.Sleep(100)
End If
End While
Return New ConsoleKeyInfo(" "C, ConsoleKey.Spacebar, False, False, False)
End Function
End Module
Now just finding out how to give attribute key NULL or something if it timed out.

Pass Dynamic connection string to another Windows Form (VB.NET)

I am creating a windows application which required Dynamic Connection String in the app starting (user need to provide db credentials through a form), After entering the connection credentials user redirected to new win form
Everything is working fine but how can I pass my dynamic connection to another form.
I tried to save it to App variable but I couldn't (I think its read only)
Also I tried save it to registry but can't retrieve values.
Is there any other option available ? like writing & retrieving ConString to a text file or XML
Thanks
This how you can get and set registry values :
Public Function GetRegistryValue(ByVal KeyName As String, Optional ByVal DefaultValue As Object = Nothing) As Object
Dim res As Object = Nothing
Try
Dim k = My.Computer.Registry.CurrentUser.OpenSubKey("Software\YourAppName", True)
If k IsNot Nothing Then
res = k.GetValue(KeyName, DefaultValue)
Else
k = My.Computer.Registry.CurrentUser.CreateSubKey("Software\YourAppName")
End If
If k IsNot Nothing Then k.Close()
Catch ' ex As Exception
'PromptMsg(ex)
End Try
Return res
End Function
Public Sub SetRegistryValue(ByVal KeyName As String, ByVal _Value As Object)
Try
Dim k = My.Computer.Registry.CurrentUser.OpenSubKey("Software\YourAppName", True)
If k IsNot Nothing Then
k.SetValue(KeyName, _Value)
Else
k = My.Computer.Registry.CurrentUser.CreateSubKey("Software\YourAppName")
k.SetValue(KeyName, _Value)
End If
If k IsNot Nothing Then k.Close()
Catch ' ex As Exception
'PromptMsg(ex)
End Try
End Sub
It's working a 100%, If you please mark this answer as Right

Strange error reported in this code, please explain?

I put together this bit of code from a few other samples, and I am getting an error I cant understand. On this line in the code below, on the word Observer,
Dim Results As ManagementObjectCollection = Worker.Get(Observer)
I get the error
"Value of type 'System.Management.ManagementOperationObserver' cannot be converted to 'Integer'"
Can somebody explain what this means?
There are two signatures for ManagementObjectSearcher.Get(), one has no parameters and the other has one parameter, a ManagementOperationObserver for async operation. That is what I am providing, yet the error indicates conversion involving an integer?
Public Shared Sub WMIDriveDetectionASYNC(ByVal args As String())
Dim Observer As New ManagementOperationObserver()
Dim completionHandler As New MyHandler()
AddHandler Observer.Completed, AddressOf completionHandler.Done
Dim Machine = "192.168.0.15"
Dim Scope = New ManagementScope("\\" & Machine & "\root\cimv2")
Dim QueryString = "select Name, Size, FreeSpace from Win32_LogicalDisk where DriveType=3"
Dim Query = New ObjectQuery(QueryString)
Dim Worker = New ManagementObjectSearcher(Scope, Query)
Dim Results As ManagementObjectCollection = Worker.Get(Observer) 'use parameter to make async
For Each item As ManagementObject In Results
Console.WriteLine("{0} {2} {1}", item("Name"), item("FreeSpace"), item("Size"))
Dim FullSpace As Long = (CLng(item("Size")) - CLng(item("FreeSpace"))) \ 1000000
Console.WriteLine(FullSpace)
Next
End Sub
Public Class MyHandler
Private _isComplete As Boolean = False
Public Sub Done(sender As Object, e As CompletedEventArgs)
_isComplete = True
End Sub 'Done
Public ReadOnly Property IsComplete() As Boolean
Get
Return _isComplete
End Get
End Property
End Class
Thanks for any advice!
I think that uses a reference type to get the result and put it in the object you sent as a parameter. So I think it just needs to look like:
Worker.Get(Observer)
instead of trying to set something = to that since it isn't a function that returns a value.
Then use the events you hook up to the object to handle whatever you need to do with the items you find.

Error In VB.Net code

I am getting the error "Format Exception was unhandled at "Do While objectReader.Peek <> -1
" and after. any help would be wonderful.
'Date: Class 03/20/2010
'Program Purpose: When code is executed data will be pulled from a text file
'that contains the named storms to find the average number of storms during the time
'period chosen by the user and to find the most active year. between the range of
'years 1990 and 2008
Option Strict On
Public Class frmHurricane
Private _intNumberOfHuricanes As Integer = 5
Public Shared _intSizeOfArray As Integer = 7
Public Shared _strHuricaneList(_intSizeOfArray) As String
Private _strID(_intSizeOfArray) As String
Private _decYears(_intSizeOfArray) As Decimal
Private _decFinal(_intSizeOfArray) As Decimal
Private _intNumber(_intSizeOfArray) As Integer
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'The frmHurricane load event reads the Hurricane text file and
'fill the combotBox object with the data.
'Initialize an instance of the StreamReader Object and declare variable page 675 on the book
Dim objectReader As IO.StreamReader
Dim strLocationAndNameOfFile As String = "C:\huricanes.txt"
Dim intCount As Integer = 0
Dim intFill As Integer
Dim strFileError As String = "The file is not available. Please restart application when available"
'This is where we code the file if it exist.
If IO.File.Exists(strLocationAndNameOfFile) Then
objectReader = IO.File.OpenText(strLocationAndNameOfFile)
'Read the file line by line until the file is complete
Do While objectReader.Peek <> -1
**_strHuricaneList(intCount) = objectReader.ReadLine()
_strID(intCount) = objectReader.ReadLine()
_decYears(intCount) = Convert.ToDecimal(objectReader.ReadLine())
_intNumber(intCount) = Convert.ToInt32(objectReader.ReadLine())
intCount += 1**
Loop
objectReader.Close()
'With any luck the data will go to the Data Box
For intFill = 0 To (_strID.Length - 1)
Me.cboByYear.Items.Add(_strID(intFill))
Next
Else
MsgBox(strFileError, , "Error")
Me.Close()
End If
End Sub
Put a break-point on these lines and step through your code:
_decYears(intCount) = Convert.ToDecimal(objectReader.ReadLine())
_intNumber(intCount) = Convert.ToInt32(objectReader.ReadLine())
Whatever is being returned by ReadLine isn't in the proper decimal or integer format when passed to the converters. You'll need to add some try/catch blocks around the do-while loop operations to handle it gracefully and make sure your data is formatted the way you expected since the wrong parts are being used in this scenario.
Also, each call to ReadLine is returning an entirely new line and the Peek check won't account for those. As long as you can trust your data that's fine.
Instead of using Convert.ToDecimal an Convert.ToInt32, try using Decimal.TryParse() and Int32.TryParse(). If they don't parse, you know your file isn't setup correctly. If they do parse, then you've loaded the value into a variable for your use.
EDIT:
Use it like this.
Dim myDecimal As Decimal
If Decimal.TryParse(objectReader.ReadLine(), myDecimal) Then
'your string successfully parsed. Use myDecimal however you want. It has the parsed value.
Else
'your string is not a decimal. Now that you know that, you can handle this situation here without having to catch an exception.
End If