Visual basic If and else not working 2015 - vb.net

I am a newbie and I am facing some problem with the 'if' and 'else' function of visual basic.
I have added a button labeled as Save, its code is as given below:
Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
If CheckBox1.Checked = True Then
Dim savedata7 As New System.IO.StreamWriter("dat0C.bin")
savedata7.WriteLine("checked")
savedata7.Close()
End If
If CheckBox1.Checked = False Then
Dim savedata7 As New System.IO.StreamWriter("dat0C.bin")
savedata7.WriteLine("unchecked")
savedata7.Close()
End If
If CheckBox2.Checked = True Then
Dim savedata8 As New System.IO.StreamWriter("dat1C.bin")
savedata8.WriteLine("checked")
savedata8.Close()
End If
If CheckBox2.Checked = False Then
Dim savedata8 As New System.IO.StreamWriter("dat1C.bin")
savedata8.WriteLine("unchecked")
savedata8.Close()
End If
End Sub
And another button labeled Load, its code is given below:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Try
Dim dataloader As New System.IO.StreamReader("dat0C.bin")
Label17.Text = dataloader.ReadToEnd
dataloader.Close()
Catch ex As Exception
End Try
Try
Dim dataloader As New System.IO.StreamReader("dat1C.bin")
label10.Text = dataloader.ReadToEnd
dataloader.Close()
Catch ex As Exception
End Try
If Label17.Text = "checked" Then
CheckBox1.Checked = True
Else
CheckBox1.Checked = False
End If
If Label10.Text = "checked" Then
CheckBox2.Checked = True
Else
CheckBox1.Checked = False
End If
End Sub
The Save button(Button5) is working perfectly fine, but the Load button(Button1) is not working as it should, on clicking Button1 the files 'dat0C.bin' and 'dat1c.bin' are loaded in 'Label17' and 'Label10' respectively but it is not working(i.e. it is not Checking the CheckBoxes1 or 2) from
If Label17.Text = "checked" Then
CheckBox1.Checked = True
Else
CheckBox1.Checked = False
End If
If Label10.Text = "checked" Then
CheckBox2.Checked = True
Else
CheckBox1.Checked = False
End If
Please correct me, If I'm doing anything wrong in it.

This happens because in the reading code you use ReadToEnd instead of ReadLine.
This method reads back the newline character added by WriteLine and doesn't strip it away as ReadLine
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Try
Using dataloader = New System.IO.StreamReader("dat0C.bin")
Label17.Text = dataloader.ReadLine()
End Using
Catch ex As Exception
MessageBox.Show("Exception=" & ex.Message)
End Try
....
A part from this you really should put the creation of disposable objects like the reader and the write inside a using statement to be sure that these objects are properly closed and disposed ALSO in case of exceptions.
Said that, your code could be simplified a lot if you use the static methods of the File class
WRITING
File.WriteAllText("dat0C.bin", If(CheckBox1.Checked, "checked", "unchecked"))
File.WriteAllText("dat1C.bin", If(CheckBox2.Checked, "checked", "unchecked"))
READING
Label17.Text = File.ReadAllText("dat0C.bin")
Label10.Text = File.ReadAllText("dat1C.bin")
CheckBox1.Checked = (Label17.Text = "checked")
CheckBox2.Checked = (Label10.Text = "checked")

Asside from not naming your controls, and not disposing properly of your StreamReader or StreamWriter instances the reason this is not working correctly is because when you write your file you call WriteLine - which appends a carriage return and line feed onto the end of what you've written.
You then read the file, and put the content in a label, which itself will render the CR/LF albeit not visible to you. You then compare to the Text of this label but without the CR/LF - so that comparison evaluates false.

Related

How to show records added to datagridview in real time

A co-worker needs to search our network and her File Explorer search does not work well. I threw this app together quickly to allow her to search and it works well. The results are written to a datagridview, but the results are not shown until the search is complete.
I would like the datagridview to show records as they are added and allow her to cancel the search if she wants.
Using a backgroundworker, I tried to refresh the grid, but as soon as it finds a match, the code stops running. There are no errors, it just stops running.
So how can I get the grid to update as it continues to search?
Public dtResults As DataTable
Dim myDataSet As New DataSet
Dim myDataRow As DataRow
Dim colType As DataColumn
Dim colResult As DataColumn
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
dtResults = New DataTable()
colType = New DataColumn("Type", Type.GetType("System.String"))
colResult = New DataColumn("Search Result", Type.GetType("System.String"))
dtResults.Columns.Add(colType)
dtResults.Columns.Add(colResult)
DataGridView1.DataSource = dtResults
DataGridView1.Columns(1).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
End Sub
Private Sub btnSearch_Click(sender As Object, e As EventArgs) Handles btnSearch.Click
btnSearch.Enabled = False
sbStatusBar.Text = "Searching..."
dtResults.Clear()
BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
LoopSubFolders(txtSearchLocation.Text)
End Sub
Public Sub LoopSubFolders(sLocation As String)
Dim di = New DirectoryInfo(sLocation)
Dim mySearchterm As String = LCase(txtSearchTerm.Text)
Dim fiArr As FileInfo() = di.GetFiles()
Dim sSearchTarget As String
sbStatusBar.Text = "Searching " & sLocation
'Search File names in
If cbFileNames.Checked = True Then
For Each myFile In fiArr
sSearchTarget = LCase(myFile.Name)
If sSearchTarget.Contains(mySearchterm) Then
myDataRow = dtResults.NewRow()
myDataRow(dtResults.Columns(0)) = "File"
myDataRow(dtResults.Columns(1)) = Path.Combine(sLocation, myFile.Name)
dtResults.Rows.Add(myDataRow)
End If
Next
End If
For Each d In Directory.GetDirectories(sLocation)
If cbFolderNames.Checked = True Then
sSearchTarget = LCase(d)
If sSearchTarget.Contains(mySearchterm) Then
myDataRow = dtResults.NewRow()
myDataRow(dtResults.Columns(0)) = "Folder"
myDataRow(dtResults.Columns(1)) = d
dtResults.Rows.Add(myDataRow)
End If
End If
LoopSubFolders(d)
Next
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
btnSearch.Enabled = True
sbStatusBar.Text = "Complete"
DataGridView1.DataSource = Nothing
DataGridView1.DataSource = dtResults
DataGridView1.Columns(1).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
End Sub
Here's an example of how you might do it using the suggested ReportProgress method and ProgressChanged event:
Private table As New DataTable
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'Configure table here.
DataGridView1.DataSource = table
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Setup UI here.
'Note that you MUST pass in the TextBox data as you MUST NOT touch the UI directly on the secondary thread.
BackgroundWorker1.RunWorkerAsync({TextBox1.Text, TextBox2.Text})
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
'Get the data passed in and separate it.
Dim arguments = DirectCast(e.Argument, String())
Dim folderPath = arguments(0)
Dim searchTerm = arguments(1)
SearchFileSystem(folderPath, searchTerm)
End Sub
Private Sub SearchFileSystem(folderPath As String, searchTerm As String)
For Each filePath In Directory.GetFiles(folderPath)
If filePath.IndexOf(searchTerm, StringComparison.InvariantCultureIgnoreCase) <> -1 Then
'Update the UI on the UI thread.
BackgroundWorker1.ReportProgress(0, {"File", filePath})
End If
Next
For Each subfolderPath In Directory.GetDirectories(folderPath)
If subfolderPath.IndexOf(searchTerm, StringComparison.InvariantCultureIgnoreCase) <> -1 Then
'Update the UI on the UI thread.
BackgroundWorker1.ReportProgress(0, {"Folder", subfolderPath})
End If
SearchFileSystem(subfolderPath, searchTerm)
Next
End Sub
Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
'Get the data passed out and separate it.
Dim data = DirectCast(e.UserState, String())
'Update the UI.
table.Rows.Add(data)
End Sub
Note that you should NEVER touch the UI directly in the DoWork event handler or a method called from it. ONLY touch the UI on the UI thread. That means that the text in your TextBoxes must be extracted BEFORE calling RunWorkerAsync. You can eithewr pass the Strings in as arguments or you can assign them to fields and access them from there on any thread. Don't EVER access a member of a control on other than the UI thread. Some times it will work, sometimes it will appear to work but not do as intended and sometimes it will crash your app. So that you don't have to remember which specific scenarios cause which result, avoid such scenario altogether.
I haven't tested this code so I'm not sure but you may have to call Refresh on the grid or the form after adding the new row to the DataTable.
Variables
Well, let's start from the top with some class level variables:
'Notice the enabled properties.
Private WithEvents BackgroundWorker1 As New BackgroundWorker With {.WorkerReportsProgress = True, .WorkerSupportsCancellation = True}
'To monitor the cancellation, set by the Cancel Button.
Private bgwCancel As Boolean = False
'The DGV source.
Private dtResults As New DataTable
'The start directory.
Private startDir As String
'The search keyword.
Private searchWord As String
'Whether to search the sub directories, from a check box for example.
Private includeSubDirectories As Boolean = True
'Whether to search the files, from another check box.
Private includeFiles As Boolean = True
The Constructor
Prepare your DGV and whatever else you need here.
Sub New()
dtResults.Columns.Add(New DataColumn("Type", Type.GetType("System.String")))
dtResults.Columns.Add(New DataColumn("Search Result", Type.GetType("System.String")))
DataGridView1.DataSource = dtResults
DataGridView1.Columns(1).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
'Make sure you add the image column after binding the data source.
Dim imgCol As New DataGridViewImageColumn(False)
With imgCol
.Image = Nothing
.Name = "imgCol"
.HeaderText = ""
.Width = 50
.DefaultCellStyle.NullValue = Nothing
End With
DataGridView1.Columns.Insert(0, imgCol)
End Sub
Iterator
Now, let's write the search routine. I'd do that through an Iterator function:
Private Iterator Function IterateFolders(startDir As String, includeFiles As Boolean, includeSubDir As Boolean) As IEnumerable(Of String)
For Each dirName In IO.Directory.EnumerateDirectories(startDir)
Yield dirName
If includeFiles Then
For Each fileName In IO.Directory.EnumerateFiles(startDir)
Yield fileName
Next
End If
If includeSubDir Then
For Each subDir In IterateFolders(dirName, includeFiles, includeSubDir)
Yield subDir
Next
End If
Next
End Function
The Main Thread Updater
A routine called by the worker's thread to update the DataTable and any control that belongs to the main thread:
Private Sub AddSearchResult(path As String)
If InvokeRequired Then
Invoke(Sub() AddSearchResult(path))
Else
dtResults.Rows.Add(If(IO.File.Exists(path), "File", "Folder"), path)
sbStatusBar.Text = $"Searching {path}"
End If
End Sub
Start
In the click event of the start button, do the necessary validations, assign the values to their variables, and start the back ground worker:
If String.IsNullOrEmpty(txtSearchKeyword.Text) Then Return
If String.IsNullOrEmpty(txtSearchLocation.Text) Then Return
bgwCancel = False
dtResults.Rows.Clear()
startDir = txtSearchLocation.Text
searchWord = txtSearchKeyword.Text.ToLower
includeSubDirectories = chkIncludeSubDirs.Checked
includeFiles = chkFiles.Checked
btnSearch.Enabled = False
sbStatusBar.Text = "Searching..."
BackgroundWorker1.RunWorkerAsync()
Cancel
To cancel the search, in the click event of the cancel button I presume, True the bgwCancel variable:
bgwCancel = True
The BackgroundWorker - DoWork
Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
For Each item As String In IterateFolders(startDir, includeFiles, includeSubDirectories)
If bgwCancel Then
BackgroundWorker1.CancelAsync()
Return
End If
If item.ToLower.Contains(searchWord) Then
AddSearchResult(item)
End If
Threading.Thread.Sleep(100)
Next
End Sub
Note that, Its good practice to give a lengthy routine a BREATH through the Sleep(ms) method of that thread.
The BackgroundWorker - ProgressChanged
I don't think you need it here.
The BackgroundWorker - RunWorkerCompleted
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If bgwCancel Then
sbStatusBar.Text = "Canceled!"
MessageBox.Show("Canceled by you!")
ElseIf e.Error IsNot Nothing Then
sbStatusBar.Text = "Error!"
MessageBox.Show(e.Error.Message)
Else
sbStatusBar.Text = "Complete"
'YOU DO NOT NEED TO DO THIS. Remove the following
'DataGridView1.DataSource = Nothing
'DataGridView1.DataSource = dtResults
'DataGridView1.Columns(1).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
End If
btnSearch.Enabled = True
End Sub
The Image Column
Handle the RowsAdded event of the DGV as follow:
Private Sub DataGridView1_RowsAdded(sender As Object, e As DataGridViewRowsAddedEventArgs) Handles DataGridView1.RowsAdded
If DataGridView1.Columns.Count < 3 Then Return
'if you want to get rid of the default x image.
If e.RowIndex = 0 Then
DataGridView1.Rows(e.RowIndex).Cells("imgCol").Value = Nothing
End If
Dim path As String = DataGridView1.Rows(e.RowIndex).Cells(2).Value?.ToString
If Not String.IsNullOrEmpty(path) Then
If IO.File.Exists(path) Then
DataGridView1.Rows(e.RowIndex).Cells("imgCol").Value = Icon.ExtractAssociatedIcon(path).ToBitmap
Else
DataGridView1.Rows(e.RowIndex).Cells("imgCol").Value = My.Resources.Folder
End If
End If
End Sub
Where the My.Resources.Folder is an icon file of your choice for the folder entries.
Good luck.

Threading doesn't complete the task before ending the thread loop

So I did something similar a while ago, but this is essentially a username checker for a (specific) website, they can load in usernames via text file and it will put it into a list box, now I have the start button and it's meant to check each username. Before, however, it froze the program when they checked, but it worked. I tried making it "threaded" so it didn't freeze.
The problem now is that it doesn't check them all, and finishes instantly.
CODE:
Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
Button6.Enabled = False
Dim goodUsers As New SaveFileDialog()
goodUsers.Filter = "TXT file (*.txt)|*.txt"
Dim flag As Boolean
Dim Incomplete As Integer = 0
Dim Taken As Integer = 0
Dim sb As New StringBuilder
If goodUsers.ShowDialog() = DialogResult.OK Then
Dim checkerMT As New Thread(
Sub()
For Each i As String In UsernameList.Items
WebRequest.Create("http://yatobooter.cf/other/checkusr.php?username=" + i.ToString)
Dim cResult As String = New System.Net.WebClient().DownloadString("http://yatobooter.cf/other/checkusr.php?username=" + i.ToString).ToString
If cResult = "taken" Then
flag = False
ElseIf cResult = "nottaken" Then
flag = True
End If
If flag = True Then
sb.Append(i & vbNewLine)
Else
Incomplete = Incomplete + 1
Taken = UsernameList.Items.Count - Incomplete
End If
Next
End Sub
)
checkerMT.Start()
Try
File.WriteAllText(goodUsers.FileName, sb.ToString)
Catch ex As Exception
Exit Sub
End Try
End If
MessageBox.Show("Checking available usernames, complete!", "NameSniper Pro")
Button6.Enabled = True
End Sub
You cannot access UI elements (UsernameList.Items) from a thread other than the UI. Instead add a background worker to your form to handle the basic threading stuff (progress reporting, finish reporting, exception handling). Pass into this an object that contains the settings your job needs to do its work without interacting with the ui.
Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
Button6.Enabled = False
Dim goodUsers As New SaveFileDialog()
goodUsers.Filter = "TXT file (*.txt)|*.txt"
If goodUsers.ShowDialog() = DialogResult.OK Then
'Note: You'll need to add the filenames
BackgroundWorker1.RunWorkerAsync(New State() With {.Names = {}, .FileName = goodUsers.FileName})
End If
End Sub
Class State
Public Names As List(Of String)
Public StringBuilder As New System.Text.StringBuilder
Public Incomplete As Integer
Public Taken As Integer
Public FileName As String
End Class
Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim state = CType(e.Argument, State)
For Each i As String In state.Names
Using cli = New System.Net.WebClient()
Dim cResult = cli.DownloadString("http://yatobooter.cf/other/checkusr.php?username=" + i.ToString).ToString
If cResult = "nottaken" Then
state.StringBuilder.Append(i & vbNewLine)
Else
state.Incomplete = state.Incomplete + 1
state.Taken = state.Names.Count - state.Incomplete
End If
End Using
Next
IO.File.WriteAllText(state.FileName, state.StringBuilder.ToString)
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If e.Error IsNot Nothing Then
MessageBox.Show(e.Error.ToString(), "Error")
Else
MessageBox.Show("Checking available usernames, complete!", "NameSniper Pro")
End If
Button6.Enabled = True
End Sub
The SaveFileDialog can be used as "Using directive"
Why do you create a webrequest on the one hand, and on the other hand use a webclient? That does not make sense at all.
Instead of your strange if condition, write:
flag = (cResult.Equals("nottaken"))
All code you want to run after the actions you are currently running in your thread have to be in your thread as well, because it is async.
You have to invoke if you use user controls within a thread
and so on..
Please turn Option Strict On and Option Infer Off
There are lots of other things you could do better.
Please remove the webrequest and webclient combination yourself, that does not make sense at all.
Take a look at this, I cleared it a little bit:
Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
Dim Incomplete As Integer = 0
Dim Taken As Integer = 0
Dim sb As New StringBuilder
Using goodUsers As SaveFileDialog = new SaveFileDialog()
goodUsers.Filter = "TXT file (*.txt)|*.txt"
If not goodUsers.ShowDialog() = DialogResult.OK Then Exit Sub
Dim checkerMT As New Thread(
Sub()
Me.invoke(sub()
Button6.Enabled = False
For Each i As String In UsernameList.Items
WebRequest.Create("http://yatobooter.cf/other/checkusr.php?username=" + i.ToString)
Dim cResult As String = New System.Net.WebClient().DownloadString("http://yatobooter.cf/other/checkusr.php?username=" + i.ToString).ToString
If (cResult.toLower().Equals("nottaken")) Then
sb.Append(String.Concat(i , Environment.NewLine)
Else
Incomplete += 1
Taken = UsernameList.Items.Count - Incomplete
End If
Next
File.WriteAllText(goodUsers.FileName, sb.ToString)
Button6.Enabled = True
MessageBox.Show("Checking available usernames, complete!", "NameSniper Pro")
End Sub)
End Sub
)
checkerMT.IsBackground = True;
checkerMT.Start()
End Sub

VB.NET: Code runs without error, but does not add item to listbox

I've got this embedded CMD on my form which I created using another person's code and everything works right. Inside one of the Private Subs (that seems to run every time a new line is written in the CMD output textbox), I've got a line which adds a item to a listbox (listboxs name is txtPlayerList) on another form labelled Status.
When this area of the code runs, it doesn't throw up any errors (and if I put a msgbox() on the same line, the msgbox() works). If I put the add to listbox line on form_load it works perfectly?
Here is my code, I've included everything from that form just in case (it is in the third sub from the top with the asterisks and comment "Get players and maybe other stuff as well"
Imports System.IO
Public Class Console
Public WithEvents MyProcess As Process
Private Delegate Sub AppendOutputTextDelegate(ByVal text As String)
Public LastLine As String
Public LastLineFormatted As String
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim LocalpathParent As String = Application.StartupPath() + "\MCserver"
'loads embed cmd
Me.AcceptButton = ExecuteButton
MyProcess = New Process
With MyProcess.StartInfo
.FileName = "CMD.EXE"
.UseShellExecute = False
.CreateNoWindow = True
.RedirectStandardInput = True
.RedirectStandardOutput = True
.RedirectStandardError = True
.WorkingDirectory = LocalpathParent
End With
MyProcess.Start()
MyProcess.BeginErrorReadLine()
MyProcess.BeginOutputReadLine()
AppendOutputText("Process Started at: " & MyProcess.StartTime.ToString)
'Resize with parent mdi container. Needs to be anchored & StartPosition = manual in properties
Me.WindowState = FormWindowState.Maximized
End Sub
Private Sub MyProcess_ErrorDataReceived(ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs) Handles MyProcess.ErrorDataReceived
AppendOutputText(vbCrLf & "Error: " & e.Data)
End Sub
Private Sub MyProcess_OutputDataReceived(ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs) Handles MyProcess.OutputDataReceived
AppendOutputText(vbCrLf & e.Data)
'*****************************************
'Get Players and maybe other stuff as well
'*****************************************
LastLine = Me.OutputTextBox.Lines.Last
If Status.ServerStarted = True Then
If Me.LastLine.Contains(" joined the game") Then
LastLineFormatted = Me.LastLine
LastLineFormatted = LastLineFormatted.Replace(" joined the game", "")
'***THIS LINE BELOW WORKS IN FORM LOAD, BUT NOT HERE FOR SOME REASON???***
Status.txtPlayersList.Items.Add(LastLineFormatted)
MsgBox("add lastlineformatted")
ElseIf Me.LastLine.Contains(" left the game") Then
LastLineFormatted = Me.LastLine
LastLineFormatted = LastLineFormatted.Replace(" left the game", "")
Status.txtPlayersList.Items.Remove(LastLineFormatted)
End If
End If
End Sub
Private Sub ExecuteButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExecuteButton.Click
MyProcess.StandardInput.WriteLine(InputTextBox.Text)
MyProcess.StandardInput.Flush()
InputTextBox.Text = ""
End Sub
Private Sub AppendOutputText(ByVal text As String)
If OutputTextBox.InvokeRequired Then
Dim myDelegate As New AppendOutputTextDelegate(AddressOf AppendOutputText)
Try
Me.Invoke(myDelegate, text)
Catch
End Try
Else
Try
OutputTextBox.AppendText(text)
Catch
End Try
End If
End Sub
End Class
EDIT: Below is the code I have for form1 per request
'code
Public Class Form1
Public Localpath As String
Public Downloadpath As String
Public LocalpathParent As String
'when this form is closing, send stop to console to make sure it has closed and saved
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Console.MyProcess.StandardInput.WriteLine("stop") 'send an EXIT command to the Command Prompt
Application.Exit()
End
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'load stuff in background n stuff
Me.Show()
Me.Focus()
Configure.Show()
Configure.Hide()
Status.Show()
Status.Hide()
Console.Show()
Console.Hide()
End Sub
'CONSOLE.form
Private Sub ConsoleToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles ConsoleToolStripMenuItem1.Click
'Hide all forms
Status.Hide()
Configure.Hide()
'Shown Form that you want to load
Console.Opacity = 100
Console.Show()
WindowState = FormWindowState.Normal
Console.MdiParent = Me
Console.OutputTextBox.SelectionStart = Console.OutputTextBox.Text.Length
Console.OutputTextBox.ScrollToCaret()
End Sub
'STATUS.form
Private Sub StatusToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles StatusToolStripMenuItem1.Click
'hide all forms
Console.Hide()
Configure.Hide()
'Show Form that you want to load
Status.Opacity = 100
Status.Show()
WindowState = FormWindowState.Maximized
Configure.Size = Me.Size
Status.MdiParent = Me
End Sub
'CONFIGURE.form
Private Sub ConfigurationToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles ConfigurationToolStripMenuItem1.Click
'hide all forms
Status.Hide()
Console.Hide()
'Show form that you want to load
Configure.Opacity = 100
Configure.Show()
WindowState = FormWindowState.Maximized
Configure.Size = Me.Size
Configure.MdiParent = Me
End Sub
End Class
'code
It seems that your original code to create an embeded CMD window was interfering with the code to update the listbox in another mdi child. After finding another way to embed a cmd console, and some fiddling around, It seems to be working Ok. I haven't been able to test pure server output yet though.
THere have been quite a few changes to the code that are too big to post here, but the Alternative embedded CMD is this.
Place this in general form declarations
'command prompt variables
Private strResults As String
Private intStop As Integer
Private swWriter As System.IO.StreamWriter
Friend thrdCMD As System.Threading.Thread
Private Delegate Sub cmdUpdate()
Private uFin As New cmdUpdate(AddressOf UpdateText)
Public WithEvents procCMDWin As New Process
This in your form_load Sub
thrdCMD = New System.Threading.Thread(AddressOf Prompt)
thrdCMD.IsBackground = True
thrdCMD.Start()
and these declarations within your form Class
Private Sub Prompt()
AddHandler procCMDWin.OutputDataReceived, AddressOf CMDOutput
AddHandler procCMDWin.ErrorDataReceived, AddressOf CMDOutput
procCMDWin.StartInfo.RedirectStandardOutput = True
procCMDWin.StartInfo.RedirectStandardInput = True
procCMDWin.StartInfo.CreateNoWindow = True
procCMDWin.StartInfo.UseShellExecute = False
procCMDWin.StartInfo.FileName = "cmd.exe"
procCMDWin.StartInfo.WorkingDirectory = LocalpathParent
procCMDWin.Start()
procCMDWin.BeginOutputReadLine()
swWriter = procCMDWin.StandardInput
Do Until (procCMDWin.HasExited)
Loop
procCMDWin.Dispose()
End Sub
Private Sub UpdateText()
OutputTextBox.Text += strResults
OutputTextBox.SelectionStart = OutputTextBox.TextLength - 1
InputTextBox.Focus()
intStop = OutputTextBox.SelectionStart
OutputTextBox.ScrollToCaret()
If OutputTextBox.Lines.Count > 2 Then
LastLine = OutputTextBox.Lines.ElementAt(OutputTextBox.Lines.Count - 2)
If Status.ServerStarted = True Then
'get element 1 of split
If LastLine.Contains(" joined the game") Then
LastLineFormatted = ExtractName(LastLine, " joined the game")
'If listlineformatted.contains(Players.allitems) then do
Status.txtPlayersList.Items.Add(LastLineFormatted)
Status.Show()
ElseIf Me.LastLine.Contains(" left the game") Then
LastLineFormatted = ExtractName(LastLine, " left the game")
'If listlineformatted.contains(Players.allitems) then do
Status.txtPlayersList.Items.Remove(LastLineFormatted)
MsgBox("remove lastlineformatted")
End If
End If
End If
End Sub
Private Function ExtractName(unformattedString As String, stringToRemove As String) As String
Dim temp As String = Split(unformattedString, "Server]")(1).ToString
ExtractName = temp.Replace(stringToRemove, "")
End Function
Private Sub CMDOutput(ByVal Sender As Object, ByVal OutputLine As DataReceivedEventArgs)
strResults = OutputLine.Data & Environment.NewLine
Invoke(uFin)
End Sub

Is there any way for Retrieve Record Value from Table Column , Loop and Loop in vb.net

Sorry for my poor English
When the user clicks the Start button, I am trying to display all of the records from the Phone column in the Textbox1 control. I want to see all those records pass into Textbox1 While it is processing the For loop. But it is currently processing very fast so that I only see the last record in Textbox1. What i'm going wrong?
While it is processing the For loop, I change the Start button to a Stop button. So when I click the button and it currently has a Text value equal to "Stop", I want it to skip the For loop and pass the value from TextBox1 to my FirstWin. And then it should change the BtnStart.Text back to "Start"
Here's my code:
Public Class PhoneFortune
Dim CN As OleDbConnection
Dim CM As OleDbCommand
Dim DA As OleDbDataAdapter
Dim DT As New DataTable
Private Sub BtnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnStart.Click
If BtnStart.Text = "Start" Then
CM = New OleDbCommand("SELECT * FROM TblPhoneNumber", CN)
DA = New OleDbDataAdapter(CM)
DA.Fill(DT)
For i = 0 To DT.Rows.Count - 1
TextBox1.Text = DT.Rows(i)("Phone")
Next
BtnStart.Text = "Stop"
End If
If BtnStart.Text = "Stop" Then
If FirstWin.Text = "" Then
FirstWin.Text = TextBox1.Text
BtnStart.Text = "Start"
ElseIf SecondWin.Text = "" Then
SecondWin.Text = TextBox1.Text
BtnStart.Text = "Start"
ElseIf ThirdWin.Text = "" Then
ThirdWin.Text = TextBox1.Text
BtnStart.Text = "Start"
End If
End If
End Sub
Private Sub PhoneFortune_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
CN = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=database\db.accdb;Jet OLEDB:Database Password=12345;")
CN.Open()
End Sub
End Class
I hope we are on the same page but if u want to slow down the process for a bit u use these two lines of code within the FOR loop
System.Threading.Thread.Sleep(1000)
Me.Refresh() Where 1000 is one second(value is represented in milliseconds).
Now what is that FirstWin.Text="" etc used for? Are you trying to start the looping,then change the text to "stop" so that when the user clicks stops it stops at the current record? Go to youtube and look for multithreading videos,not sure how to help u on that one hope the rest helps. If this is useful please acknowledge
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If Button1.Text = "Start" Then
If TextBox1.Text = "" Then
t1 = New Thread(AddressOf Me.PhoneThread)
t1.Start()
Button1.Text = "Stop"
Else
t1.Resume()
Button1.Text = "Stop"
End If
Else 'Click Stop
t1.Suspend()
Button1.Text = "Start"
If FirstWin.Text = "" Then
FirstWin.Text = TextBox1.Text
ElseIf SecondWin.Text = "" Then
SecondWin.Text = TextBox1.Text
ElseIf ThirdWin.Text = "" Then
ThirdWin.Text = TextBox1.Text
End If
End If
End Sub
Sub PhoneThread()
'Dim ThreadsArray As List(Of Threading.Thread) = New List(Of Threading.Thread)
Dim s As Integer
'MsgBox(DT.Rows.Count)
For s = 0 To DT.Rows.Count
If s = DT.Rows.Count Then
s = 0
Else
TextBox1.Text = DT.Rows(s)("Phone")
' ThreadsArray.Add(t1)
Thread.Sleep(19)
'TextBox1.Text = s.ToString()
Me.Refresh()
End If
Next
End Sub
Private Sub BtnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnStart.Click
Me.Close()
End Sub
For something simple like this, System.Threading.Thread.Sleep(100) (to block the thread) followed by Application.DoEvents() (to process any button clicks) seems like it would do the trick.
For something more complicated, this approach will result in re-entrancy and difficult-to-reproduce bugs; in that case, you definitely need asynchronous programming.

.NET fulltext autocomplete in a combobox. Any performance-positive way of overriding listitems?

I'm struggling to meet a demand from my supervisors. I really hope that someone could give some advice.
Basically there are places in our project where there is a big selection of options. The most concrete example is choosing a city in the world. The items are hundreds of thousands.
Using standard winforms controls and properties, one can search through a list fast.
The problem is that we're using a concatenation of city&district name for all the items. Essentially PREFIX autotomplete works but does not work as needed. The task is to filter and show items by any given string in any part of the item. Essentially a FULL TEXT search in the combobox.
Does anyone have an idea about switching autocomplete sources in runtime relatively qiuckly and handling the suggest/suggestappend event?
Also the project is in VB.NET, though any form of .NET advice will be extremely helpful.
Thanks!
UPDATE: The latest attempt using competent_tech's suggestion with some minor modifications.
Imports System.Data
Public Class Form1
Private _ErrorText As String
Private _CommandExecuted As Boolean
Private m_fOkToUpdateAutoComplete As Boolean
Private m_sLastSearchedFor As String = ""
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Call Me.SetStatusText("Loading...")
Me._ErrorText = ""
Me.Cities.Clear()
Me.BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Try
Me._CommandExecuted = True
Me.Ara_airportsTableAdapter.Fill(Me.Cities.ara_airports)
Catch ex As Exception
_ErrorText = ex.Message
End Try
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If Me._ErrorText = "" Then
Me.SetStatusText(Me.Cities.ara_airports.Count & " Records loaded")
Else
Me.SetStatusText(Me._ErrorText)
End If
Me.BindingSource.ResetBindings(False)
End Sub
Private Sub SetStatusText(ByVal sText As String)
Me.Text = sText
End Sub
Private Sub cboPort_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles cboPort.KeyDown
Try
If e.KeyCode = Keys.Up OrElse e.KeyCode = Keys.Down Then
m_fOkToUpdateAutoComplete = False
Else
m_fOkToUpdateAutoComplete = True
End If
Catch theException As Exception
' ...
End Try
End Sub
Private Sub cboPort_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboPort.KeyUp
Try
If m_fOkToUpdateAutoComplete Then
With cboPort
If .Text.Length >= 2 Then
Dim cSuggestions As IList
Dim sError As String = ""
m_sLastSearchedFor = .Text
cSuggestions = GetSuggestions(m_sLastSearchedFor)
.DataSource = Nothing
If cSuggestions IsNot Nothing Then
.BindingContext = New BindingContext
.DisplayMember = "CName"
.ValueMember = "id"
.DataSource = New BindingSource(cSuggestions, Nothing)
System.Threading.Thread.Sleep(10)
System.Windows.Forms.Application.DoEvents()
.DroppedDown = True
.Text = m_sLastSearchedFor
If .Text.Length > 0 Then .SelectionStart = .Text.Length
End If
End If
End With
End If
Catch theException As Exception
' ...
End Try
End Sub
Private Function GetSuggestions(ByVal searchFor As String) As IList
BindingSource.Filter = "CName LIKE '%" & searchFor & "%'"
Return BindingSource.List
End Function
End Class
The way we address this with very large sets of data (full set of drug information) is:
1) Handle the combo's TextChanged event
2) Within this event, get the list of suggestions that match the user's current input from the database. We leverage the power of database searching to find matches anywhere within the string.
3) When the suggestions are retrieved, bind them to the combobox
4) Wait for a little bit (500ms) to let the UI catch up (we use a combination of System.Threading.Thread.Sleep and System.Windows.Format.Application.DoEvents()).
A couple of notes on this approach:
1) Nothing is bound to the list when the form is first opened
2) We wait until the user has entered at least 4 characters before we start searching to reduce the hit on the DB and improve the user experience (you don't want to show all of the matches for A, for example).
Update with code to show full solution:
Here are some additional notes and code to show the actual process.
The ComboBox should be configured with all of the properties set to their default values with the exception of:
AutoCompleteMode = SuggestAppend
PreferredDropDownSize = 0, 0
Here is the code that we use for our specific situation (searching first four chars) with a placeholder for retrieving and assigning the data:
Private m_fOkToUpdateAutoComplete As Boolean
Private m_sLastSearchedFor As String = ""
Private Sub cboName_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles cboName.KeyDown
Try
' Catch up and down arrows, and don't change text box if these keys are pressed.
If e.KeyCode = Keys.Up OrElse e.KeyCode = Keys.Down Then
m_fOkToUpdateAutoComplete = False
Else
m_fOkToUpdateAutoComplete = True
End If
Catch theException As Exception
' Do something with the error
End Try
End Sub
Private Sub cboName_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboName.TextChanged
Try
If m_fOkToUpdateAutoComplete Then
With cboName
If .Text.Length >= 4 Then
' Only do a search when the first 4 characters have changed
If Not .Text.Substring(0, 4).Equals(m_sLastSearchedFor, StringComparison.InvariantCultureIgnoreCase) Then
Dim cSuggestions As IEnumerable
Dim sError As String = ""
' Record the last 4 characters we searched for
m_sLastSearchedFor = .Text.Substring(0, 4)
' And search for those
cSuggestions = GetSomeSuggestions(m_sLastSearchedFor) ' Your code here
.DataSource = Nothing
If cSuggestions IsNot Nothing Then
' Because this can use the same data source as the list, ensure that
' the bindingcontexts are different so that the lists are not tied to each other
.BindingContext = New BindingContext
.DataSource = cSuggestions
' Let the UI process the results
System.Threading.Thread.Sleep(10)
System.Windows.Forms.Application.DoEvents()
End If
End If
Else
If Not String.IsNullOrEmpty(m_sLastSearchedFor) Then
' Clear the last searched for text
m_sLastSearchedFor = ""
cboName.DataSource = Nothing
End If
End If
End With
End If
Catch theException As Exception
' Do something with the error
End Try
End Sub