How to handle unexpected shut down of vb.net application - vb.net

I'm developing VB.Net application and i wanted to block users from open another session of the program while they already has one
so i made a value in my DB that changes from Offline to Online and reverse according to the status of the log in
Program Started = Online (In Form Load Event)
Program Closed = Offline (In Form Closing Event)
The problem is : some times the program hang or windows ..... etc so the program don't change the DB value for that user from Online to Offline and this prevent him from opening the application
so how i can handle the unexpected shut down of my program to deal with this case?

you could simply use the built in functionality Single instance application by clicking on your project and on application check Make Single instance application as the screen shot shows

I think you're talking about user session management here. If I understand you correctly, you want to stop any one user from logging in to two instances at the same time rather than there being two copies of your application open at one time (obviously with different users logged into each). If this is the case then it isn't actually that difficult to implement something very basic.
When your user logs on, perform a check to see if they already have a record in your session table. If not, then create one and issue that user with the session id. This id must then be supplied during all operations so that you can check it is valid. So far, so good.
If there is already a record in that session table then invalidate it (delete it, change the status - whatever) so that the old session id can't be used and issue a new one. That way, if your user already has a logged in copy of the app open then start another, the first one will no longer actually do anything useful (don't forget to inform users that an invalid session id is the reason why they can't do anything).
Obviously you will need to persist that session id for the life of the application, but for the love of all that is good, don't put it in a global variable: Pass it as part of the constructor to any object you instantiate which will perform any DB actions. Maybe even wrap it in a class of it's own if you need functionality and that variable or object can be private to your main class.
For example, lets say your main class is a form called frmMain which spawns a login dialog when it starts to capture username and password:
Public Class SessionManagerClass
_dal As New DAL
Private _sessionId As Int
Private _userName As String
Public Sub New(ByVal UserName As String, ByVal Password As string)
_sessionId = _dal.Login(UserName, Password)
End Sub
End Class
Partial Class frmMain
Private _session As SessionManagerClass
Public Sub frmMain_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim loginForm As New dlgLogin
loginForm.ShowDialog()
_session = New SessionManagerClass(loginForm.UserName, loginForm.Password)
loginForm.Dispose()
End Sub
Public Sub btnLaunchChildForm_Click(ByVal sednder As Object, ByVal e As EventArgs) Handles btnLaunchChildForm.Click
Dim frm As New frmChildForm(_session)
frm.ShowDialog()
End Sub
End Class
Partial Class frmChildForm
_session As SessionManagerClass
_dal As New DAL
Public Sub New(ByVal Session As SessionManagerClass)
_session = Session
End Sub
Private Sub DoSomething()
If _dal.SaveValues(_session.SessionId, Value1, Value2, Value3) Then
'All Good
Else
'Something went wrong. Maybe invalid session ID or perhaps you didn't validate your data. Whatever. Handle the problem if you can.
End If
End Sub
End Class
This is in no way working code, just an example of how you might go about it to get you started.

You should attempt to remove the lock from the database when your application exits, but you can't stop someone going into task manager and ending the process. In this case your application does not get any notification of a shutdown and so can't write to the database.
We handle this occurrence by getting users to request an unlock code a secret code which allows them to clear the logged in flag. The unlock code changes each day so if they want one tomorrow they have to ask for another one.

Review your entire approach: you can use the Process class instead.
Dim list() As Process = Process.GetProcessesByName(Process.GetCurrentProcess.ProcessName)
If list.Length > 1 Then
Application.Exit()
End If

Well,
I've created a new solution
another field should be created with name currentsession
when the user open the program it takes a number
and when UN-expected shutdown occur i made a patch to change the current status to offline and the session id to the next number
then I've created a check sub in each save button to check for the current session and if it matches the one in the database it will continue
and if not it will shutdown the program

Related

VB.NET 2019 Open a form from another form

I know this appears to be a rather common topic and should have been resolved from earlier posts. But what I am experiencing still does not seem to have a solution online:
I have a form called ExpenseEntry in which there is a sub procedure called Public Sub OpenVoucher.
I want to call this sub from another form for which I use the following code:
Dim ExpForm As New ExpenseEntry
ExpForm.Show()
ExpForm.OpenVoucher()
While this works well enough, the problem is everytime I click the button, a new window of ExpenseEntry is launched. As per how I have designed the application, repeat windows is not permissible and only one window should be available at a time.
I have tried various methods to restrict more than one form such as by using a variable to control the form but that gives rise to other issues.
If I use Application.OpenForms but still does not resolve the issue.
I have earlier queried in this regard in the following link:
Textbox not refreshing
I am using VB.NET 2019 which does not allow the launch of default instance of a form like Form.Show. I know this is bad practice but it was easier to manage with that till VB.NET 2017.
Now by creating a form variable and launching that creates an infinite loop where I cannot have just one instance of a form running on a single thread.
The really simple way to handle this is to use the default instance of the form type. In VB, since 2005, each form type has a default instance that you can access via the type name. Read here for more info. In your case, you can do this:
'Display the form if it is not already displayed.
ExpenseEntry.Show()
'Activate the form if it is already displayed.
ExpenseEntry.Activate()
'Do the deed.
ExpenseEntry.OpenVouncher()
That said, default instances are a bit dodgy. They do enable beginners to access forms from anywhere in their project under certain circumstances but they also have limitations that can cause issues. Most importantly though, they help to prevent you learning proper OOP by treating forms differently to other types. If you want to do this the way a proper developer would then simply declare a variable to refer to the current instance of the form:
Private expenseEntryDialogue As ExpenseEntry
When it's time to use the form, you simply check whether that variable refers to a usable instance and use it if it does, otherwise create a new one:
If expenseEntryDialogue Is Nothing OrElse expenseEntryDialogue.IsDisposed Then
expenseEntryDialogue = New ExpenseEntry
End If
expenseEntryDialogue.Show()
expenseEntryDialogue.Activate()
expenseEntryDialogue.OpenVoucher()
A third option would be to implement your own singleton, i.e. a type that can only ever have a single instance. You probably wouldn't do that in VB, given that the default instance is basically a thread-specific singleton and does more automatically but, if you wanted to, you could do this:
Public Class ExpenseEntry
Private Shared _instance As ExpenseEntry
'The one and only instance of the type.
Public Shared ReadOnly Property Instance As ExpenseEntry
Get
If _instance Is Nothing OrElse _instance.IsDisposed Then
_instance = New ExpenseEntry
End If
Return _instance
End Get
End Property
'The constructor is private to prevent external instantiation.
Private Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
End Sub
End Class
and then this:
ExpenseEntry.Instance.Show()
ExpenseEntry.Instance.Activate()
ExpenseEntry.Instance.OpenVoucher()

Label Text not updating even when using Refresh, Invalidate, and DoEvents

My code is designed to be a control system for a 2-axis motion system. I have 2 drives that each output a count of their steps. I can read the device, update a property, and update the text field of a label. However, it does not update the form. When I use a message box, I can display the text value being correct, but nothing updates the label.
I'm happy to try any suggestions, but I've been fighting this for about 16 hours and I'm at my wits end - as evidenced by the clear overkill/terrible coding that is shown in the code. I can't understand why it's not updating.
Additionally, a manual button with all versions seen below to refresh a form doesn't update the control.
Direction, recommendations?
Private Sub PositionChanged(ByVal sender As Object, ByVal e As EventArgs)
If TraverseController.InvokeRequired Then
TraverseController.Invoke(
New EventHandler(Of EventArgs)(AddressOf PositionChanged), sender, e)
Return
End If
'RaiseEvent PropertyChanged(TraverseController, New System.ComponentModel.PropertyChangedEventArgs("Position"))
MessageBox.Show(TraverseController.lblLinearDrivePosDisp.Text)
TraverseController.lblLinearDrivePosDisp.Text = CStr(_position)
Application.DoEvents()
TraverseController.lblLinearDrivePosDisp.ResetBindings()
TraverseController.GBDrivePositionDisp.Refresh()
TraverseController.lblLinearDrivePosDisp.Refresh()
TraverseController.Refresh()
TraverseController.Invalidate()
TraverseController.Update()
Application.DoEvents()
MessageBox.Show(TraverseController.lblLinearDrivePosDisp.Text)
End Sub
Assumption: TraverseController is form's class name.
This looks like a VB default form instance issue. It is apparent that you are trying to properly marshal control interaction back to the UI thread by using checking TraverseController.InvokeRequired. However, due to the way these default instance are created, TraverseController.InvokeRequired is creating a new instance of TraverseController on the secondary thread and all subsequent code is modifying that instance and not the one created on the UI thread.
One way to deal with this is to pass a synchronizing control instance to the class where PositionChanged changed method is defined and check that control's InvokeRequired method instead of TraverseController.InvokeRequired. If the containing class is itself a UI control, then use that class instance (Me.InvokeRequired).

Setting the value of a variable in Visual BASIC

Hi i'm new in programming world and I've started my programming by Visual BASIC. I'm trying to set a value of a variable through the program closing event and load the same value in program load event. As example:
At first I tried:
Dim Age as Integer
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
Age = 50
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Textbox1.text = Age
End Sub
But when I close the program and restart it, it resets to zero.
Next I tried "Settings" from properties but if I move my program from one location to another then it also resets everything.
Finally I tried Stream readers and writers to catch the final value but for this I had to attach some text files to the programs which I don't want. Can anyone help me how to solve the following problem with custom class libraries or by something else?
All the variables that you have are run time variables. What that means is it will only have value till your program is running.
If you want to store the data taken from user, you store it in database. You can use any kind of database and connect it to your program, store everything in there. You can also retrieve the values from database to use in system when you restart your program.
If you are new to programming and trying to learn visual basic, start with basic concepts or pick up a book that start with basics. Once you know the basics of programming, you can read about connecting program to database.
The value of age is never going to remain static when the application is shut down unless you keep it in the application settings or some sort of flat file, database etc. The initial value could be set in the application when the form opens or from at static value in application settings, but unless you store the value somewhere other than memory, it will not persist.
What you can do is create a form called module1.vb . in this form declare and set your variables . . .
Example
Public Age As Integer = 50

Passing References through forms vb.net

Is there anyone with very good knowledge in vb.net. I am working on my final semester project. I need to pass objects between forms. I have my codes of two forms here.
http://pastebin.com/xP1LdL3t
http://pastebin.com/fpuY98NT
To connect to the irc server i am using irc.Connect() function. It is perfectly working on my channel form and it is to be called only when users want to connect or on form load. When i double click the online user list a private message form opens. And i am unable to send irc.sendraw command and that form has not called irc.Connect(). It is not supposed to be called in every form. What i want is to use the channel's connection status on other forms so that irc.sendraw command will work.
If i have failed to explain properly please let me know.
It's not clear what you mean by "pass references". There are several ways to communicate between forms. Here are a few:
Declare public variables or properties in one form to be accessed by other forms. If you do this, be sure you are using the proper instance of the form containing the public variables. If you refer to one of these variables before that form is loaded, you'll end up with two instances of the form and things will get confusing.
Use a public method, similar to (1)
Declare global variables in a separate module, to be accessed by any form in the project. (Some people consider this bad manners.)
Pass parameters to and from the forms.
Raise an event to be handled in another form.
basically,
If you want to pass through function in Form 1 to function in Form 2 you can do somthing like this:
Public Class Form1
Dim x As Integer = 2
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Form2.fun(x)
Form2.Show() ' it's optional
End Sub
End Class
and in Form 2 you just get the value as ref:
Public Class Form2
Dim y As Integer 'the variable to get the value of x
Public Sub fun(ByRef x As Integer)
y = x
End Sub
End Class
Hope it can help you, and it's what you wanted.

Storing variables between pages VB WP8

I have an app that records time as you press a button. So leave office, arrive site, leave site and arrive office. I have created a button that allows the user to input what parts have been used on the job. This takes you to another screen where input takes place. I can pass these variables back to the main page but because I'm using:
NavigationService.Navigate(New Uri("/MainPage.xaml?msg=" & textBox1.Text, UriKind.Relative))
It resets the data that was in main page.
When I use the NavigationService.GoBack(), the data remains.
Is there a way to keep that data when I am navigating away from the main page?
Yes, just keep the data/datacontext/object on App level.
So for example, use an object in App.xaml.vb
Public Shared Property MyBook() As Book
Get
Return m_MyBook
End Get
Set
m_MyBook = Value
End Set
End Property
Private Shared m_MyBook As Book
And in the OnNavigatingFrom event on your page (or even before, wherever you like), save that data
Protected Overrides Sub OnNavigatingFrom(ByVal e As System.Windows.Navigation.NavigatingCancelEventArgs)
App.MyBook = currentBook
End Sub
When navigating back to that page, just check if the App.MyBook is null, if it's not, it means you've cached something before navigating, so just read it and set the current datacontext to it (or however you set your data on the page)
Protected Overrides Sub OnNavigatedTo(ByVal e As System.Windows.Navigation.NavigationEventArgs)
If (App.MyBook Is Nothing) Then
Else
currentBook = App.MyBook
End If
End Sub
(since you shared no relevant code, my implementation is rather abstract, but the main point is - keep it in the App.xaml.cs and save/load it when you need it)
Store the value in a variable at App.xaml.cs. App.xaml.cs stores variable throughout the lifetime of the app. If the value is being used frequently in other classes/pages too, then as an alternative you can either create a singleton or a static class and use it as a manager for these values. Cluttering App.Xaml.cs is not a good choice, if you have many values to store.