I step through this code and find out that the function is not only never called but the rest of the myBase.Load never completes what is going on here.
All outside references are displayed now. Program never hits the lines surrounded in ** and does run frmMain_Load as first item. the stepthrough icon does land ON the line that starts with reader= but never calls runAsIsQuery (breakpoints don't catch and stepthrough just evaporates). then it shows me frmMain without proccessing any other code from frmMain_Load nor from runAsISQuery
Private Sub frmMain_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
sqlstring = "SELECT Nickname FROM tblBikeInfo"
reader = sql.runAsIsQuery(cnn, sqlstring) 'never fires
**If 1 = 1 Then**
'ummmm never comes back here either
End If
Extra details asked for about the other references these are in frmMain as global vars
Dim reader As OleDbDataReader
Dim sql As OLEDB_Handling 'custom class
Public cnn = MotorcyleDB.GetConnection
Function from Custom Class (OLEDB_Handling)
**Public Function runAsIsQuery(connection As OleDbConnection, SQL As String) As OleDbDataReader**
Dim reader As OleDbDataReader
Dim command As New OleDbCommand(SQL)
command.Connection = connection
Try
connection.Open()
reader = command.ExecuteReader()
Return reader
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Function
Connection string class called (MotorcyleDB)
Public Shared Function GetConnection() As OleDbConnection
Return New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\************\Documents\Visual Studio 2010\Projects\MotorcycleMinder\MotorcycleMinder\MotorcycleServiceLog11.accdb")
End Function
I found this:
http://blog.adamjcooper.com/2011/05/why-is-my-exception-being-swallowed-in.html
This is a snippet from the site.
If these conditions are met:
You are running on a 64-bit version of Windows (whether your application is built for 32-bit or 64-bit doesn’t matter; only the bit
depth of the OS)
You are building a WinForms app
You are debugging the application with Visual Studio (using default
options for Exception catching)
Your main form has a Load event handler
During the execution of your Load handler, an exception occurs
Then:
The exception will be silently swallowed by the system and, while your
handler will not continue execution, your application will continue
running.If you wrap your handler code in a try/catch block, you can
still explicitly catch any thrown exceptions. But if you don’t, you’ll
never know anything went wrong.
Note that all of the conditions must be met. If, for instance, you run
the application without debugging, then an unhandled exception still
be correctly thrown.
There is also a workaround on the site. But I would put the code in a try catch block, or put the entire thing in the Initializer/Constructor.
Related
I am working in VB and when the end user clicks on a button, I want to show a “Please wait” window (no progress update necessary) and trigger the process in the background on another thread as it might take a while to complete. I understand BackgroundWorker is the recommended approach for this, and although I have previously set up a BGW on a windows forms application, I am new to WPF and having a hard time understanding the differences.
In order to reuse some of my code, I have written a function (“DbOperation”) that executes a SQL stored procedure (from parameter) and returns a data table (or NULL if no output), and it seems to work well everywhere except in concert with my BGW.
I understand UI should only be affected by the main thread, and background threads should not touch the UI, and the BGW thread should call the long-running process.
Private Sub btnProcessReports_Click(sender As Object, e As RoutedEventArgs) Handles btnProcessReports.Click
'Set up background worker
bgw.WorkerReportsProgress = False
bgw.WorkerSupportsCancellation = False
AddHandler bgw.DoWork, AddressOf bgw_DoWork
AddHandler bgw.RunWorkerCompleted, AddressOf bgw_RunWorkerCompleted
'Show please wait window
f.Label1.Text = "Importing web reports. Please wait."
f.Show()
'Start the work!
bgw.RunWorkerAsync()
End Sub
Private Sub bgw_DoWork(sender As Object, e As DoWorkEventArgs)
'Set current thread as STA
Thread.CurrentThread.SetApartmentState(ApartmentState.STA)
'Trigger job
Dim Qry As String = "EXEC [msdb].[dbo].sp_start_job N'Import Online Payment Portal Reports';"
DbOperation(Qry)
End Sub
Public Function DbOperation(ByVal qry As String, Optional ByVal type As DatabaseQueryReturnType = DatabaseQueryReturnType.NonQuery) As Object
Dim objDB As New Object
Dim dt As DataTable
Dim da As SqlDataAdapter
OpenConnection()
Dim cmd As New SqlCommand(qry)
cmd.Connection = con
If type = DatabaseQueryReturnType.DataTable Then
dt = New DataTable
da = New SqlDataAdapter(cmd)
Try
da.Fill(dt)
Catch ex As Exception
MessageBox.Show("Error retrieving data from database: " & ex.Message.ToString)
End Try
objDB = dt
dt.Dispose()
CloseConnection()
Return objDB
ElseIf type = DatabaseQueryReturnType.NonQuery Then
Try
cmd.ExecuteNonQuery()
Catch ex As Exception
MessageBox.Show("Error executing nonquery: " & ex.Message.ToString)
End Try
objDB = Nothing
CloseConnection()
Return objDB
End If
Return objDB
End Function
When I try running the program, it gives me “The calling thread must be STA, because many UI components require this.” on the line that calls my function. After a bit of research, I learned that you have to call SetApartmentState() before the thread is started, but this doesn’t make sense since the recommended code seems to be:
Thread.CurrentThread.SetApartmentState(ApartmentState.STA)
After adding this line, I then get “Failed to set the specified COM apartment state” on that line of code.
I have also tried commenting out the messagebox lines in the function in case it was trying to open the messageboxes on the UI thread, but it had no impact and I still got the same errors.
What am I missing in my code to get the function to run on the BGW thread?
I'm trying to connect to my database and I'm getting this error message (ex):
I've another function which opens DB and load some data, it works fine without any error... But when I try to use this, it returns me this error, the line 175 is "cn.Open()".
My connection string and Local_DB is both same as other functions which are working without errors.
Private Sub AtualizaClientes(ID As Integer)
' Local da DataBase
Dim Local_DB As String
Local_DB = "C:\Users\Heitor BASAM\Desktop\Sistema\DataBase_Sistema.accdb"
Try
Dim cn As New OleDb.OleDbConnection
cn.ConnectionString = $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={Local_DB}"
cn.Open()
cn.Close()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Glad you fixes your problem! Just a few bits to tidy up the code.
Always use Using...End Using with database objects that expose a Dispose method. They may be using unmanaged objects and their dispose methods must run to release these resources. The End Using takes care of this for you even if there is an error.
You can let the error bubble up to the calling code, user interface code. Wrap the call to AtualizaClientes in a Try...Catch...End Try
Private Sub AtualizaClientes(ID As Integer)
Dim Local_DB = "C:\Users\Heitor BASAM\Desktop\Sistema\DataBase_Sistema.accdb"
Using cn As New OleDb.OleDbConnection($"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={Local_DB}")
cn.Open()
End Using
End Sub
EDIT
You would add the Try...End Try to the UI code. Example...
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim id As Integer = 7
Try
AtualizaClientes(id)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
I figured out the problem! I've a function when a especify textbox is changed, it calls this "AtualizaClientes" function. The problem is, when you load the form, it runs a "TextChanged" event in every textbox and trys to run the database before loading it. This was causing the error message.
To solve this problem, I made a boolean variable which returns true after loading the database. So, I changed my textchanged event to run only if this variable is true.
I have another question considering events and exceptions
A small introduction to my project: I'm working in a 3 layer architecture, so I have a GUI(form), BLL(Business logic layer) and a DAL(data acces layer).
So my GUI is linked to a BLL which is connected to several DAL classes. For example my BLL has a class clsCSV (which reads and writes CSV files)
I now want to raise events and/or catch exceptions from this class to inform the user and log exceptions. There are 3 events: "ErrorLoad", "ErrorWrite", "Ready"
Public Class clsCSV
Public Sub New()
End Sub
Public Function Load(sFilePath As String)
Dim oFileHelper As New DelimitedFileEngine(Of clsItem)
Dim oList As New List(Of clsItem)
' Load a CSV file
Try
oList = oFileHelper.ReadFileAsList(sFilePath)
Catch ex As Exception
'RaiseEvent ErrorLoad("")
clsErrorLog.Log(ex)
Finally
End Try
' If the list is empty return nothing
If Not IsNothing(oList) Then
Return oList
Else
Return Nothing
End If
End Function
Public Sub Write(sFilePath As String, oList As List(Of clsTranslatedItem))
Dim oFileHelper As New DelimitedFileEngine(Of clsTranslatedItem)
oFileHelper.WriteFile(sFilePath, oList)
RaiseEvent Ready()
End Sub
Public Event ErrorLoad(ByVal sender As Object, ByVal e As EventArgs)
Public Event ErrorWrite(sMessage As String)
Public Event Ready()
End Class
There is a try-catch in my public sub load which catches any exception and logs it to a text file by calling clsErrorLog.log(ex) which then calls this class and logs the error:
Public Shared Sub Log(ex As Exception)
Try
Dim oBestand As New System.IO.StreamWriter(My.Computer.FileSystem.SpecialDirectories.Desktop & "\ErrorLog.txt", True)
If Not IsNothing(oBestand) Then
oBestand.WriteLine("")
oBestand.WriteLine(My.Computer.Clock.LocalTime.ToString)
oBestand.WriteLine(ex.Message)
oBestand.WriteLine(ex.StackTrace)
oBestand.WriteLine("_________________________________________")
oBestand.Close()
End If
Catch exc As Exception
End Try
End Sub
This works fine, but now I want to inform the user that an error occured, so I was thinking to raise an event called "ErrorLoad" (in clsCSV) and catch this in my BLL. But what can I do then? Add a sub that handles this event, which then raises an event in the BLL, caught by the GUI? or is this a long way to this?
I also want to do this for the other events offcourse. But the whole event system in the layered architecture is a bit confusing.
Anyone who can enlighten me?
Thanks in advance!
Without knowing the implementation details of your UI, I can only give you some general advice.
You need some kind of two directional communication between your GUI and your BLL. For example in WPF this is usually done using INotifyPropertyChanged interface and the event it defines.
So the BLL raises a event and the GUI is listening. The basically only has the task of informing the GUI that it has to check a specific property or function or anything like this from the BLL. The rest is up to the GUI to do so and inform the user.
I wouldn't do that using exceptions. These are there to handle the error path of specific functions. This path is done once your BLL noticed the error and prepared it for the UI handling.
I am using a Windows form application due to added security measures i have to work around for session in my application.Currently i am using a Timer to achieve the functionality I am able to close the form but i need to again restart the application to return to the login form.I am using the below code
Private Sub sessionTimer_Tick(sender As Object, e As EventArgs) Handles sessionTimer.Tick
Try
Me.sessionTimer.Stop()
Me.sessionTimer.Enabled = False
Process.Start(Application.StartupPath + "\application.exe")
Process.GetCurrentProcess().Kill()
Catch ex As Exception
End Try
End Sub
I am getting an exception when i use the above method and it doesn't serve the purpose,also i have already tried using Application.Restart didn't work out.Please help i am new to windows form. Also adding to this in order to reset the timer i am using the below code.
Private Sub frmMain_MouseMove(sender As Object, e As MouseEventArgs) Handles MyBase.MouseMove
Me.sessionTimer.Stop()
Me.sessionTimer.Start()
End Sub
But this doesn't seem to work the main form has menu's which i am using to navigate to other forms so the idle time should not include the time spent in other forms which are opened via the menu's. What event should i use in frmMain to handle this problem.Thanks
Just let the Framework do the work.
Application.Restart()
If your session Timer fires from a background thread (maybe you use System.Timers.Timer instead of System.Windows.Forms.Timer) you propable have to sync with your main thread.
Me.Invoke(new MethodInvoker(Addressof Application.Restart))
If Application.Restart does not work there is propably something wrong with your app. You should try the following.
If you created threads, be sure they are created with "thread.IsBackground = true" otherwise they will keep your process open
Stop your timers and background workers.
Be sure you don't have forms that handle the FormClosing event and set e.Cancel = true. In that case you have to take e.CloseReason into account.
User Mark Hurd posted a great post about what happens during Application.Restart, have a look here
Iam using this code to restart my application. It works very well.
System.Diagnostics.Process.Start(Application.ExecutablePath) 'First start a new instance
Me.Close() 'Close the current application
If this doesnt work. I think there is no way around than using another application which restarts the Process. Here is a code example (second application)
Private Shared Sub RestartApp(pid As Integer, applicationName As String, arguments As String)
' Wait for the process to terminate
Dim process__1 As Process = Nothing
Try
process__1 = Process.GetProcessById(pid)
process__1.WaitForExit(1000)
' ArgumentException to indicate that the
' process doesn't exist?
Catch ex As ArgumentException
End Try
Process.Start(applicationName, arguments)
'Arguments?
End Sub
Source of the code
My goal here is to get stack trace information from a dynamically loaded assembly. If the dynamically loaded assembly just throws the error back to the caller, the stack trace information doesn’t tell you the location in the dynamic assembly where the error occurred. If I throw my own exception, passing in the original exception, it will get added as an inner exception and will have the information need. I’m trying to avoid changing all my dynamic assemblies to throw new exceptions. Does anybody know a better way to get the stack trace information from a dynamically loaded assembly?
Public Class ErrorPlugin
' Example Function from plug in DLL
Public Function SimpleExample() As Double
Dim RentedUnits As Double = 42
Dim NumberUnits As Double = 0
Try
' Just need to generate exception
Return RentedUnits \ NumberUnits
Catch ex As Exception
' Give's me no Stack Trace infomation.
'Throw
' This will give me Stack Trace infomation,
' but requires adjusting all the plugins.
Throw New Exception("Stop dividing by zero.", ex)
End Try
End Function
End Class
Imports System.Reflection
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim rpt As Object
Dim r As Double
Try
rpt = LoadReport("C:\ErrorPlugin\bin\Debug\ErrorPlugin.dll")
r = rpt.SimpleExample()
Catch ex As Exception
MsgBox(ex.Message & vbCrLf & ex.StackTrace)
If ex.InnerException IsNot Nothing Then
MsgBox(ex.InnerException.StackTrace)
End If
End Try
End Sub
Public Function LoadReport(ByVal FileName As String) As Object
Dim m_ReportAssembly As [Assembly]
Dim m_ReportClass As Type
Dim rpt As Object
Try
m_ReportAssembly = Assembly.LoadFrom(FileName)
For Each m_ReportClass In m_ReportAssembly.GetTypes
If m_ReportClass.Name.ToLower = "ErrorPlugin".ToLower Then
rpt = Activator.CreateInstance(m_ReportClass)
Exit For
End If
Next
Return rpt
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Function
End Class
Can you see what happens if you just Throw, not Throw ex? From memory, "throw ex" does a copy while "throw" actually rethrows the caught exception. I guess your "throw ex" is effectively resetting the stack trace to your local code.
MSDN says if you're rethrowing exceptions you should add value to it by wrapping it in a new exception, otherwise you might as well not bother with try/catch in your example.
Do you have the debug symbols for these external DLL's? If you look at the stack trace, and it reads "External Code", that should be expanded into the DLL stack if you have the DLL debug symbols loaded while debugging, since the symbols will provide your debugger with the necessary info to walk the stack.
Either do this by manually loading the symbols, via the Modules Window in the Debug menu, or running against a debug build of the DLL.