I'm building a program in VB whose purpose is to run in the background and automatically update other programs I've created. To do this, it has to check if those programs are still running and, if they are, wait for them to close.
Unfortunately, the program won't compile. The exception states: GetProcessesByName is not a member of String. (The string it refers to is the Process parameter shown in the code below.)
I can't understand why this is happening, because this method has always worked without problems. I'm using Visual Studio 2015. For your reference, here's the code block:
Private Function CheckIfRunning(Process As String) As Boolean
Dim MyProcess() As Process
MyProcess = Process.GetProcessesByName("ProcessName")
If MyProcess.Count > 0 Then
Return True
Else
Return False
End If
End Function
Try using System.Diagnostics.Process.GetProcessesByName("ProcessName")
Since you've declared Process as a string parameter, Process.GetProcessesByName refers to the string instead of the System.Diagnostics method. Alternatively, you can use a different name for the string parameter.
Related
I have a problem understanding command line arguments in VB.NET. Need help from anyone who understands it.
This is for my app. What I wanted is when app is started with switch -U or any other defined parameter, open another form with progressbar.
I have created and defined new form with update functionality, but one thing missing - reaction on command line arguments.
This is for my new app running on Windows in separate folder (not in Program Files), where I want to use auto update function.
https://learn.microsoft.com/en-us/dotnet/api/system.environment.getcommandlineargs?view=netframework-4.8
The example is in C#, but the principle is the same... use GetCommandlineArgs which returns a string array with the command line args that your app was started with.
It's actually quite simple to do.
When your application loads, get a list of the command line variables, then iterate through them and look for the one you want, then act accordingly:
Public Sub Main()
Dim arguments As String() = Environment.GetCommandLineArgs()
For Each a In arguments 'loop through the args in case there are multiple
Select Case a.ToUpper 'compare in uppercase if you don't care how the user enters it.
Case "-U"
'the -U argument was found, set a flag, or perform an action, or otherwise act accordingly.
End Select
Next
End Sub
I always put it in a select case, because in my apps, I may have multiple arguments and I loop through them all and set properties accordingly. In a select case, it's easy to add other parameters later. You can easily add a case else in the event you want to throw up an 'invalid argument' message.
I have made several VB apps that communicate using Windows Remoting, but this is the first time I ran into this problem.
There are two programs in my project, a client and a server. The server program has a queue. The client program adds items to the queue by calling a server method. But when the server program checks the queue, it is empty.
Furthermore, the server program instantiates several classes, but when the client tries to use them, it finds that they are Nothing. So this is a general problem not just an issue with the queue per se.
I have had experience with threading problems in the past, so I assumed that this was some kind of threading problem. I tried using a delegate function, but that did not help.
Here is a snippet of code to illustrate where the problem appeared. My apologies for not knowing how to make it properly formatted, this is my first attempt.
' ====================================================================
' this class is instantiated on the server at startup time
Public Class CPAutoDispatcher
' EXAMPLE #1
Public mWLQueue As New Collection
' This function is called from the remote client using Windows Remoting
Public Function SendWorkList(ByVal theList As String) As Boolean
Dim objWL As New AutoWorkList
If Not parseWorkList(theList, objWL) Then Exit Function
Call mWLQueue.Add(objWL)
SendWorkList = True
End Function
' This function is called from the server
Public Sub Tick()
If mWLQueue.Count = 0 Then Exit Sub ' <-- THIS ALWAYS EXITS!
Dim objWL As AutoWorkList = mWLQueue.Item(1)
Call mWLQueue.Remove(1)
' ... do something with objWL ...
End Sub
' EXAMPLE #2
Private mServerReports() As CPAutoServerReport
Private mDelGNR As DEL_GetNewReport = AddressOf getNewReportDelegate
' This function is called from the server
Public Function ProcessMessage(objSR As CPAutoServerReport) As Boolean
If mServerReports Is Nothing Then
ReDim mServerReports(0)
mServerReports(0) = objSR
Else
' ... do something else ...
End If
End Function
' This function is called from the remote client using Windows Remoting
Public Function GetNewReport() As CPAutoServerReport
GetNewReport = mDelGNR.Invoke
End Function
Private Function getNewReportDelegate() As CPAutoServerReport
If mServerReports Is Nothing Then Exit Function ' <-- THIS ALWAYS EXITS!
' ... do something with mServerReports ...
End Function
End Class
' ================================================================
Example #1: Similar code in other projects works, so I expected mWLQueue and mServerReports to be reachable by both the server and the client. But they are not. The client finds mWLQueue, but it is empty.
Example #2: If this was simply a threading issue, I would expect the delegate to make thing right. But it does not. The client finds that mServerReports Is Nothing, even after it has been set.
My code is behaving as if there are TWO instances of my CPAutoDispatcher class, one for the server thread, and another for the client thread (the remoting calls). But there is only one global variable, which is referenced by both threads.
I am baffled by this situation. Am I missing something that should be obvious?
The ultimate cause of my problems was the presence of duplicate declarations, which did not cause a compile error, and so went unnoticed. When I removed the extra declarations, all of the weird behavior went away.
I suspect that somehow, an instance of the alternate class was instantiated automatically, and being uninitialized, had an empty queue and references that were Nothing. But I don't understand how that came about.
I want my program to take a variable, and find letters A-Z. I have made this section of my program in a module to be shared between 2 different forms.
variables are passed from form1 and are processed by the module and then sent back again to form1. the problem is I think some sort of bug in the code but I cant identify it.
Public Function UPCASES(ByRef password1, points) As Boolean
Dim intersection As IEnumerable(Of Char)
intersection = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Intersect(password1)
'System.StackOverflowException error ^^^^^^^^^^^^^^^^^^^^^^^^^
If intersection.Count() = 1 Then
points = 5
Else
points = 0
End If
Return UPCASES(password1, points)
End Function
You are calling the method itself at the method end, that causes the StackOverflowException:
Return UPCASES(password1, points)
I guess this method should check if the password contains uppercase letters, then use:
Dim containsUpperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Intersect(password1).Any()
So no need to create a method just for this one-liner, if you need a method:
Public Function ContainsUpperCaseLetter(password1 As String) As Boolean
Return "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Intersect(password1).Any()
End Function
Side-note: you should change your default project settings to use Option Strict ON(Off is default unfortunately). Then you will be able to write much more safe, robust and performant code after you have learned a lot about .NET types because you have to fix the compiler errors.
We have a VB.NET project which I am doing some refactoring in. A lot of current functions require a userId to be passed in as a parameter. For example:
Private Function Foo(userId As Integer) As String
Return "Foo"
End Function
But now, I have made this userId paramater no longer needed in much of our code.
I was thinking I would just remove all the userId parameters from all of the functions that don't need them anymore, and try re-building the project to see what calling code needs to change. To my surprise though, the code built successfully.
I learned that you can call a function which returns a string and doesn't take any parameters, but still pass in an Integer value. VB.NET builds/executes this code as if you were trying to invoke the function and then get the character from the String at the specified index. For example:
Imports System
Public Module MyModule
Private Function Foo() As String
Return "Foo"
End Function
Public Sub Main()
Console.WriteLine(Foo(0)) ' prints 'F'
Console.WriteLine(Foo(1)) ' prints 'o'
End Sub
End Module
(.NET Fiddle)
I want my build to fail in this case. I have tried using Option Strict On and Option Explicit On but neither seem to change this behaviour.
Is there anyway to make this kind of function invocation invalid in my VB.NET project?
Create an overload with no parameters which is a copy of the original function in every other respect.
Public Function Foo() As String
Return "Foo"
End Function
Now change the type of userId to something else (not Object or anything numeric etc.)
Public Function Foo(userId As DateTime) As String
Return "Foo"
End Function
Since there is an overload with a parameter, the compiler thinks you mean to call that, instead of indexing the chararray. So you have compile errors. Fix the errors
Then delete the original function.
I've created a Windows Application using VB.Net that uses Sub Main to determine if the application should run a specific process or just open as a form for user interaction. Everything works great except for when I try to schedule my application via Windows Task Scheduler. I kept getting the result code of 0xFF. I then tried running my application directly through the command prompt. When doing this, I received a System.ArgumentNullException error. The other information provided is very lacking so I'm struggling to determine where my issue actually lies. I can run my application from the form using a System.Diagnostics.Process command and passing the arguments to it that way. I can also successfully run it by entering command line arguments in the Debug tab of the application Properties. Below is a general outline of what my code looks like. I'm using the Command Line Parser Library to decipher the arguments. Any help or guidance would be greatly appreciated
Imports CommandLine
Imports CommandLine.Text
Module Startup
Public Sub Main()
Dim Args() As String = Environment.GetCommandLineArgs
Dim Options As New Arguments
Dim Parser As New Parser
If Parser.ParseArguments(Args, Options) Then
' Run application
Else
' Open windows form
End If
End Sub
Public Class Arguments
<[Option]("p", "process", Required:=True)> Public Property ProcessOption As String
<[Option]("r", "run", Required:=True)> Public Property RunOption As String
<[Option]("d", "date", Required:=False, DefaultValue:=Nothing)> Public Property DateOption As Date
<[Option]("u", "user", Required:=False, DefaultValue:="")> Public Property UserOption As String
End Class
End Module
I was able to run this on my testing machine with a debugger and found where my issue is. It actually has nothing to do with the arguments being passed by the command prompt. It's with another sub call I make. I will have to play with it and if I can't figure it out I will open another question. Thank you for your help.