Speed up search file using Multithreading or Parallel.ForEach - vb.net

I wrote a code to search for files and folders and (to check all possible combinations of inserted words) I have a sub that gives all permutations of the inserted strings.
My problem is that I'm repeating the code for every permutated string (for 4 words it means 24 times) and I'm trying to use MultiThreading to speed up the code.
I've read a lot of examples but I wasn't able to really understand the logic for many reasons (some examples were in C; any example was wrote with different logic)
I've tried with
Parallel.For
Parallel.ForEach
ThreadPool
but I wasn't able to wait all threads before setting the List (containig all results) as datasource of a listbox.
My code logic is:
Get words by splitting the search string
If search type is "all words in any order" then I get all permutations
I start searching for each of permutated strings
I don't like to add too much code to a question but I think it's necessary in this case to know how I'm working:
Private Sub Btn_Search_Click(sender As Object, e As EventArgs) Handles Btn_Search.Click
Select Case True
Case RBtn_Exact.Checked
StartSearch(Me.TB_Pattern.Text.Trim)
Case RBtn_AllInOrder.Checked
Dim Pattern As String = ""
For Each Word As String In Me.TB_Pattern.Text.Split(New Char() {" "c})
If Word.Trim <> "" Then Pattern &= "*" & Word.Trim
Next
Pattern &= "*"
StartSearch(Pattern)
endsearch()
Case RBtn_AllWithoutOrder.Checked
Dim WordHash As New HashSet(Of String)
For Each Word As String In Split(Me.TB_Pattern.Text, " ")
If Word.Trim <> "" Then WordHash.Add(Word.Trim)
Next
If WordHash.Count > 5 Then
MessageBox.Show("Max 5 words allowed for this kind of search", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Exit Sub
End If
'Get permutations into an array
StringPermutations()
'I need to add "*" at the end of each permutated string
For S As Integer = 0 To PermutationsArr.Length - 1
PermutationsArr(S) &= "*"
Next
'This is for searching without MultiThreading
For Each Pattern As String In PermutationsArr
StartSearch(Pattern)
Next
'This is my last test
'Parallel.ForEach(PermutationsArr,
' Sub(Pattern)
' StartSearch(Pattern)
' End Sub
' )
'Task.WaitAll()
endsearch()
Case RBtn_AnyWord.Checked
Dim WordHash As New HashSet(Of String)
For Each Word As String In Split(Me.TB_Pattern.Text, " ")
If Word.Trim <> "" Then WordHash.Add(Word.Trim)
Next
If WordHash.Count > 5 Then
MessageBox.Show("Max 5 words allowed for this kind of search", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Exit Sub
End If
For Each Word As String In WordHash
StartSearch(pattern:="*" & Word & "*")
Next
endsearch()
End Select
End Sub
Private Sub StartSearch(ByVal pattern As String)
'Search for files
If Me.CBox_Files.Checked Then
FileSearch(Me.TB_StartFolder.Text, pattern)
End If
'Search for folders
If Me.CBox_Folders.Checked Then
ProcessDir(Me.TB_StartFolder.Text, pattern)
DirSearch(Me.TB_StartFolder.Text, pattern)
End If
End Sub
Sub endsearch()
Me.Btn_Search.Text = "Start"
Me.Btn_Search.BackColor = Me.BackColor
If Me.LB_Files.Items.Count > 0 Then
Me.Lbl_FilesFound.Text = Me.LB_Files.Items.Count.ToString
Me.Lbl_FilesFound.Visible = True
End If
If Me.LB_Folders.Items.Count > 0 Then
Me.Lbl_DirFound.Text = Me.LB_Folders.Items.Count.ToString
Me.Lbl_DirFound.Visible = True
End If
End Sub
Sub DirSearch(ByVal sDir As String, ByVal Pattern As String)
Try
For Each Dir As String In Directory.GetDirectories(sDir)
Try
For Each D As String In Directory.GetDirectories(Dir, Pattern)
Try
If LimitReached(LB_Folders) Then
Me.Lbl_LimitReached.Visible = True
Exit Sub
Else
If Me.CBox_Folders.Checked AndAlso Not LB_Folders.Items.Contains(D) Then LB_Folders.Items.Add(D)
End If
Catch ex As Exception
Continue For
End Try
Next
DirSearch(Dir, Pattern)
Catch ex As Exception
Continue For
End Try
Next
Catch ex As Exception
End Try
End Sub
Sub FileSearch(ByVal sDir As String, ByVal Pattern As String)
Dim d As String = ""
Try
For Each f As String In Directory.GetFiles(sDir, Pattern)
Try
If LimitReached(LB_Files) Then
Me.Lbl_LimitReached.Visible = True
Exit Sub
Else
If Me.CBox_LastModRange.Checked Then
If Me.CBox_Files.Checked AndAlso IntoRangeDate(f) AndAlso Not LB_Files.Items.Contains(f) Then LB_Files.Items.Add(f)
Else
If Me.CBox_Files.Checked AndAlso Not LB_Files.Items.Contains(f) Then LB_Files.Items.Add(f)
End If
End If
Catch ex As Exception
Continue For
End Try
Next
'Search for subfolders
For Each d In Directory.GetDirectories(sDir)
Try
ProcessDir(d, Pattern)
Catch ex As Exception
End Try
Try
FileSearch(d, Pattern)
Catch ex As Exception
End Try
Next
Catch excpt As System.Exception
End Try
End Sub
Private Sub ProcessDir(d As String, ByVal Pattern As String)
Try
For Each f As String In Directory.GetFiles(d, Pattern)
Try
If LimitReached(LB_Files) Then
Me.Lbl_LimitReached.Visible = True
Exit Sub
Else
If Me.CBox_LastModRange.Checked Then
If Me.CBox_Files.Checked AndAlso IntoRangeDate(f) AndAlso Not LB_Files.Items.Contains(f) Then LB_Files.Items.Add(f)
Else
If Me.CBox_Files.Checked AndAlso Not LB_Files.Items.Contains(f) Then LB_Files.Items.Add(f)
End If
End If
Catch ex As Exception
Continue For
End Try
Next
Catch ex As System.Exception
End Try
Try
For Each d In Directory.GetDirectories(d, Pattern)
Try
If Me.CBox_Folders.Checked AndAlso Not LB_Folders.Items.Contains(d) Then LB_Folders.Items.Add(d)
Catch ex As Exception
Continue For
End Try
Next
Catch ex As Exception
End Try
End Sub
EDIT
Below my code for getting permutations (I know it has a particular logic but it works and it seems enough fast):
Private Sub StringPermutations()
Try
Dim WordHash As New HashSet(Of String)
For Each Word As String In Split(Me.TB_Pattern.Text, " ")
If Word.Trim <> "" Then WordHash.Add(Word.Trim)
Next
Dim WordList As List(Of String) = WordHash.ToList
ReDim PermutationsArr(Factorial(WordList.Count) - 1)
AddString(WordList, 0)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Private Function Factorial(ByVal Num As Integer) As Integer
Try
If Num > 0 AndAlso Num < 12 Then
Dim Result As Int32 = 1
Do
Result *= Num
Num -= 1
Loop Until Num <= 1
Return Result
Else
Return 0
End If
Catch ex As Exception
Return Nothing
End Try
End Function
Private Sub AddString(ByVal WordList As List(Of String), ByVal StartId As Integer)
Try
Dim InsLoop As Integer = Factorial(WordList.Count - 1)
If InsLoop = 0 Then InsLoop = 1
For Each Word As String In WordList
For InsWord As Integer = 1 To InsLoop
PermutationsArr(StartId + InsWord - 1) &= "*" & Word
Next
If WordList.Count > 1 Then
Dim Remaining As New List(Of String)
For Each RemWord As String In WordList
If RemWord <> Word Then Remaining.Add(RemWord)
Next
AddString(Remaining, StartId)
End If
StartId += InsLoop
Next
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub

Here's my Form class, based on yours but substantially simplified. I used Tasks for multithreading, ConcurrentDictionarys to capture the results with capacity limits, concurrency levels, and without duplicates, and populate the Listboxes in one call at the end to minimize UI updates and the associated slowness. Concurrency level is the number of tasks that will be spawned to feed the ConcurrentDictionary.
Imports System.Text.RegularExpressions
Public Class SearchForm
Private FoldersList As Concurrent.ConcurrentDictionary(Of String, Object)
Private FilesList As Concurrent.ConcurrentDictionary(Of String, Object)
Private Tasks As New List(Of Task)
Private Words As New List(Of String)
Private StopWatch As New Stopwatch
' Capacity of the ConcurrentDictionary objects
' Set this from user input on form to limit # of results returned
Private Capacity As Int32 = 0
Private PermutationsArr() As String = Nothing
Private Sub Btn_Search_Click(sender As Object, e As EventArgs) Handles Btn_Search.Click
Btn_Search.Text = "Wait"
' Capacity of the ConcurrentDictionary objects
' Set this from user input on form to limit # of results returned
Capacity = 10000
Tasks.Clear()
Words.Clear()
LB_Folders.DataSource = Nothing
LB_Files.DataSource = Nothing
Me.Refresh()
StopWatch.Restart()
Words.AddRange(Regex.Split(Regex.Replace(Me.TB_Pattern.Text.Trim, "\*", String.Empty), "\s+"))
Select Case True
Case String.IsNullOrWhiteSpace(Me.TB_Pattern.Text.Trim)
MsgBox("Too few words", vbOKOnly, "Oops")
Case Words.Count < 1
MsgBox("Too few words", vbOKOnly, "Oops")
Case Words.Count > 5
MsgBox("Too many words", vbOKOnly, "Oops")
Case Me.CBox_LastModRange.Checked AndAlso Me.DT_ModRangeEnd.Value < Me.DT_ModRangeStart.Value
MsgBox("Range Start must precede Range End", vbOKOnly, "Oops")
Case Me.RBtn_Exact.Checked
FoldersList = New Concurrent.ConcurrentDictionary(Of String, Object)(1, Capacity)
FilesList = New Concurrent.ConcurrentDictionary(Of String, Object)(1, Capacity)
With Join(Words.ToArray)
If Me.CBox_Folders.Checked Then
' NOTE: SearchFolders will evaluate CBox_Files.Checked and do SearchFiles if True
SearchFolders(Me.TB_StartFolder.Text, .ToString, True)
Else
' NOTE: Only call SearchFiles from here if NOT doing SearchFolders
If Me.CBox_Files.Checked Then
SearchFiles(Me.TB_StartFolder.Text, .ToString, True, True)
End If
End If
End With
Case Me.RBtn_AllInOrder.Checked
FoldersList = New Concurrent.ConcurrentDictionary(Of String, Object)(1, Capacity)
FilesList = New Concurrent.ConcurrentDictionary(Of String, Object)(1, Capacity)
With String.Format("*{0}*", Join(Words.ToArray, "*"))
If Me.CBox_Folders.Checked Then
' NOTE: SearchFolders will evaluate CBox_Files.Checked and do SearchFiles if True
SearchFolders(Me.TB_StartFolder.Text, .ToString, True)
Else
' NOTE: Only call SearchFiles from here if NOT doing SearchFolders
If Me.CBox_Files.Checked Then SearchFiles(Me.TB_StartFolder.Text, .ToString, True, True)
End If
End With
Case Me.RBtn_AllWithoutOrder.Checked
StringPermutations()
' Math.Min caps the concurrency level at 40
FoldersList = New Concurrent.ConcurrentDictionary(Of String, Object)(Math.Min(40, PermutationsArr.Count), Capacity)
FilesList = New Concurrent.ConcurrentDictionary(Of String, Object)(Math.Min(40, PermutationsArr.Count), Capacity)
For Each Pattern As String In PermutationsArr
If Me.CBox_Folders.Checked Then
' NOTE: SearchFolders will evaluate CBox_Files.Checked and do SearchFiles if True
SearchFolders(Me.TB_StartFolder.Text, Pattern, True)
'Tasks.Add(Task.Run(Sub() SearchFolders(Me.TB_StartFolder.Text, Pattern)))
Else
' NOTE: Only call SearchFiles from here if NOT doing SearchFolders
If Me.CBox_Files.Checked Then SearchFiles(Me.TB_StartFolder.Text, Pattern, True, True)
End If
Next
Case Me.RBtn_AnyWord.Checked
FoldersList = New Concurrent.ConcurrentDictionary(Of String, Object)(Words.Count, Capacity)
FilesList = New Concurrent.ConcurrentDictionary(Of String, Object)(Words.Count, Capacity)
For Each Word In Words
With String.Format("*{0}*", Word)
If Me.CBox_Folders.Checked Then
' NOTE: SearchFolders will evaluate CBox_Files.Checked and do SearchFiles if True
SearchFolders(Me.TB_StartFolder.Text, .ToString, True)
Else
' NOTE: Only call SearchFiles from here if NOT doing SearchFolders
If Me.CBox_Files.Checked Then SearchFiles(Me.TB_StartFolder.Text, .ToString, True, True)
End If
End With
Next
End Select
Task.WaitAll(Tasks.ToArray)
Debug.Print("Tasks Completed in {0}", StopWatch.Elapsed.ToString)
Debug.Print("Adding {0} Folders", FoldersList.Keys.Count.ToString)
Me.LB_Folders.DataSource = FoldersList.Keys
Debug.Print("Adding {0} Files", FilesList.Keys.Count.ToString)
Me.LB_Files.DataSource = FilesList.Keys
Btn_Search.Text = "Search"
End Sub
Private Sub SearchFolders(FolderPath As String, Pattern As String, Optional FirstCall As Boolean = False)
Try
Dim Folders() As String = IO.Directory.GetDirectories(FolderPath)
For Each Folder As String In Folders
Dim SubFolders() As String = IO.Directory.GetDirectories(Folder, Pattern)
For Each SubFolder As String In SubFolders
Select Case True
Case Not FilesList.Count < Capacity
Exit For
Case Not Me.CBox_LastModRange.Checked
FoldersList.TryAdd(SubFolder, Nothing)
Case FolderInModRange(Folder)
FoldersList.TryAdd(SubFolder, Nothing)
End Select
Next
If Me.CBox_Files.Checked Then
' Do NOT call this with Recursive = True from here!
SearchFiles(Folder, Pattern)
End If
If FirstCall Then
' Perform multithreaded Recursion
Tasks.Add(Task.Run(Sub() SearchFolders(Folder, Pattern)))
Else
' Perform deep recursion within task thread...don't branch further
SearchFolders(Folder, Pattern)
End If
Next
Catch ex As UnauthorizedAccessException
' Access Denied
Catch ex As Exception
Debug.Print("SearchFiles: {0}", ex.ToString)
End Try
End Sub
Private Sub SearchFiles(FolderPath As String, Pattern As String, Optional Recursive As Boolean = False, Optional FirstCall As Boolean = False)
' Recursive and FirstCall should only be True if NOT doing SearchFolders
' Recursive should only be True if called from the main thread or this method to continue the deep dive
' FirstCall should only be True if called from the main thread
Try
For Each Filename As String In IO.Directory.GetFiles(FolderPath, Pattern)
Select Case True
Case Not FilesList.Count < Capacity
Exit For
Case Not Me.CBox_LastModRange.Checked
FilesList.TryAdd(Filename, Nothing)
Case FileInModRange(Filename)
FilesList.TryAdd(Filename, Nothing)
End Select
Next
If Recursive Then
Try
Dim Folders() As String = IO.Directory.GetDirectories(FolderPath)
For Each Folder As String In Folders
If FirstCall Then
' Perform multithreaded Recursion
Tasks.Add(Task.Run(Sub() SearchFiles(Folder, Pattern, Recursive)))
Else
' Perform deep recursion within task thread...don't branch further
SearchFiles(Folder, Pattern, Recursive)
End If
Next
Catch ex As Exception
' Access Denied - Does this happen?
Debug.Print("Recursive FolderPath: {0}", ex.Message)
End Try
End If
Catch ex As UnauthorizedAccessException
' Access Denied
Catch ex As Exception
Debug.Print("SearchFiles: {0}", ex.ToString)
End Try
End Sub
Private Function FolderInModRange(Folder As String) As Boolean
Try
With New IO.DirectoryInfo(Folder)
Select Case True
Case .LastWriteTime < Me.DT_ModRangeStart.Value
Return False
Case .LastWriteTime > Me.DT_ModRangeEnd.Value
Return False
Case Else
Return True
End Select
End With
Catch ex As Exception
Debug.Print("FolderInModRange: {0}{1}{2}", Folder, Environment.NewLine, ex.ToString)
End Try
' Only if exception is thrown
Return False
End Function
Private Function FileInModRange(Filename As String) As Boolean
Try
With New IO.FileInfo(Filename)
Select Case True
Case .LastWriteTime < Me.DT_ModRangeStart.Value
Return False
Case .LastWriteTime > Me.DT_ModRangeEnd.Value
Return False
Case Else
Return True
End Select
End With
Catch ex As IO.PathTooLongException
' Path Too Long
Catch ex As Exception
Debug.Print("FileInModRange: {0}{1}{2}", Filename, Environment.NewLine, ex.ToString)
End Try
' Only if exception is thrown
Return False
End Function
End Class
Recursion avoids the UnauthorizedAccessException errors generated by .Net's GetDirectories and GetFiles methods when they run into folders that the user doesn't have access rights to.
References:
Task-based Asynchronous
Programming
Concurrent
Collections

Related

How to use a Name rather than OID in vb.net

Good day,
I am trying to figure out this code from sharp-snmp samples.
https://github.com/lextudio/sharpsnmplib-samples/blob/master/Samples/VB.NET/snmpset/Program.vb
I am using the vb.net SET sample.
Public Sub New(id As Lextm.SharpSnmpLib.ObjectIdentifier, data As Lextm.SharpSnmpLib.ISnmpData)
Member of Lextm.SharpSnmpLib.Variable
Public Sub New(id As UInteger(), data As Lextm.SharpSnmpLib.ISnmpData)
Member of Lextm.SharpSnmpLib.Variable
Is my Name syntax just wrong, or is it that it must be an OID integer? When I use the OID it runs, when I use the name it dies.
System_Operation_Mode.0 'name
1.3.6.1.4.1.21703.100.1.1.0 'oid
This is the part of the SET sample where it dies at the asterix ** at the bottom of the code.
Extra(i) is filled out with the above Name instead of the OID.
ReDim args(3)
args(0) = "192.168.45.5" 'IP Address
args(1) = NetworkConfig.addrModeStringCommand 'command string name System_Operation_Mode.0
args(2) = "i" 'tell it what data type you are sending
args(3) = NetworkConfig.StaticMode 'mode you want from the IPNetwork, in this case static
Dim p As OptionSet = New OptionSet().Add("c:", "Community name, (default is public)", Sub(v As String)
If v IsNot Nothing Then
community = v
End If
End Sub) _
.Add("l:", "Security level, (default is noAuthNoPriv)", Sub(v As String)
If v.ToUpperInvariant() = "NOAUTHNOPRIV" Then
level = Levels.Reportable
ElseIf v.ToUpperInvariant() = "AUTHNOPRIV" Then
level = Levels.Authentication Or Levels.Reportable
ElseIf v.ToUpperInvariant() = "AUTHPRIV" Then
level = Levels.Authentication Or Levels.Privacy Or Levels.Reportable
Else
Throw New ArgumentException("no such security mode: " & v)
End If
End Sub) _
.Add("a:", "Authentication method (MD5 or SHA)", Sub(v As String)
authentication = v
End Sub) _
.Add("A:", "Authentication passphrase", Sub(v As String)
authPhrase = v
End Sub) _
.Add("x:", "Privacy method", Sub(v As String)
privacy = v
End Sub) _
.Add("X:", "Privacy passphrase", Sub(v As String)
privPhrase = v
End Sub) _
.Add("u:", "Security name", Sub(v As String)
user = v
End Sub) _
.Add("C:", "Context name", Sub(v As String)
contextName = v
End Sub) _
.Add("h|?|help", "Print this help information.", Sub(v As String)
showHelp__1 = v IsNot Nothing
End Sub) _
.Add("V", "Display version number of this application.", Sub(v As String)
showVersion = v IsNot Nothing
End Sub) _
.Add("d", "Display message dump", Sub(v As String)
dump = True
End Sub) _
.Add("t:", "Timeout value (unit is second).", Sub(v As String)
timeout = Integer.Parse(v) * 1000
End Sub) _
.Add("r:", "Retry count (default is 0)", Sub(v As String)
retry = Integer.Parse(v)
End Sub) _
.Add("v:", "SNMP version (1, 2, and 3 are currently supported)", Sub(v As String)
Select Case Integer.Parse(v)
Case 1
version = VersionCode.V1
Exit Select
Case 2
version = VersionCode.V2
Exit Select
Case 3
version = VersionCode.V3
Exit Select
Case Else
Throw New ArgumentException("no such version: " & v)
End Select
End Sub)
If args.Length = 0 Then
ShowHelp(p)
Return
End If
Dim extra As List(Of String)
Try
extra = p.Parse(args)
Catch ex As OptionException
Console.WriteLine(ex.Message)
Return
End Try
If showHelp__1 Then
ShowHelp(p)
Return
End If
If (extra.Count - 1) Mod 3 <> 0 Then
Console.WriteLine("invalid variable number: " & extra.Count)
Return
End If
If showVersion Then
Console.WriteLine(Reflection.Assembly.GetExecutingAssembly().GetName().Version)
Return
End If
Dim ip As IPAddress
Dim parsed As Boolean = IPAddress.TryParse(extra(0), ip)
If Not parsed Then
For Each address As IPAddress In Dns.GetHostAddresses(extra(0))
If address.AddressFamily <> AddressFamily.InterNetwork Then
Continue For
End If
ip = address
Exit For
Next
If ip Is Nothing Then
Console.WriteLine("invalid host or wrong IP address found: " & extra(0))
Return
End If
End If
Try
Dim vList As New List(Of Variable)()
Dim i As Integer = 1
While i < extra.Count
Dim type As String = extra(i + 1)
If type.Length <> 1 Then
Console.WriteLine("invalid type string: " & type)
Return
End If
Dim data As ISnmpData
Select Case type(0)
Case "i"c
data = New Integer32(Integer.Parse(extra(i + 2)))
Exit Select
Case "u"c
data = New Gauge32(UInteger.Parse(extra(i + 2)))
Exit Select
Case "t"c
data = New TimeTicks(UInteger.Parse(extra(i + 2)))
Exit Select
Case "a"c
data = New IP(IPAddress.Parse(extra(i + 2)).GetAddressBytes())
Exit Select
Case "o"c
data = New ObjectIdentifier(extra(i + 2))
Exit Select
Case "x"c
data = New OctetString(ByteTool.Convert(extra(i + 2)))
Exit Select
Case "s"c
data = New OctetString(extra(i + 2))
Exit Select
Case "d"c
data = New OctetString(ByteTool.ConvertDecimal(extra(i + 2)))
Exit Select
Case "n"c
data = New Null()
Exit Select
Case Else
Console.WriteLine("unknown type string: " & type(0))
Return
End Select
Dim test As New Variable(*New ObjectIdentifier(extra(i))*, data)
vList.Add(test)
i = i + 3
End While
I have been using using the "Name" instead of the "OID" is there a way to change so it can read either, or have them converted? Or will I have to go back use the OIDs?

Formatting 45.22.30 in VB.NET [duplicate]

Under keypress event, I have a function validating the entered characters, this is my code.
Public Function vNum2(val As Object)
Dim result As Boolean = False
Dim allowedChars As String = "0123456789." & vbBack
Try
If allowedChars.IndexOf(val) = -1 Then
result = True
End If
Catch ex As Exception
MsgBox("Error 1010xVNum2: " & ex.Message)
End Try
Return result
End Function
How do i validate a decimal when I entered more than 2 dots in decimal? When I press another dot, the textbox will not receive the character.
E.g: -> correct entry 45.23 receive the first dot.
-> validating entry 45.2.3 will not receive the next dot.
Try this :
Public Function vNum2(val As Object)
Dim result As Boolean = False
Try
'Dim allowedChars As String = "42.2.3"
Dim allowedChars As String = val.ToString()
'Bellow line will count how many dots are in string, if there one or none, result will be True
If allowedChars.Where(Function(dots) dots = ".").Count < 2 Then result = True
Catch ex As Exception
MsgBox("Error 1010xVNum2: " & ex.Message)
End Try
Return result
End Function

String comparison not working for array of strings

cfg file to start, this is the file:
http://pastebin.com/mE3Y3wiq
What I am doing is looking for a class, once found I store the data for THAT class in a listbox, so ex: if I'm looking for "Fixing", I will store each line in a listbox that is after "{Fixing}" until we hit the next class OR the end of the file (for Fixing we would stop at "{Pillars}")
Here is my code:
Private Sub tvList_AfterSelect(sender As Object, e As TreeViewEventArgs) Handles tvList.AfterSelect
Dim cfgData() As String
' Dim lstData As New ListBox()
lstData.Items.Clear()
If rbnInch.Checked Then
cfgData = File.ReadAllLines("C:\Library\Common\PARAM-NG\Dbs\Mould\Dme_I\Dme_I.cfg")
Else
cfgData = File.ReadAllLines("C:\Library\Common\PARAM-NG\Dbs\Mould\Dme\Dme.cfg")
End If
Dim classID As Short = tvList.SelectedNode.Index
Dim classType As String = tvList.Nodes.Item(classID).Text
Try
For i As Short = 0 To cfgData.Count - 1
If cfgData(i).Contains("{" & classType & "}") Or cfgData(i).Contains("{" & classType.Replace(" ", "") & "}") Then
i += 1
Do
lstData.Items.Add(cfgData(i))
i += 1
If cfgData(i).Contains(tvList.Nodes.Item(tvList.SelectedNode.Index + 1).Text.Replace(" ", "")) Or cfgData(i).Contains(tvList.Nodes.Item(tvList.SelectedNode.Index + 1).Text) Or cfgData(i).ToString() Is vbNullString Then
Exit Do
End If
Loop
End If
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Right now I am only getting the first line in my listbox and that's it. Need help on collecting the data I need and then stopping at the next class or end of file (end of file for the last class since there is no class after it that will mark my exit)
This has been extracted from the question and posted on the OP's behalf.
I solved it myself.
Private Sub tvList_AfterSelect(sender As Object, e As TreeViewEventArgs) Handles tvList.AfterSelect
Dim cfgData() As String
' Dim lstData As New ListBox()
lstData.Items.Clear()
If rbnInch.Checked Then
cfgData = File.ReadAllLines("C:\Library\Common\PARAM-NG\Dbs\Mould\Dme_I\Dme_I.cfg")
Else
cfgData = File.ReadAllLines("C:\Library\Common\PARAM-NG\Dbs\Mould\Dme\Dme.cfg")
End If
Dim classID As Short = tvList.SelectedNode.Index
Dim classType As String = tvList.Nodes.Item(classID).Text
Try
For i As Short = 0 To cfgData.Count - 1
If cfgData(i).Contains("{" & classType) Or cfgData(i).Contains("{" & classType.Replace(" ", "")) Then
i += 1
Do
If tvList.SelectedNode.Index + 1 >= tvList.Nodes.Count Then
If i >= cfgData.Count - 1 Then
lstData.Items.Add(cfgData(i))
Exit Do
ElseIf cfgData(i) = vbNullString Then
lstData.Items.Add(cfgData(i))
i += 1
ElseIf cfgData(i).Substring(0, 1).Contains("{") Then
Exit Do
Else
lstData.Items.Add(cfgData(i))
i += 1
End If
ElseIf i >= cfgData.Count - 1 Then
lstData.Items.Add(cfgData(i))
Exit Do
ElseIf cfgData(i) = vbNullString Then
lstData.Items.Add(cfgData(i))
i += 1
ElseIf cfgData(i).Substring(0, 1).Contains("{") Then
Exit Do
Else
lstData.Items.Add(cfgData(i))
i += 1
End If
Loop
End If
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub

How to Nest a "Try if " Statement DataGridView

What I am trying to do is : FIRST: Check if Cell Value Exist if TRUE continue.
SECOND : If False MsgBox Invalid Ticket.
Private Sub changefound()
Dim findtxt As String = txt_Find.Text
Try
If DataGridView2.Rows.Count > 0 Then
For i As Integer = 0 To DataGridView2.Rows.Count - 1
Dim CellChange As String = DataGridView2.Rows(i).Cells("CODE").Value.ToString 'This is line 363
If CellChange.Contains(findtxt) = True Then
If Not IsDBNull(DataGridView2.Rows(i).Cells("STATUS").Value) _
AndAlso DataGridView2.Rows(i).Cells("STATUS").Value = "IN" Then
MsgBox("Ticket Used")
Exit Sub
Else
With DataGridView2
.Rows(i).Cells("STATUS").Value = "IN"
Exit Sub
End With
End If
End If
Next
End If
Catch e As Exception
MessageBox.Show(e.ToString())
End Try
'''''''''''''''''''If Flase Only Works Here''''''''''''''''''''''
Try
If DataGridView2.Rows.Count > 0 Then
For i As Integer = 0 To DataGridView2.Rows.Count - 1
Dim CellChange As String = DataGridView2.Rows(i).Cells("CODE").Value.ToString
If CellChange.Contains(findtxt) = False Then
MsgBox("InValid Ticket")
Exit Sub
End If
Next
End If
Catch e As Exception
MessageBox.Show(e.ToString())
End Try
End Sub
the problem is i keep getting the error MSGBOX

How To Download Emails From Junk Folder Using POP3

POP Servers allow for the LIST command that returns a list of all of the emails in the mail box. Unfortunately it does not return ALL of the emails, it only returns the emails from the Inbox. So if an email lands in a junk folder it cannot find it.
Is it possible to download emails from the junk folder using POP?
This is the current class(s) that I am using:
Option Strict On
Option Explicit On
Imports System.Net, System.Text
Public Class POP3
Inherits Sockets.TcpClient
Dim Stream As Sockets.NetworkStream
Dim UsesSSL As Boolean = False
Dim SslStream As Security.SslStream
Dim SslStreamDisposed As Boolean = False
Public LastLineRead As String = vbNullString
Public Overloads Sub Connect(ByVal Server As String, ByVal Username As String, ByVal Password As String, Optional ByVal InPort As Integer = 110,Optional ByVal UseSSL As Boolean = False)
If Connected Then Disconnect()
UsesSSL = UseSSL
MyBase.Connect(Server, InPort)
Stream = MyBase.GetStream
If UsesSSL Then
SslStream = New Security.SslStream(Stream)
SslStream.AuthenticateAsClient(Server)
End If
If Not CheckResponse() Then Exit Sub
If CBool(Len(Username)) Then
Me.Submit("USER " & Username & vbCrLf)
If Not CheckResponse() Then Exit Sub
End If
If CBool(Len(Password)) Then
Me.Submit("PASS " & Password & vbCrLf)
If Not CheckResponse() Then Exit Sub
End If
End Sub
Public Function CheckResponse() As Boolean
If Not IsConnected() Then Return False
LastLineRead = Me.Response
If (Left(LastLineRead, 3) <> "+OK") Then
Throw New POP3Exception(LastLineRead)
Return False
End If
Return True
End Function
Public Function IsConnected() As Boolean
If Not Connected Then
Throw New POP3Exception("Not Connected to an POP3 Server.")
Return False
End If
Return True
End Function
Public Function Response(Optional ByVal dataSize As Integer = 1) As String
Dim enc As New ASCIIEncoding
Dim ServerBufr() As Byte
Dim Index As Integer = 0
If dataSize > 1 Then
ReDim ServerBufr(dataSize - 1)
Dim dtsz As Integer = dataSize
Dim sz As Integer
Do While Index < dataSize
If UsesSSL Then
sz = SslStream.Read(ServerBufr, Index, dtsz)
Else
sz = Stream.Read(ServerBufr, Index, dtsz)
End If
If sz = 0 Then Return vbNullString
Index += sz
dtsz -= sz
Loop
Else
ReDim ServerBufr(255)
Do
If UsesSSL Then
ServerBufr(Index) = CByte(SslStream.ReadByte)
Else
ServerBufr(Index) = CByte(Stream.ReadByte)
End If
If ServerBufr(Index) = -1 Then Exit Do
Index += 1
If ServerBufr(Index - 1) = 10 Then Exit Do
If Index > UBound(ServerBufr) Then
ReDim Preserve ServerBufr(Index + 255)
End If
Loop
End If
Return enc.GetString(ServerBufr, 0, Index)
End Function
Public Sub Submit(ByVal message As String)
Dim enc As New ASCIIEncoding
Dim WriteBuffer() As Byte = enc.GetBytes(message)
If UsesSSL Then
SslStream.Write(WriteBuffer, 0, WriteBuffer.Length)
Else
Stream.Write(WriteBuffer, 0, WriteBuffer.Length)
End If
End Sub
Public Sub Disconnect()
Me.Submit("QUIT" & vbCrLf)
CheckResponse()
If UsesSSL Then
SslStream.Dispose()
SslStreamDisposed = True
End If
End Sub
'*******************************************************************************
' Function Name : List
' Purpose : Get the drop listing from the maildrop
' :
' Returns : Any Arraylist of POP3Message objects
' :
' Typical telNet I/O:
'LIST (submit)
'+OK Mailbox scan listing follows
'1 2532 (record index and size in bytes)
'2 1610
'3 12345
'. (end of records terminator)
'*******************************************************************************
Public Function List() As ArrayList
If Not IsConnected() Then Return Nothing 'exit if not in TRANSACTION mode
Me.Submit("LIST" & vbCrLf) 'submit List request
If Not CheckResponse() Then Return Nothing 'check for a response, but if an error, return nothing
'
'get a list of emails waiting on the server for the authenticated user
'
Dim retval As New ArrayList 'set aside message list storage
Do
Dim response As String = Me.Response 'check response
If (response = "." & vbCrLf) Then 'done with list?
Exit Do 'yes
End If
Dim msg As New POP3Message 'establish a new message
Dim msgInfo() As String = Split(response, " "c) 'separate by spaces, which divide its fields
msg.MailID = Integer.Parse(msgInfo(0)) 'get the list item number
msg.ByteCount = Integer.Parse(msgInfo(1)) 'get the size of the email message
msg.Retrieved = False 'indicate its message body is not yet retreived
retval.Add(msg) 'add a new entry into the retrieval list
Loop
Return retval 'return the list
End Function
Public Function GetHeader(ByRef msg As POP3Message, Optional ByVal BodyLines As Integer = 0) As POP3Message
If Not IsConnected() Then Return Nothing
Me.Submit("TOP " & msg.MailID.ToString & " " & BodyLines.ToString & vbCrLf)
If Not CheckResponse() Then Return Nothing
msg.Message = vbNullString
Do
Dim response As String = Me.Response
If response = "." & vbCrLf Then
Exit Do
End If
msg.Message &= response
Loop
Return msg
End Function
Public Function Retrieve(ByRef msg As POP3Message) As POP3Message
If Not IsConnected() Then Return Nothing
Me.Submit("RETR " & msg.MailID.ToString & vbCrLf)
If Not CheckResponse() Then Return Nothing
msg.Message = Me.Response(msg.ByteCount)
Do
Dim S As String = Response()
If S = "." & vbCrLf Then
Exit Do
End If
msg.Message &= S
Loop
msg.ByteCount = Len(msg.Message)
Return msg
End Function
Public Sub Delete(ByVal msgHdr As POP3Message)
If Not IsConnected() Then Exit Sub
Me.Submit("DELE " & msgHdr.MailID.ToString & vbCrLf)
CheckResponse()
End Sub
Public Sub Reset()
If Not IsConnected() Then Exit Sub
Me.Submit("RSET" & vbCrLf)
CheckResponse()
End Sub
Public Function NOOP() As Boolean
If Not IsConnected() Then Return False
Me.Submit("NOOP")
Return CheckResponse()
End Function
Protected Overrides Sub Finalize()
If Not SslStreamDisposed Then
SslStream.Dispose()
End If
MyBase.Finalize()
End Sub
End Class
Public Class POP3Message
Public MailID As Integer = 0
Public ByteCount As Integer = 0
Public Retrieved As Boolean = False
Public Message As String = vbNullString
Public Overrides Function ToString() As String
Return Message
End Function
End Class
Public Class POP3Exception
Inherits ApplicationException
Public Sub New(ByVal str As String)
MyBase.New(str)
End Sub
End Class
As per the comments, the POP3 standard only allows for downloading from the "Inbox". It's not designed for anything more advanced.
The ideal solution would be to use IMAP4, if the mail server supports it.
IMAP4 allows you to save, flag, copy and delete messages, as well as allowing folders and subfolders and it does not require exclusive access.