Can not get Process to die in VB.net - vb.net

I've inherited some VB.net code. My task is to find out why it isn't working. I have 2 applications. The first one
is run as a service, infinitely checking a table to see if there are any tasks to be handled. If it finds one, its supposed to fire off the second application to handle the task then returns to the loop and checks for another. Both these applications are forms but they do not show any windows. The problem I'm having is after the second application is finished, the first application never gets a signal it is done so it is waiting forever, thus it can't move onto the next task. If I go into TaskManager and kill the second application, the first one gets that notification and proceeds as it should. Below is how I am creating the process and waiting for it. I've tried several different ways of creating and waiting for the process (using a Shell/OpenProcess, WaitForSingleObject,etc) and I can't get it to work. I've searched all over the internet, StackOverflow and the MSDN site but nothing I've tried works. I've been messing with this for 2 days!!
Form 1 Load:
Dim ProcessProperties As New ProcessStartInfo
ProcessProperties.FileName = strExeFullPath
ProcessProperties.Arguments = " /project " & l_project
ProcessProperties.CreateNoWindow = True
Dim myProcess As Process = Process.Start(ProcessProperties)
myProcess.WaitForExit()
When Form2 is finished, it does a Me.Close() and Exit Sub in the load subroutine but the process is still showing in the TaskManager and never returns to Form1 so Form1 is in WaitForExit forever. I've tried closing every open file and connection and setting them to Nothing in Form2, Me.Dispose,etc. I've tried Application.Exit as the last line of Form2. That stupid thing will not die!! Why won't it DIE!!??!!
What am I missing?

If I go into TaskManager and kill the second application, the first one gets that notification
Keep your eyes on the ball, the real problem is that this second application is not exiting by itself. And thus myProcess.WaitForExit() isn't going to return. So this is not a problem in your code snippet.
Why the 2nd app doesn't want to quit is completely unclear from your question. Given that it is a Windows Forms app, do keep in mind that there is nobody to click the Close button of the form. Application.Exit() should make it stop, Environment.Exit() is a rude abort that cannot be veto-ed by a FormClosing event handler.

Anyway use this:
ProcessProperties.Arguments = String.Format("/project {0}", 1_project)
No leading space is required and code becomes more readable.
Cheers!

I suspect Form2 is trying to show some modal dialog (maybe a message box, maybe an unhandled exception box) before quitting. Since App2 is launched by App1, which is a service, Form2 cannot interact with the desktop and just sits there waiting for a button click that will never happen.
Try to allow the App1 service to interact with the desktop (you can find that option on the Log On tab of the service properties dialog box) and check if Form2 actually pops up a dialog before quitting.

Related

Abort running code on form when form is disposed?

I have a large, complex client application I am now maintaining. For security purposes, it requires a constant connection to the server. It has a thread that is handling all the socket communication between itself and the server.
The way it's currently written, if there is any communication issue with the server, the communications thread fires off an event that closes and disposes all open forms and returns the user back to the initial connection/logon screen.
The problem I'm having is that sometimes this communication issue can happen in the middle of the execution of a function (such as one that is blocked by a modal form). When the modal form and parent form are disposed of, the function still finishes running, often leading to exceptions and errors.
For example, the report form has a function that opens a dialog, accepts input, and then runs a report based on that input:
'Inside the class for the ReportForm:
Private Sub RunReport()
'Run code that requests list of reports from server
_ReportSelectionForm = New frmReportSelection(reportList)
_ReportSelectionForm.ShowInTaskbar = False
Me.AddOwnedForm(_ReportSelectionForm)
_ReportSelectionForm.ShowDialog(Me)
'the following code will still execute when ReportForm (Me) is disposed:
username = _ReportSelectionForm.txtUsername
If (_ReportSelectionForm.DialogResult = Windows.Forms.DialogResult.Ok) Then
'Run code
ElseIf (_ReportSelectionForm.DialogResult = Windows.Forms.DialogResult.Cancel) Then
'Run different code
End If
'etc
End Sub
So, if the Report Selection Form is open and the communications thread times out communications with the server, the communications error event fires which closes and disposes the ReportForm. This, in turn, closes the _ReportSelectionForm Dialog. When this happens, even though the parent form has been disposed, finishes running the code after "_ReportSelectionForm.ShowDialog(Me)". This throws an exception on "_ReportSelectionForm.DialogResult" or "_ReportSelectionForm.txtUsername" because _ReportSelectionForm is Nothing.
If this was one isolated place, I could handle this with a few extra checks before continuing to run the function, but it's all over this large program.
What's the best way to handle this? Can I abort code execution on a form that I'm closing?
Hopefully I explained it adequately. My Google-Fu is failing me. Thanks in advance.
Change your code to:
Dim result as DialogResult = _ReportSelectionForm.ShowDialog(Me)
If (result = Windows.Forms.DialogResult.Ok) Then
'Run code
ElseIf (result = Windows.Forms.DialogResult.Cancel) Then
'Run different code
End If
That way you're not referencing the ReportSelectionForm.

Difference between form.close and application.exit

I am recently out of school, working my first job as a programmer. We have a user-reported bug that is occurring when our application timeout timer closes the application. I'm pretty sure I've narrowed it down, but am curious as to why the original programmer would have done this, if it's good coding practice, and if so, I am curious if anyone has a way to handle this. We are getting a post-closing system error, as it occurs after the main form closes, so we don't get any exception log input.
The close functionality of the timeoutTimer_tick handler does the following:
For iCount As Int16 = Application.OpenForms.Count - 1 To 0 Step -1
Try
Application.OpenForms(iCount).Close()
Catch
End Try
Next
Try
Application.Exit()
Catch ex As Exception
End Try
The program is set with the application property to close when the main form closes (not ALL open forms are closed). This makes me wonder why we're looping through each form and closing them individually, and then calling Application.Exit()
I'm pretty sure our error is because of the Application.Exit call after all open forms are closed. It doesn't see the main form, as it was closed during the loop, and throws an error. I feel like we should be using one or the other, but not both.
Any input or advice? Which is better, or are either better (or should this code work without error, and I am simply wrong).
Thanks
In WinForms you have a Shutdown Mode setting (Project Properties>Application Tab)
This allows you to specify When startup form closes or When last form closes
So logically you should not need Application.Exit .If you do then there is some other object hanging around in memory that you need to dispose of (something started on a thread / background worker etc)
So If you have the startup form setting:
[StartupFormName].Close
or if you have the last form setting:
Do While My.Application.OpenForms.Count > 0
My.Application.OpenForms(0).Close()
Loop

Keep VB.NET application running in the background after base form closed

I am writing an application in VB.Net in which a user can schedule emails to be sent in the future. Is there a way to keep my listener thread running in the background after the base form on the application is closed? I would also need to start up the listener when the system boots, but wouldn't want any forms to open at that time.
Example (desired) functionality: I open the application in the morning and schedule three emails, one of which should be sent in three hours, and the other two of which should be sent tomorrow morning. I close the application. In three hours, the first one sends. At the end of the day, I shut down my machine. When I turn it back on tomorrow morning, the other two are sent without me ever opening the application.
I am thinking I need to separate the listener into a service, but want to make sure there isn't an easier way before going down that road.
If I do end up having a separate service and application, can I create an installer that will install both at once?
In the options of your project, set the “Startup Object” to “Sub Main” instead of of a form name. You might have to disable the setting “Application Framework” first.
Now you have to launch the form manually because it’s no longer done automatically, but on the other hand you can now control when to launch it, and your application will exit when it reaches the end of the Main method (or when it’s quit explicitly) rather than when the form closes.
If all you want is to keep the program running, you could supply it with the definition for a TaskBar icon, and represent state in your application using the icon's graphic. It would appear over on the right next to the system clock.
Then it's just a matter of reconfiguring your development project so that the application close event is triggered off that icon's menu instead of off the fact that the form is closed.
Use a NotifyIcon control and when the user close the mainform capture the OnClosing Event to Ask the Question if he want to minimize to the tray or exit the application.
Here is the documentation of NotifyIcon control from Microsoft:
NotifyIcon Control
I have a possible solution for you here. In the form closing event you can place the following code:
Private Sub Form1_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Me.Visible = False
e.Cancel = True
End Sub
This will hide the form and allow it to run in the background until you shutdown the computer. To handle the restart and then send emails I'd suggest adding the emails to be sent to a text file that can be accessed after restart and then adding the program to startup. An even better solution might be to have 2 programs, one that is on startup and is always hidden that checks the text file every 15 minutes (for example) and a second program that is launched when a new email is to be added to the list and it appends the text file with new emails to be sent.
(Sorry if i am wrong, just proposing a probable solution here)
I think attaching a simple db to hold the email sending schedule information/date-time and loading the application at startup with Notification Icon (or without Notification Icon but with a shortcut to show user interface/form to feed the emails and schedule information/date-time, if required + BackgroundWorker, if you want the application to go to sleep mode and wake it later to send first scheduled email; after X hours). After sending first email update the db then exit the application. Check the db on startup to send the first email or go to sleep mode if pc boots before sending first email. But, if first email is already sent then send other two scheduled emails (check db date-time). This should do the job...
:)

Why does my form appear behind everything?

I have a program where I need to do some initial work before calling the form, so I disabled the Application Framework setting and wrote my own Main function with a call to Application.Run(myForm) when it's time to run the form.
Everything was working fine, no problems, but now I have need of some other service before opening the form. Rather than add all that code to this program, it has all been moved into its own executable. This second program can edit files that the first program will use, so I need the first program to wait so that it will read up those changes (should they be made). I suppose could just as easily use the Shell function, but for various reasons I'm creating my own Process object and calling it/waiting on it through that.
Anyway, I make this call to the second program some time before the Application.Run call. The first program waits its turn, and I can interact with the second program successfully, no trouble at all. But when it's done, the window for the first program is hidden behind any other windows that are on the screen. This doesn't happen in XP, only in Vista (and maybe 7, but I haven't confirmed yet). I've already tried manually forcing the form to appear in front, minimize then maximize, get focus, etc, but nothing brings it to the front unless the user manually clicks on it with the mouse.
What am I doing wrong? Why does this behavior occur? I know it has something to do with waiting for the executable to finish, because if I don't force the first program to wait everything is fine (other than it not waiting). I can circumvent the issue by calling the second program in the Load event of the form, but then I have to read the file a second time to catch the changes instead of reading it once, and it also looks bad because the form is being drawn really slowly while the second program is sitting there.
If anyone has any input, I'd appreciate it.
This isn't really an answer to why you're experiencing this behaviour, but a simple workaround would be to temporarily set the form's TopMost property to True in the load event. Then, depending on how intrusive you want that to be, you could either reset it under a short timer or wait for say the MouseEnter event to fire.
There are another topic in this site about that, but I not got the link. This problem seems be a bug into .NET framework. The API below (VB.NET example) works for me in windows XP and 8.1. Don't tested in other versions of Windows.
<Runtime.InteropServices.DllImport("user32")> _
Public Shared Function SetForegroundWindow(hwnd As IntPtr) As Integer
End Function
Private Sub Form_Load(sender As Object, e As EventArgs) Handles Me.Load
SetForegroundWindow(Handle)
End Sub

How could my Application form in vb be closing by itself?

I have a form in a Pocket PC app that is set to be the Application form using:
Application.Run(New frmMain())
Somehow this form is getting closed for no reason while working on another form. No closing event is fired and nowhere in my code can you close the main form anyway. It is only closed by clicking the OK button at the top right of the window. When this is clicked, the user is prompted if he/she really wants to close the application. However, this is not occurring either.
Basically, I am on another form which adds a new record to the database. After adding the record the gotFocus event is somehow called for frmMain. When the code in the gotFocus event reaches a reference to a control on the form, there is an exception that states that the object is disposed.
When I bypass the code in the gotFocus event, the application just closes completely. I verify this by checking that it is not running in the device's memory.
I have been stepping through code for 2 hours and I have absolutely no idea why this could be occurring. Anyone possibly have a tip?
This sounds as an exception being raised anywhere. Maybe an exception on another thread? Look at the output window to see what it says.