Closing Windows SplashScreen when lost focus throws Win32Exception - wpf

In our application we open a splashscreen for the intial loading of the login screen, this logonscreen is shown async.
when we close the splashscreen sometimes we get following error:
System.ComponentModel.Win32Exception was unhandled. Message="The operation completed successfully"
I figured out this has something to do with loosing focus and it's a known bug in .net 3.5.
However I did not find a solution to fix this in my code. And we are unable to upgrade the application to 4.0.
I allready tried: Application.Current.MainWindow.Focus() but this doens't work since i'm not on the correct thread due to the async call
I hope somebody had this problem before and can provide me a working fix for this bug.
This is the code and the splashscreen comes from system.windows.dll:
Public Sub New(ByVal splashResourceName As String)
logonSplash = New SplashScreen(splashResourceName)
logonSplash.Show(False)
InitializeComponent()
GetAllInfo()
DataContext = context
End Sub
Private Sub LoginDialog_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
'Focus()
If logonSplash IsNot Nothing Then
logonSplash.Close(Nothing)
logonSplash = Nothing
End If
txtPassword.Focus()
End Sub

Related

Fix a System.TypeInitializationException Error in SqlConnection with VB.net App

I have developed a program for a user to search a database. I did this on my local PC and it worked fine. I move the app to the server where it would used, changed the Data Source and I get an error (below). I used the name of the Server Name shown on the start up of SQL2008 R2 as the Data Source, which is the same thing I did on my local PC. I built a simple program just to test the Connection (below). I have tried different things, read everything I could find on the error, but no good.
Here is the code I'm using to test the connection:
Imports System.Data.SqlClient
Imports System.IO
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim MyConnectionString As String = " Data Source=MenClub02;Database=eCom_Email;Integrated Security=SSPI"
Using connection As New SqlConnection(MyConnectionString)
connection.Open()
MsgBox("State: {0}", connection.State)
MsgBox("ConnectionString: {0}", connection.ConnectionString)
End Using
End Sub
End Class
The following error shows up on the Using connection As New SqlConnection(MyConnectionString) line:
System.TypeInitializationException
HResult=0x80131534
Message=The type initializer for 'System.Data.SqlClient.SqlConnection' threw an exception.
Source=System.Data

Catch-all Exception Handler for non-UI Threads in WPF

Specifically, I'm using WPF with MVVM. I have a MainWindow, which is a WPF Window where all of the action happens. It uses a corresponding View Model class for its properties, commands, etc.
I have set up main UI thread and non-UI thread exception handlers in Application.xaml.vb StartUp like this:
Private Sub Application_DispatcherUnhandledException(sender As Object, e As Windows.Threading.DispatcherUnhandledExceptionEventArgs) Handles Me.DispatcherUnhandledException
' catches main UI thread exceptions only
ShowDebugOutput(e.Exception)
e.Handled = True
End Sub
Private Sub Application_Startup(sender As Object, e As StartupEventArgs) Handles Me.Startup
' catches background exceptions
Dim currentDomain As AppDomain = AppDomain.CurrentDomain
AddHandler currentDomain.UnhandledException, AddressOf UnhandledExceptionHandler
AddHandler System.Threading.Tasks.TaskScheduler.UnobservedTaskException, AddressOf BackgroundTaskExceptionHandler
End Sub
Sub UnhandledExceptionHandler(sender As Object, args As UnhandledExceptionEventArgs)
Dim ex As Exception = DirectCast(args.ExceptionObject, Exception)
ShowDebugOutput(ex)
End Sub
Sub BackgroundTaskExceptionHandler(sender As Object, args As System.Threading.Tasks.UnobservedTaskExceptionEventArgs)
Dim ex As Exception = DirectCast(args.Exception, Exception)
ShowDebugOutput(ex)
End Sub
This part works
When I try to test this out, by deliberately throwing an exception, it works. It is actually in the View Model in the Sub that handles the Select All button click.
The button:
<Button Content="Select All" Height="23" Width="110" Command="{Binding SelectAllCommand}" />
The Command where I'm throwing the exception that is successfully caught:
Private Sub SelectAll()
Throw (New Exception("UI Thread exception"))
SetAllApplyFlags(True)
End Sub
This part doesn't work
There's another button in the same MainWindow similarly bound to a command. However, it uses a Task to perform its work in the background, and an exception thrown in there does NOT get caught by my catch-all handlers.
Private Sub GeneratePreview()
' run in background
System.Threading.Tasks.Task.Factory.StartNew(
Sub()
' ... stuff snipped out, issue is the same with or without the rest of the code here ...
Throw (New Exception("Throwing a background thread exception"))
End Sub)
End Sub
There are several similar questions, but I haven't been able to actually figure out my answer from them. The AppDomain UnhandledException seems to be the answer in most cases, but it isn't for mine. What exactly do I have to add to be able to catch an exception that might be thrown in a non-UI thread this way?
What I ended up doing
I could not get the TaskScheduler.UnobservedTaskException event to call my event handler when I was handling it in Application.xaml.vb. But I took hints from the other answer, and I'll mark it as the answer because it ultimately helped.
However, it is not at the application level, so if this was a larger application, I'd have to duplicate this in every instance where I used a Task. This wasn't really what I was looking for, but not willing to spend more time on it now.
I ended up putting a try-catch inside the Task. In the catch, I was able to use Dispatcher.Invoke to still display a user-friendly dialog with the exception info.
Private Sub GeneratePreview()
' run in background
System.Threading.Tasks.Task.Factory.StartNew(
Sub()
Try
' ... stuff snipped out, issue is the same with or without the rest of the code here ...
Throw (New Exception("Throwing a background thread exception"))
Catch ex As Exception
Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, DirectCast(
Sub()
HRNetToADImport.Application.ShowDebugOutput(ex)
End Sub, Action))
End Try
End Sub)
End Sub
TaskScheduler.UnobservedTaskException Event is what you want to subscribe from App start.
https://msdn.microsoft.com/en-us/library/vstudio/system.threading.tasks.taskscheduler.unobservedtaskexception(v=vs.100).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1
Occurs when a faulted Task's unobserved exception is about to trigger exception escalation policy, which, by default, would terminate the process.
This AppDomain-wide event provides a mechanism to prevent exception escalation policy (which, by default, terminates the process) from triggering.
NOTE: The event might not be fired right away (possible a few second delay). You could imagine there's some operations of call stack bubbling and context switching of normal exception operation before ended up reaching the UnobservedTaskException event.
One thing I want to point out is that, it's a must to wrap your whole application with generic exception handler to prevent application being terminate. But, please do remember that it's also a must to implement proper exception handling to all paths that might throw exception.
Sandra,
I read cscmh99 proposition,
took your code,and try to run, and it works !
I mean you can subscribe to TaskScheduler.UnobservedTaskException.
Then you will catch UnobservedException
But you won't catch observed exceptions
Observed exceptions are those from Tasks waited with .Wait() or .Result
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
' Here follows an Unobserved Exception
System.Threading.Tasks.Task.Factory.StartNew(
Sub()
Throw (New Exception("Throwing a background thread exception"))
End Sub)
' Here follows an ObservedException
' ObservedException because there is call to .Wait() (or .Result)
' You can't use UnobservedException for that one
Dim t As Task = System.Threading.Tasks.Task.Factory.StartNew(
Sub()
Throw (New Exception("Throwing a background thread exception"))
End Sub)
t.Wait()
End Sub
Here is code to working solution : http://1drv.ms/1XOvTbK
Regards
Sandra,
There is a way to catch the exception from inside your background Task.
I admit my solution is not global, but at least it catches and prevents crash !
Private Async Sub Button_Click(sender As Object, e As RoutedEventArgs)
Dim t As Task = Task.Factory.StartNew(
Sub()
' ... stuff snipped out, issue is the same with or without the rest of the code here ...
Throw (New Exception("Throwing a background thread exception"))
End Sub)
Try
Await t
Catch ex1 As Exception
Debug.WriteLine("Exception from inside task " & ex1.Message)
End Try
End Sub
Think it could help, may be you, may be others.

Backgroundworker - Cannot use generated bitmap after completion

Hi I am having trouble assigning the image data that was generated inside my BackgroundWorker's DoWork handler, to an image object after processing is complete. I am getting an error stating that "the calling thread cannot access this object because a different thread owns it". The erroring line is
PreviewImage.Source = Bmp
My DoWork handler code is as follows:
Private Sub QueryForAssociatedData(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BW_DrawSideBarImage.DoWork
Using Context As New MyContext
Try
Dim bmp2 As New BitmapImage
bmp2.BeginInit()
bmp2.StreamSource = New MemoryStream(SidebarImageBytes)
bmp2.EndInit()
'Dispatcher.Invoke(Sub() PreviewImage.Source = bmp2)
e.Result = bmp2
Catch ex As Exception
End Try
End Using
End Sub
I expected to be able to expose the created image in RunWorkerCompleted in the usual way but it didnt seem to work:
Private Sub FinishDrawingSidebar(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BW_DrawSideBarImage.RunWorkerCompleted
Dim Bmp As BitmapImage = TryCast(e.Result, BitmapImage)
PreviewImage.Source = Bmp
End Sub
I also tried
Dispatcher.Invoke(Sub() PreviewImage.Source = Bmp)
in DoWork and in RunWorkerCompleted but the same error appears. If I just return Nothing instead of Bmp then there is no problem so I am assuming the Bmp is the object being complained about.
Please let me know what stupid thing I am doing wrong. Thanks!
As long as the BitmapImage is still modifiable, it stays associated with the thread that created it. And using it in another thread will throw the exception you got.
Simple to fix, you need to freeze it so it becomes thread-safe. Add this line of code to your worker:
...
bmp2.EndInit()
bmp2.Freeze(); // <== added

VB.net GetProcess Options

I currently have the following code that runs an external Virtual Application(created with Cameyo), when the Run Button is clicked. I also have a Timer that checks ever second to see if the Process(virtual exe program) is still open. In theory the GetProcessByName should find the program listed in the Task Manager right? However it doesn't! I even tried using GetProcessByName to Kill the process (one another button clicked), but the processs is not killed.
Could it be because I virtualized the program that I want GetProcessByName to recognize? Therefore the name of the Task in the Task Manager is not correct?.
Example
The program started: SmartDefrag.virtual.exe
It runs
The Task Manager shows it as SmartDefrag.exe
Use GetProcessByName("SmartDefrag.exe") to Disable Run Button if process SmartDefrag.exe running.
Does not Disable Run Button.
Could I use TITLE OF PROCESS? Or will the PID be the same everytime the process opens? Any other options?
Code:
Private Sub SMDFRunAppMainButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles SMDFRunAppMainButton.Click
' LoadingSMDFMainButton.Visibility = Windows.Visibility.Visible
Dim downloadlocation As String = (currentpath & "\1stAidApps\SMDF\SmartDefrag.virtual.exe")
My.Settings.FileLoad = downloadlocation
Try 'Errors on Cancel
dp1Timer = New DispatcherTimer
dp1Timer.Interval = TimeSpan.FromMilliseconds(1000)
AddHandler dp1Timer.Tick, AddressOf TickMe1
dp1Timer.Start()
fileload = My.Settings.FileLoad
Process.Start(fileload)
Catch ex As Exception
MessageBox.Show("Failed to launch. Please try again.", "Launch Failed")
End Try
End Sub
Private Sub TickMe1()
Dim p() As Process
p = Process.GetProcessesByName("SmartDefrag.exe")
If p.Count > 0 Then
LoadingSMDFMainButton.Visibility = Windows.Visibility.Hidden
SMDFRunAppMainButton.IsEnabled = False
Else
SMDFRunAppMainButton.IsEnabled = True
End If
End Sub
GetProcessByName doesn't take the full path, but rather the "name" of the process. This will likely need to be GetProcessByName("SmartDefrag").
From the documentation for GetProcessByName:
The process name is a friendly name for the process, such as Outlook, that does not include the .exe extension or the path.

I don't know where to catch this error: Access to the port is denied

I'm using a serial port with a Serial Object and sometimes I get this error.
UnauthorizedAccessException: Access to the port is denied.
with a stack trace of:
at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
at System.IO.Ports.InternalResources.WinIOError()
at System.IO.Ports.SerialStream.Dispose(Boolean disposing)
at System.IO.Ports.SerialStream.Finalize()
It doesn't occur at any line of code (within my code at least) so I'm not sure how to trap it. I figure what is happening is the serial (via USB) port is being physically unplugged/disconnected for a split second and is throwing everything into whack.
I can click Continue on the error which I'm debugging and everything is fine. Communication with the serial device is flawless otherwise. But when the program is actually published, deployed and running it gives me several error messages and is all ugly for the user.
How can I trap this error/what can I do to prevent it in the first place?
Thanks
I encounter the same exception and stack trace in my WinForms application when used with a USB-to-serial converter. I can consistently recreate it by
creating an instance of SerialPort
calling SerialPort.Open,
removing the USB-to-serial converter,
closing the app (which calls SerialPort.Dispose)
My suspicion is that the exception is being thrown in SerialPort's finalizer.
Others have experienced the same symptoms - see here.
To work around I followed the recommendation of Kuno and KyferEz (from link above) to implement my own ExtSerialPort. This inherits SerialPort, overrides the Dispose method and (using reflection) disposes the SerialPort's internalSerialStream.
Imports System.IO.Ports
Public Class ExtSerialPort
Inherits SerialPort
Public Sub New()
MyBase.new()
End Sub
Public Sub New(ByVal portName As String)
MyBase.New(portName)
End Sub
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Dim mytype As Type = GetType(SerialPort)
Dim field As Reflection.FieldInfo = mytype.GetField("internalSerialStream", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)
Dim stream As Object = field.GetValue(Me)
If stream IsNot Nothing Then
Try
stream.Dispose()
Catch ex As Exception
End Try
End If
MyBase.Dispose(disposing)
End Sub
End Class

Resources