VB.NET Have whole program loop until user decides to exit? - vb.net

I have a simple program to average ten (user-defined) numbers and then print the result. At the end of the program I'd like to print Would you like to average a new set of numbers? (Y/N) If the user inputs y than I want the program to execute again from the top. If the user inputs n than the program should close. I've tried researching this, but only found ways to have the entire console exit and re-open which is not what I want.

To detect what the user has entered you have a couple options:
Console.ReadKey()
will read the next keystroke. You can then use a simple Select Case branch to choose what to do.
You can also use:
Console.ReadLine()
which will return a string (after the user presses enter). You can then use a simple If statement to determine what's in the string (and repeat the query if something other than "y" or "n" was entered.)
Example:
Shared Sub Main()
While True
AverageNums()
Console.WriteLine( "Do you want to run again? (Y/N)" )
Dim key = Console.ReadKey()
If key.Key = ConsoleKey.N Then
Exit While
End If
End While
End Sub
Shared Sub AverageNums()
' ...
End Sub

My response may be a little late in the game, but thought I'd share a compact version implementing a try-catch method.
Sub Main()
Do
Try
Console.Write("Enter a value: ")
Console.ReadLine()
'...
SomeProcedure()
Catch ex As Exception
Console.WriteLine(ex.ToString)
Finally
Console.Write("Enter another value? (N for No) ")
End Try
Loop Until Console.ReadLine() = "N"
End Sub
Sub SomeProcedure()
'...
End Sub

Related

How to make a private sub go back to sub main()

Ok so, I have all my program and what not, it's just I don't how to prevent it from quitting the program after the execution of a
private sub
Like for example, I have
Private Sub KeyList()
Console.WriteLine("1.) File - Opens a test file")
Console.WriteLine("2.) Update - Updates the program using an external .bat file")
Console.WriteLine("3.) Username - ReDo Your username")
Console.WriteLine("4.) Site - Starts your browser and leads you to our site :D")
Console.WriteLine("5.) PLUGIN_STRT_NOPROT - Starts the loaded plugin without layered protection, do not do this unless you know")
Console.WriteLine("what you are doing")
Console.WriteLine("6.) PLUGIN_STRT_PROT - Starts loaded plugin with protection, reccomended.")
Console.WriteLine("7.) API_Str_Rand - Creates a random API string that you can assign to a plugin.")
Console.WriteLine("8) DownloadDevKit - Downloads the developmental kit to create a plugin")
End Sub
but after I hit any other key, the program terminates. How do I prevent the program from terminating, and going back to the
sub main()
Here is my data code for the entire program, it's VB.net 2010.
Module Module1
Sub Main()
REM Add all the Dimensions/Descriptions here.
Dim VersionName As String = "1"
Dim Action As String = "Action"
Dim username As String = "UserName"
REM The Visual part of the program. No pun intended :>
REM Ask the name for the session.
username:
Console.WriteLine("Hello, What is your name? ")
username = Console.ReadLine()
Console.WriteLine("Hello " + username)
If username = "Skycoder" Then
Console.WriteLine("Welcome back!, Planned updates to include in this are, 1.) ADd in more key features")
Console.WriteLine("2.) Add hotkeys")
Console.WriteLine("3.) Implement and auto updater")
Console.Beep()
If username = "" Then
Console.WriteLine("Please type in name. Numerals can be used")
GoTo username
End If
End If
Fish:
Console.ReadLine()
Console.Clear()
Console.Title = ("Desktop TBI | Hello " + username)
Console.WriteLine("-----------------------------------------------------------------------------------------------------------")
Console.WriteLine("Please select an option, note that this is a work in progress, and will contain more features in the future")
Console.WriteLine("")
Console.WriteLine(" Type 'File' to create the directory (Important if you want to add plugins)")
Console.WriteLine(" Using Version: " + VersionName)
Console.WriteLine("-----------------------------------------------------------------------------------------------------------")
Console.WriteLine(" Please choose what action you want to do")
Console.WriteLine(" Type in 'File' To find the directory")
Console.WriteLine(" Type in 'Update' To open the .bat file to download the updates")
Console.WriteLine("-----------------------------------------------------------------------------------------------------------")
Console.WriteLine("To create the new path, enter 'CreateDir'")
REM Begin the part where users can select their code.
Dim selection As String = Console.ReadLine
Select Case selection
REM This allows the creation of a text file.
Case "File"
Console.Clear()
File() REM Private sub selection
REM Updates their program.
Case "Username"
Console.Clear()
GoTo UserName
REM Set's their username for the program.
Case "Update"
Update()
Case "KeyList"
KeyList()
Case "CreateDir"
CreateDir()
Case "SERV_Start"
Chat_Start_SERV()
Case "Site"
Site()
Console.ReadLine()
End Select
End Sub
but after I select the case that I want to use and head into the sub code for the
keylists, it just terminates, and it doesn't even wait for me to read it. I'll literally provide video of it happening if it helps anyone... I am desperate...
Put your Select case block in the loop, add one more option ("Exit" for example) - if that option will be selected exit loop and application will be exited.
Console.WriteLine("0) Exit - Exit application")
Dim selection As String = Console.ReadLine()
While selection.Equals("Exit") = false
Select Case selection
REM This allows the creation of a text file.
Case "File"
Console.Clear()
File() REM Private sub selection
'...
'... other Case values
'...
End Select
selection = Console.ReadLine()
Loop
This application will only hit the Console.ReadLine() if the user entered "Site". Move the Readline statement below the End Select statement and it will do what you want.

Call Function when User Types Certain Keyword

Okay, so I am working on a small scripting language using a VB Console Application.
I want the user to input "say('something')" and it calls the function I made named "say", is there a way to call the function and still use the following code:
Module Module1
Sub say(sayline)
Console.WriteLine(sayline)
End Sub
Sub Main()
Dim cmd As String
Console.WriteLine(">")
Do
Console.Write("")
cmd = Console.ReadLine()
If cmd IsNot Nothing Then cmd
Loop While cmd IsNot Nothing
End Sub
End Module
No, you cannot just call a method from user's string. You need to interpret the entered data.
First, you need to split your method name and arguments so that entered "say('something')" will transform to say and something. Remember that user can enter wrong data and you need to check if this call is correct - it's all about syntactic and lexical analysis. I hope you understand how to do this because it is pretty difficult.
Then, you need to check if you have a method called say. In case of plain and simple structure, switch construction will be enough. If your have such method, then pass something argument to this method. Else, output something like "unknown method".
If you wanted to call the method say upon typing the word say(something) and display the word something, then you can just have a certain condition that if the user types the word say within the input then call say method else, do whatever you want to do under else portion. Parse the input and omit the word say from the input and display it then.
You can have your code this way for example. (I just copied your code and added some codes to meet what you wanted... in my understanding)
Module Module1
Sub say(ByVal sayline)
Console.WriteLine(sayline)
End Sub
Sub Main()
Dim cmd As String
Do
Console.Write("> ")
cmd = Console.ReadLine()
Try
If cmd IsNot Nothing And cmd.Substring(0, 3).ToUpper().Equals("SAY") Then
say(parseInput(cmd))
End If
Catch ex As Exception
Console.WriteLine("message here")
End Try
Loop While cmd IsNot Nothing
End Sub
Function parseInput(ByVal cmd As String) As String
Dim input As String = ""
For index As Integer = 3 To cmd.Length - 1
If Char.IsLetter(cmd) Then
input += cmd.Substring(index, 1)
Else
input = input
End If
Next
Return input
End Function
End Module

Update a label from a task

I'm trying to implement tasks in my program. I launch a task that will produce a log file, and after, I want to update the label to say "Log sucessfully saved".
Here is my code
Private Function Createlog(ByVal mylist As List(Of classTest))
Dim sw As New StreamWriter("log_list.log")
For index = 1 To mylist.Count - 1
sw.WriteLine(mylist(index).comments)
Next
sw.Close()
Try
Me.Invoke(UpdateLabel("Log sucessfully saved"))
Catch ex As Exception
End Try
Return 1
End Function
Private Function UpdateLabel(ByVal text As String)
Label1.Text = text
Return 1
End Function
I launch the task from the Main form in the Load() :
Dim tasktest = Task(Of Integer).Factory.StartNew(Function() Createlog(theList))
(I don't know if it is better to use the factory or declare as a task and then task.Start())
I have the error on the label update :
Cross-thread operation not valid: Control 'Label1' accessed from a thread
other than the thread it was created on.
Could you please explain why it doesn't work with the invoke method ? And do you have an alternative solution ?
Thanks for your help
First, UpdateLabel should be a Sub, not a Function. Second, this line is wrong:
Me.Invoke(UpdateLabel("Log sucessfully saved"))
Read it again. You are, in order, executing the UpdateLabel function, then passing the result of that function to Me.Invoke (if you used Sub instead of Function, the compiler should have warned you about the error).
This doesn't raise any compiler errors because a Function declared without As [Type] is defaulted to As Object, that can be cast to anything. It should be:
Me.Invoke(Sub()
UpdateLabel("Log sucessfully saved")
End Sub)
To simplify, your code can be rewritten like this:
Private Sub Createlog(ByVal mylist As List(Of classTest))
Dim sw As New StreamWriter("log_list.log")
For index = 1 To mylist.Count - 1
sw.WriteLine(mylist(index).comments)
Next
sw.Close()
Me.Invoke(Sub()
Label1.Text = "Log sucessfully saved"
End Sub)
End Sub

Getting error from Isnumeric() VB.NET

I'm getting runtime error when I enter alphabets in the inputbox
Dim amount As String
amount = InputBox("Enter the amount of people you want to participtate", "System Message")
If amount < 0 Or Not (IsNumeric(amount)) Then
MsgBox("Please enter positive number of people", vbExclamation, "System Message")
End If
Comparing strings to numbers is pretty dangerous and blew up in your face. You can make it work but you'll have to code is carefully, ensuring that you never try to compare a string that can't be converted to a number. That requires using another operator:
If Not IsNumeric(amount) OrElse amount < 0 Then
MsgBox("Please enter positive number of people", vbExclamation, "System Message")
End If
Note the changed order and the use of OrElse, the short-circuiting version of Or. It won't evaluate the right-hand side expression if the left-hand side is already True.
The more .NET centric way to do this is by using Integer.TryParse() to convert strings to numbers.
To avoid an error, you can make it like this ..
If IsNumeric(amount) Then
If value(amount) > 0 Then
'codes here
Else
MsgBox("Please enter positive number of people", vbExclamation, "System Message")
End If
Else
MsgBox("Please enter a number of people", vbExclamation, "System Message")
End If
So I was looking at validating a textbox, first I wanted to make sure that it was not empty and make sure that it was a number. I'm by no means an expert but I'll put the code I wrote to validate the user input. I put it in a function because I had a lot of text fields that the user had to enter.
Class MainWindow
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
tb2.Text = tbCheck(tb1)
End Sub
Private Function tbCheck(ByRef tb As TextBox) As Boolean
tbCheck = tb.Text.Length > 0
Try
tbCheck = (tb.Text / 1) > 0
Catch ex As Exception
tbCheck = False
End Try
Return tbCheck
End Function
End Class
This is just the simple program I wrote to check if the code worked as I had hoped.
Hope this can help someone or at least tell me if there is something I'm missing.

While loop causes the app to go slow? Any idea why?

I have a simple code that looks up a text file, reads the line of text, splits the string by semi-colons and then posts the results.
After it has done this, I have created a really simple while loop to waste 10 seconds before going for it again.... here is the code:
Private Sub checkTemps()
While Abort = False
Try
fileReader = New StreamReader(directory.Text & "currentTemp.dat")
rawData = fileReader.ReadLine()
fileReader.Close()
Dim dataArray() As String
dataArray = rawData.Split(";")
updateOutput("1", dataArray(0), dataArray(1))
updateOutput("2", dataArray(2), dataArray(3))
updateOutput("3", dataArray(4), dataArray(5))
updateOutput("4", dataArray(6), dataArray(7))
stpWatch.Start()
While stpWatch.Elapsed.Seconds < 10 And Abort = False
pollInterval(stpWatch.ElapsedMilliseconds)
End While
stpWatch.Stop()
stpWatch.Reset()
Catch ex As Exception
msgbox("oops!")
End Try
End While
closeOnAbort()
End Sub
But when it gets to the "time-wasting" loop - it seems to slow the whole application down? And I can't work out why!
So a couple of questions... is there a better way to do all this? and second - can anyone spot a problem?
All the other commands seem to run fine - there isn't much else to this app. I have another program that updates the dat file with the values, this is simply a client side app to output the temperatures.
Any help would be appreciated.
Andrew
More info:
I should explain what the pollInterval sub does!
Private Delegate Sub pollIntervalDelegate(ByVal value As Integer)
Private Sub pollInterval(ByVal value As Integer)
If Me.InvokeRequired Then
Dim upbd As New pollIntervalDelegate(AddressOf pollInterval)
Me.Invoke(upbd, New Object() {value})
Else
ProgressBar1.Value = value
End If
End Sub
Your loop is a very tight loop continually calling pollInterval. This will tie up the application until the loop condition is met.
You should use the Sleep method to pause this thread for the required amount of time.
If you want to show the progress (as per your update) you could put the Sleep into the loop and sleep for 1 second (or half a second?) at a time:
While stpWatch.Elapsed.Seconds < 10 And Abort = False
Sleep(1000) <-- NOT 100% sure of the syntax here,
but the time is specified in milliseconds
pollInterval(stpWatch.ElapsedMilliseconds)
End While
You should go with
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(10).TotalMilliseconds);