S22.IMAP causing exceptions while "idling" - vb.net

I am trying to use the S22.Imap library (https://github.com/smiley22/S22.Imap) to listen for new messages.
I have followed the examples provided, but am in need of help...
According to what I have read, the ImapClient object should sit in the background and listen for new messages (using the IDLE feature) and raise an event when a new message is received.
And it seems to work... for a while!
I am using Visual Studio 2010 on Windows 7 Ultimate 64-bit.
I have a simple VB.NET Windows Forms project - here is the code:
Imports S22.Imap
Public Class Form1
Private Shared Sub UnhExceptionHandler(sender As Object, e As System.UnhandledExceptionEventArgs)
Console.WriteLine("Unhandled UI Exception: {0}", DirectCast(e.ExceptionObject, Exception).Message)
End Sub
Private Shared Sub ThrExceptionHandler(sender As Object, e As System.Threading.ThreadExceptionEventArgs)
Console.WriteLine("Unhandled Thread Exception: {0}", e.Exception.Message)
End Sub
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf UnhExceptionHandler
AddHandler System.Windows.Forms.Application.ThreadException, AddressOf ThrExceptionHandler
Try
Dim c As ImapClient = New ImapClient("imap.gmail.com", 993, "john#john-online.co.uk", "XXXXXXXXXXXXXXXX", AuthMethod.Login, True)
' Should ensure IDLE is actually supported by the server
If c.Supports("IDLE") = False Then
Console.WriteLine("Server does not support IMAP IDLE")
Else
' We want to be informed when new messages arrive
AddHandler c.NewMessage, New EventHandler(Of IdleMessageEventArgs)(AddressOf OnNewMessage)
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Private Shared Sub OnNewMessage(sender As Object, e As IdleMessageEventArgs)
Console.WriteLine("A new message arrived. Message has UID: " & Convert.ToString(e.MessageUID))
End Sub
End Class
When I run this, all goes well for a while - I receive new message notifications OK, but after a while, if I disconnect and reconnect my network connection, I get the following message in 'UnhExceptionHandler()':
Unable to read data from the transport connection: An established connection was aborted by the software in your host machine.
In this code example, I could simply trap the error and restart the ImapCLient connection. But this is just to test the S22.Imap library - I want to use it in an application where many accounts are checked simultaneously, so need I need to be able to trap the error and determine which individual ImapClient object raised it?
Can anyone suggest any possible resolutions?

Related

vb.net Desktop Application not running on a client machine after installation

I have created an application in vb.net using sql server database and crystal reports, I then created the setup file using visual studio 2015 installer extension and installed the project on my Computer from which the application was developed and it is working fine. The issue starts when I install in the client computer, the application does not even start in the client machine, I have installed the .netFramework required and crystal reports run time engine in the client machine but still the app is not starting.
I have a background worker on my startup form and the connection is tested on form load. If the connection is successful the applications the creates a crystal report from a table in the database and if connection is not successful, the application loads the configuration form to manually configure the connection string and a message box will show the exception occurred.
Below is the code
Imports System.ComponentModel
Imports System.Data.SqlClient
Public Class loader
Dim connection As SqlConnection
Private Sub loader_Load(sender As Object, e As EventArgs) Handles MyBase.Load
BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
If BackgroundWorker1.CancellationPending Then
e.Cancel = True
Else
ShowPanel([Panel2])
LoaderReportLoading([CrystalReportViewer1])
End If
End Sub
Delegate Sub LoadRpt(ByVal [crv] As Object)
Delegate Sub SetPanelVisible(ByVal [panel] As Panel)
Private Sub LoaderReportLoading(ByVal [crv] As Object) 'use the same delegate LoadRpt
Try
If My.Settings.connection = "" Then
server_configuration.ShowDialog()
Else
connection = New SqlConnection(My.Settings.connection)
connection.Open()
Dim CoTable As New DataTable
Using command As New SqlCommand("SELECT * FROM COMPANY", connection)
Dim adapter As New SqlDataAdapter(command)
adapter.Fill(CoTable)
End Using
Dim rep As New loaderReport
rep.Database.Tables("COMPANY").SetDataSource(CoTable)
If [crv].InvokeRequired Then
Dim myDelegate As New LoadRpt(AddressOf LoaderReportLoading)
Me.Invoke(myDelegate, New Object() {crv})
Else
[crv].ReportSource = rep
End If
connection.Close()
End If
Catch ex As Exception
MessageBox.Show(ex.Message, "The following Error Occured While Connecting to the database")
server_configuration.ShowDialog()
End Try
End Sub
Private Sub ShowPanel(ByVal [panel] As Panel)
If [panel].InvokeRequired Then
Dim myDelegate As New SetPanelVisible(AddressOf ShowPanel)
Me.Invoke(myDelegate, New Object() {panel})
Else
[panel].Visible = True
End If
End Sub
End Class
I don't have any idea of using windows event logs, this is my first desktop application to be deployed.
Finally got the error after implementing logging on my system. The error was with the runtime engine for crystal reports. I changed a version of the crystal reports from SP30 to SP26 and all is working fine now.

Application taking a while to listen for incoming connections

I have an application which uses the hosts file to block certain websites. The websites can't connect because of the hosts file, so that works great, however, my program is supposed to raise an event when a website is blocked.
I'm using this code:
Private Sub Main_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim blocker As BlockListener
Dim thread As Thread
blocker = New BlockListener
thread = New Thread(New ThreadStart(AddressOf blocker.listen))
thread.Start()
AddHandler blocker.Blocked, AddressOf User_Blocked
End Sub
Private Sub User_Blocked()
My.Computer.Audio.Play("Sounds\Website-Blocked.wav")
WebsiteDetected.ShowDialog()
SetForegroundWindow(WebsiteDetected.Handle)
End Sub
Public Class BlockListener
Private port As Integer = 80
Private listener As TcpListener
Private BlockUsers As Boolean = True
Public Event Blocked As EventHandler
Public Sub listen()
listener = New TcpListener(IPAddress.Parse("127.0.0.1"), port)
listener.Start()
While (BlockUsers)
Dim clientConnection As TcpClient = listener.AcceptTcpClient
clientConnection.Close()
BlockUsers = False
RaiseEvent Blocked(Me, EventArgs.Empty)
End While
listener.Stop()
End Sub
After I wait for a while (say for about two minutes) then the program can detect bad websites that are visited, however, I don't really want to wait, as I think it's a lot more practical if you just run the program, and done, you won't have to wait for the program to start listening for incoming connections.
Is there anyway I can listen on the server quicker?
Also, could it be because I have lots of websites on my hosts file? I've got a total of 80, 000 infected websites, and since Visual Basic is a lot slower than some certain languages, could that be the reason why?
I don't know why the TcpListener takes such a long time to detect the connection, but I can confirm that it does.
What seems to solve the problem is to switch to a HttpListener instead, which can be used to host an actual HTTP server.
Finally, you need to marshal the call from User_Blocked to the UI thread before you can start opening forms and accessing UI elements. This is because your Blocked event is run in the background thread, and all UI-related code must run on the UI thread only.
Private port As Integer = 80
Private listener As New HttpListener
Private BlockUsers As Boolean = True
Public Event Blocked As EventHandler
Public Sub listen()
listener.Start()
listener.Prefixes.Add("http://*:80/")
While (BlockUsers)
Dim context As HttpListenerContext = Listener.GetContext()
context.Response.Close()
BlockUsers = False
RaiseEvent Blocked(Me, EventArgs.Empty)
End While
listener.Close()
End Sub
In your form:
Private Sub User_Blocked()
If Me.InvokeRequired Then 'Do we need to invoke or are we already on the UI thread?
Me.Invoke(New MethodInvoker(AddressOf User_Blocked))
Else 'We are on the UI thread.
My.Computer.Audio.Play("Sounds\Website-Blocked.wav")
WebsiteDetected.Show() 'Note that if you use ShowDialog(), the next line won't execute until the form has been closed.
SetForegroundWindow(WebsiteDetected.Handle)
End If
End Sub
NOTE: Your application must run with administrative privileges for the HttpListener to work.

System.ObjectDisposedException in Multithreaded Application

I am writing a simple program to test out various functions of VB.NET, I will later use this in a much more complex program. The idea is to send a message via the serial port com5. The message will be taken from what is entered in the application's textbox. A background worker (activated when a button labeled "send" is pressed) continuously transmits the message. There is also a label, which does nothing.
Imports System.ComponentModel
Public Class Form1
Dim message
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
message = TextBox1.Text
If BackgroundWorker1.IsBusy = False Then
BackgroundWorker1.RunWorkerAsync()
End If
End Sub
Sub SendSerialData(ByVal data As String)
' Send strings to a serial port.
Try
Using com5 As IO.Ports.SerialPort =
My.Computer.Ports.OpenSerialPort("COM5")
com5.WriteLine(data)
End Using
Catch ioex As System.IO.IOException
TextBox1.Text = ("COM5 Not Found!")
End Try
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
While (True)
SendSerialData(message)
End While
End Sub
End Class
Originally, I used Application.DoEvents(), but it was slow and I heard it was a bad programming practice. (This, however, had no errors.) So I rewrote the program using a background worker. Now, the program runs fine while running, but when closed, this pops up:
System.ObjectDisposedException was unhandled Message: An unhandled exception of type 'System.ObjectDisposedException' occurred in
mscorlib.dll Additional information: Safe handle has been closed
I believe this has something to do with the background worker, because if the program is closed and I have not ran the background worker, the error does not appear. I have tried placing a try-catch inside every sub in the program (including changing the exception type for the catch in SendSerialData to be any exception), to no avail. This is my first post in case of issues feel free to comment.
What you need to do is signal to the BackgroundWorker1_DoWork thread that the program is closing so that it can tidy up properly. This is something that the BackgroundWorker class in the .NET framework already knows how to do.
You need to do the following:
Use a BackgroundWorker to run the task
Configure the BackgroundWorker to accept a cancellation request
Change the While loop in the background task to check for cancellation
On exiting the program request cancellation of the background task and then wait for the thread to complete.
NB: The MSDN page on BackgroundWorker has an example that does almost exactly what you want.

axacropdflib - set source from worker thread

I have a vb.net project which has a treeview of pdf's on the left and the acrobat AxAcroPDF viewer control on the right. Click a item in the treeview, I get the fileinfo.fullname value and pass that over to the AxAcroPDF src property.
While testing I noticed that pdf's were slow to load and would block my ui thread so I decided that a workerthread would be a good helper to lazy load these pdf's in the background.
When I run my code with the worker thread's DoWork method and it tries to update my pdfviewer object I get an invalid cast exception.
System.InvalidCastException was caught HResult=-2147467262
Message=Unable to cast COM object of type 'System.__ComObject' to
interface type 'AcroPDFLib.IAcroAXDocShim'. This operation failed
because the QueryInterface call on the COM component for the interface
with IID '{3B813CE7-7C10-4F84-AD06-9DF76D97A9AA}' failed due to the
following error: No such interface supported (Exception from HRESULT:
0x80004002 (E_NOINTERFACE)). Source=mscorlib StackTrace:
at System.StubHelpers.StubHelpers.GetCOMIPFromRCW(Object objSrc, IntPtr pCPCMD, IntPtr& ppTarget, Boolean& pfNeedsRelease)
at AcroPDFLib.IAcroAXDocShim.set_src(String pVal)
at AxAcroPDFLib.AxAcroPDF.set_src(String value)
at myapp.fill_treeview_with_filesfolders_docked_andthreads.LoadPDFInBackground(String
selectedfile) in
C:\Users\me\Desktop.....\fill_treeview_with_filesfolders_docked_andthreads.vb:line
84 InnerException:
I can't find any other threads online with this exception detail so I am not sure what the issue is here. I thought my problem had to do with a cross thread access violation but even if I set Control.Checkforillegalcrossthreadcalls to false I get the same exception. It didn't make sense to me that I would check for invokerequired from the DoWork routine anyways because the point of my worker thread is to handle the load for me, not shove it back into the UI thread.
Can anyone recommend a workaround that I can try to achieve what I am after here?
my Code:
The treeview afterselect is wired to displayfile
AddHandler TreeView.AfterSelect, AddressOf displayfile
Private Sub displayfile(sender As Object, e As TreeViewEventArgs)
Try
Dim selectedfile As FileInfo = New FileInfo(e.Node.Tag) 'tag has our full path embedded.
'todo: Future - consider type of the file and load a pre-made panel with appropriate host object
If selectedfile.Extension.ToLower.Equals(".pdf") Then
'show "loading...."
LoadingPanel.BringToFront()
backgroundworker.RunWorkerAsync(selectedfile.FullName)
End If
Catch ex As Exception
End Try
End Sub
Background Worker Stuff:
#Region "Background Worker Events"
' This event handler is where the time-consuming work is done.
Private Sub backgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As DoWorkEventArgs) Handles backgroundworker.DoWork
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
e.Result = LoadPDFInBackground(e.Argument)
End Sub
' This event handler updates the progress.
Private Sub backgroundWorker_ProgressChanged(ByVal sender As System.Object, ByVal e As ProgressChangedEventArgs) Handles backgroundworker.ProgressChanged
ProgressBar.Value = e.ProgressPercentage
End Sub
' This event handler deals with the results of the background operation.
Private Sub backgroundWorker_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As RunWorkerCompletedEventArgs) Handles backgroundworker.RunWorkerCompleted
If e.Result Then
'hide loading panel and show pdf panel
pdfviewer.BringToFront()
Else
'what to do if failed to load???
End If
End Sub
#End Region
Private Function LoadPDFInBackground(ByVal selectedfile As String) As Boolean
Try
pdfviewer.src = selectedfile
Return True
Catch ex As Exception
Return False
End Try
End Function
Just a thought, but try changing this line:
pdfviewer.src = selectedfile
to the following:
If pdfviewer.InvokeRequired Then
pdfviewer.Invoke(Sub() pdfviewer.src = selectedfile)
It might work around the error. Interesting to see if it does.

VB.Net Sending errors through mail when error is detected

I'm developing an application with an error log when something goes bad. It must send an e-mail with the error details so I can remotely fix and upload a new update with the fix.
I'm using Try Catch Exception but I have a lot of methods to include this option in.
Is there another way to do it without doing so much code?
Since exceptions bubble up to the application instance try using the Application.SetUnhandledExceptionMode Method.
From above MSDN Link:
It is often not feasible to catch all of the exceptions thrown by
Windows Forms. Using this method, you can instruct your application
whether it should catch all unhandled exceptions thrown by Windows
Forms components and continue operating, or whether it should expose
them to the user and halt execution.
Public Shared Sub Main()
' Add the event handler for handling UI thread exceptions to the event.
AddHandler Application.ThreadException, AddressOf Form1_UIThreadException
' Set the unhandled exception mode to force all Windows Forms errors to go through
' our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException)
' Add the event handler for handling non-UI thread exceptions to the event.
AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf CurrentDomain_UnhandledException
' Runs the application.
Application.Run(New Form1()) '' This is your applications Main Form
End Sub
Private Shared Sub Form1_UIThreadException(ByVal sender As Object, ByVal t As ThreadExceptionEventArgs)
'Put Error Handling Code here see the MSDN article for an example implementation
End Sub
Private Shared Sub CurrentDomain_UnhandledException(ByVal sender As Object, _
ByVal e As UnhandledExceptionEventArgs)
''Put Error Handling Code here see the MSDN article for an example implementation
End Sub
Sorry, misunderstood your question. Try putting your logic in a method and just try to call that method in every try catch statement you have.
Example:
Public Shared Sub Method1()
Try
'Method logic here
Catch ex As Exception
EmailError(ex)
End Try
End Sub
Public Shared Sub EmailError(ex As Exception)
'your remote error email logic here
End Sub