VB.NET Service Skipping Over Sub Procedure - vb.net

I'm writing a Windows Service in VB using Visual Studio 2010. The service is going to check for changes to a table in a database every minute or so. I have experience with VB6 but am new to both VB.NET and creating services, so I might be overlooking something obvious here. When the service is stopped, paused, started, or resumed, a sub procedure is supposed to be called. The problem is that the program skips right over the call to the sub procedure. I set break points at OnPause() and OnContinue() and stepped through the code, to confirm that the program is skipping right over the calls to AgentStopped() and AgentStarted(). What am I doing wrong?
Protected Overrides Sub OnPause()
Log.WriteEntry("Agent paused.") 'This is written to the log
AgentStopped() 'This line is skipped
End Sub
Protected Overrides Sub OnContinue()
Log.WriteEntry("Agent restarted.") 'This is written to the log
AgentStarted() 'This line is skipped
End Sub
Private Sub AgentStarted()
Log.WriteEntry("AgentStarted called.") 'This never written to the log
End Sub
Private Sub AgentStopped()
Log.WriteEntry("AgentStopped called.") 'This never written to the log
End Sub

As you understand, there is no way for the lines you imply to be skipped since the containing method is called. Something else is happening. I suppose the code you are showing is simplified. Right?
I would bet that either you are running a wrong version of your code by mistake, or on your real code an exception occurs inside the called methods (AgentStarted and AgentStopped).
In order to debug this, I would follow these steps:
Change the current log messages and add messages after the call to the functions
Protected Overrides Sub OnPause()
Log.WriteEntry("Agent pause beginning.")
AgentStopped()
Log.WriteEntry("Agent pause ending.")
End Sub
Protected Overrides Sub OnContinue()
Log.WriteEntry("Agent restart beginning.")
AgentStarted()
Log.WriteEntry("Agent restart ending.")
End Sub
If you see the new messages, you will be able to verify that you are actually running the right version of the code and not an older version deployed by mistake.
You should use exception handling with try - catch. I am not really sure (I have never used it), but perhaps using the UnhandledException event to get info for possible uncaught exceptions could be helpful. Another option would be to check the windows event log for errors occuring while executing a web service.
Hope I helped!

Related

VB.Net Multi-Threading InvokeRequired and Passing Thread

I need to be able to pass the thread name into a subroutine in order to abort it when I need to.
So I have this so far:
Dim BrowserSpawn As New System.Threading.Thread(AddressOf BrowserSub)
BrowserSpawn.Start()
Private Async Sub BrowserSub(BrowserSpawn)
...
End Sub
Because the subroutine creates a browser within Form1 groups I needed to invoke access to these controls within the sub.
Note: This works fine when I'm not passing in the thread name.
If Me.GroupNamehere.InvokeRequired Then
Me.GroupNamehere.Invoke(New MethodInvoker(AddressOf BrowserSub))
Else
'Do nothing
End If
When I'm passing in the thread name these become a problem when trying to compile:
Method does not have a signature compatible with delegate 'Delegate Sub MethodInvoker()'.
I'm hoping this is just a syntax thing but I can't seem to get it to work. Is there any way I'm able to pass in this thread name without breaking my invokerequired check?
If I try and change it to the obvious:
Me.GroupNamehere.Invoke(New MethodInvoker(AddressOf BrowserSub(BrowserSpawn)))
It tells me Addressof operand must be the name of a method (without parentheses). Although without the parentheses it's not happy either so I don't know where to go from here.
/edit:
Stumbled across How can I create a new thread AddressOf a function with parameters in VB?
Which seems to confirm what I was trying passing something like:
Private Sub test2(Threadname As Thread)
' Do something
End Sub
And the sub seems happy with that. But I'm not sure how to do that without breaking the invoker part.
Me.GroupNameHere.Invoke(New MethodInvoker(AddressOf SubNameHere))
Works normally. If SubNameHere() becomes SubNameHere(threadname as thread) then that seems happy enough but the invoke line breaks and doesn't want more than the address of.
Two slight syntax changes sorted it:
Private Async Sub SubName(ThreadNameAs Thread)
and
GroupName.Invoke(New MethodInvoker(Sub() Me.SubName(ThreadName)))

Execute a subroutine before exiting the application

I am designing a client-server application, where the client requests various data and the server retrieves it from the local SQL server.
I need to execute a function when the application exits in order to tell associated services that the server is offline, but I am unable to figure out exactly how to do this.
This related question seems to have the answer:
handle the AppDomain.ProcessExit event, which is raised when the application's parent process exits.
however when using the below code the onExit subroutine does not get executed on application closure, probably because I am using the wrong approach to this problem or that Environment.Exit isn't executed when the application exits:
Dim myConn As SqlConnection
Dim cmd As New SqlCommand
Sub Main()
AddHandler AppDomain.CurrentDomain.ProcessExit, AddressOf onExit
End Sub
Public Sub onExit(sender As Object, e As EventArgs)
'Unrelated code removed here.
End Sub
To clarify, I need it to execute onExit when the user closes the application; I am not looking to close the application via a console command.
I've also thought that perhaps I could add a Handle to onExit but I have no idea what to use here.
Is it possible to reliably execute a subroutine or function when the user attempts to close the application via the standard Windows Explorer user interface?
This is a console application, I know this can be very easily done in Windows Forms and thought it would be easy in console. Obviously not.
You need to import the SetConsoleCtrlHandler like in this sample:
Module Module1
Public Declare Function SetConsoleCtrlHandler Lib "kernel32" (Handler As ConsoleCtrlDelegate, Add As Boolean) As Boolean
Public Delegate Sub ConsoleCtrlDelegate()
Sub Main()
SetConsoleCtrlHandler(New ConsoleCtrlDelegate(AddressOf OnExit), True)
Console.WriteLine("Please try to close down...")
Console.ReadLine()
End Sub
Sub OnExit()
MsgBox("Help I'm being closed!")
End Sub
End Module

Debugging VB.Net Service, but getting Source Not Available

I've been googling and trying different things, but I can't seem to figure out a way to debug my service :(
Typically I just use NLog to debug, but the service doesn't seem to want to create log files :( So - I need to debug step-by-step, if possible.
I have used VS to attach to the process (can only do that with no program/solution loaded into VS)... but it says 'Source Not Available'.
Any help would be greatly appreciated.
One way to debug a service is to run it as a non-service. In the following example, use System.ServiceProcess.ServiceBase.Run(New serviceclassname) to run as a service, or the dim and runConsole lines to run as a normal process. Do While True is ugly, but it works for debugging.
Shared Sub main()
System.ServiceProcess.ServiceBase.Run(New serviceclassname)
' use these two lines to debug (instead of the one above)
'Dim ps As New serviceclassname
'ps.runConsole(Nothing)
End Sub
Sub runConsole(ByVal args() As String)
' This is only used for console debugging (even though nothing goes to the console)
Call OnStart(args) ' onStart Override -- if you need it.
Console.ReadLine()
Do While True
Loop
Call OnStop()
End Sub

My program in vb.net often end abruptly. How to find end command?

I think there is an end command somewhere that I miss and got called.
However, how to find it.
If I search for end then there are so many end. End sub, end function.
I just want the program to break just before abruptly end.
Is this because of some out of memory or what?
The program run in debug mode. Suddenly it ends. So it runs 100 threads and then the vb 2012 is still running but the program have stopped. As if someone press the stop button or some end statement reached.
Depending on your technology stack, try overriding the OnExit method:
protected override void OnExit(ExitEventArgs e) {
base.OnExit(e);
}
Set a break point on the base.onExit(e); line and then look in the call stack. Or if you aren't in the debugger, write to a message box the previously called method.
If you want to find End and ignore End Sub etc. you can search using regular expressions (Ctrl+F Alt+E)
End\r?$
Finds End at the end of a line. Interestingly, it's exactly the example in the MSDN regex page

VB.Net App Stuck in Loop

I would just like the program to end itself.
Application.Exit just keeps rolling me back in a loop.
EDITED to Include Code::
Module Module 1
Sub Main()
Sub1()
Sub2()
End Sub
Sub1()
EndSub
Sub2()
End Sub
End Module
EDIT: It seems to be looping back here to Sub ChooseDomain2.. I am including Sub 1 as well.
Sub ChooseDomain1()
Dim DomainName As Object
'Get List of all users on Domain using WinNT
DomainName = InputBox(messageOK, Title, defaultValue)
de.Path = "WinNT://****".Replace("****", DomainName)
If DomainName Is "" Then ChooseDomain2() Else StoreUserData1()
End Sub
Sub ChooseDomain2()
MsgBox("Welcome to the Domain Searcher. Click OK to Auto Search for Domain")
Dim MsgBoxResult As Object = ActiveDirectory.Domain.GetCurrentDomain.Name
MsgBoxResult = InputBox(messageCan, Title, MsgBoxResult)
de.Path = "WinNT://*****".Replace("*****", MsgBoxResult)
StoreUserData1()
End Sub
When it hits end Module it Just starts back from Square one.
Modules don’t execute at all – so it never “hits end module” and never starts “from square one”. Modules merely group methods that can be executed, and Main is a special method that serves as the start of your application.
That said, your code is guaranteed (!) not to execute repeatedly. Also, there is no Application.Exit anywhere in your code so it’s hard to see what you are actually executing. Not the code you showed, anyway.
Note that VB potentially executes code that you didn’t write (code can be auto-generated by the compiler, in particular the application framework) but this doesn’t seem to be happening in your case, and shouldn’t loop in any case. But again, this is impossible to say from the information you have given.
Application.Exit is not required as the console app will quit after it finishes executing the last line in Sub Main. As previously mentioned it is likely you have Sub1 calling Sub2 (or something similar), so set a breakpoint on the start of each sub to find which one is continually being called. Then you can do a search in your code to find where this sub is being called from.