System.NullReferenceException: Object reference not set to an instance of an object when running as a Service

Locked System.NullReferenceException: Object reference not set to an instance of an object when running as a Service

  • Friday, May 04, 2012 9:56 PM
     
     

    I'm trying to run a service that calls a sub from a class (pop3.vb) but I always get system.NullReferenceException errors:

    System.NullReferenceException: Object reference not set to an instance of an object.
       at Auto_PrintEmailAttachment.POP3.POPConnect(String strServer, String strUserName, String strPassword)
       at Auto_PrintEmailAttachment.AutoPrintEmailAttachment.OnTimedEvent(Object source, ElapsedEventArgs e)

    When I'm running the same code (except the service starting part) in a windows form app, everything runs fine.

    The service sub in POP3.vb starts with: 
    Sub POPConnect(ByVal strServer As String, ByVal strUserName As String, ByVal strPassword As String)

    ...

    end sub

    The AutoPrinter.vb has the start service and timer commands. The service is started with this:

    Protected Overrides Sub OnStart(ByVal args() As String)
            'Create eventviewer entries
            If Not System.Diagnostics.EventLog.SourceExists("Test Auto Print Email Attachment Service") Then
                System.Diagnostics.EventLog.CreateEventSource("Test Auto Print Email Attachment Service",
                "Test")
            End If
            EventLog1.Source = "Test Auto Print Email Attachment Service"
            EventLog1.Log = "Test"

            NotifyIcon1.Visible = True
            NotifyIcon1.ShowBalloonTip(3000, "Test", "Test Auto Print Email Attachment Service is started", ToolTipIcon.Info)


            Try

                aTimer.Enabled = True
                EventLog1.WriteEntry("Service Started.")

            Catch ex As Exception
                EventLog1.WriteEntry(ex.ToString)
                Exit Try
            Finally
            End Try


        End Sub

    The AutoPrinter.vb has also the initialization part:

        Public Sub New()
            MyBase.New()
            InitializeComponent()

            'Create eventviewer entries
            If Not System.Diagnostics.EventLog.SourceExists("Test Auto Print Email Attachment Service") Then
                System.Diagnostics.EventLog.CreateEventSource("Test Auto Print Email Attachment Service",
                "Test")
            End If
            EventLog1.Source = "Test Auto Print Email Attachment Service"
            EventLog1.Log = "Test"

            Try
                aTimer = New System.Timers.Timer(10000)
                AddHandler aTimer.Elapsed, AddressOf OnTimedEvent
                aTimer.Interval = My.Settings.checkinterval_milliseconds

                'System.Configuration.ConfigurationManager.AppSettings("checkinterval_milliseconds")

                'CREATE WORKING DIRECTORY
                If Directory.Exists((Environ("HOMEPATH") & "\Documents\") & "TestEmailAutoPrintAttachment") = False Then
                    Directory.CreateDirectory((Environ("HOMEPATH") & "\Documents\") & "TestEmailAutoPrintAttachment")
                End If

                'CREATE WORKING SUBDIRECTORY (PRINTED FILES)
                If Directory.Exists((Environ("HOMEPATH") & "\Documents\") & "TestEmailAutoPrintAttachment\SentToPrinter") = False Then
                    Directory.CreateDirectory((Environ("HOMEPATH") & "\Documents\") & "TestEmailAutoPrintAttachment\SentToPrinter")
                End If

            Catch ex As Exception
                EventLog1.WriteEntry(ex.ToString)
                Exit Try
            Finally
            End Try
        End Sub

    also in AutoPrinter.vb, there's the OnTimedEvent sub that's called

    Private Sub OnTimedEvent(source As Object, e As ElapsedEventArgs)

            EventLog1.WriteEntry("Timed events initiated.")

            Try


                'variable declaration
                Dim strServer, strUsername, strPassword, strFrom, strSubject, strToo, strBody, strMailContent As String
                Dim popConn As Auto_PrintEmailAttachment.POP3
                Dim mailMess As Auto_PrintEmailAttachment.EmailMessage
                Dim intMessCnt, i As Integer



                'set the variables to the input boxes
                strServer = My.Settings.pop3server.ToString()
                'System.Configuration.ConfigurationManager.AppSettings("pop3server")

                strUsername = My.Settings.mailboxusername.ToString()
                'System.Configuration.ConfigurationManager.AppSettings("mailboxusername")

                strPassword = My.Settings.mailboxpassword.ToString()
                'System.Configuration.ConfigurationManager.AppSettings("mailboxpassword")

                'make sure some detials have been filled in
                If strServer = "" Then
                    EventLog1.WriteEntry("No Mail server specified!")
                    Exit Sub
                End If
                If IsNothing(strServer) = True Then
                    EventLog1.WriteEntry("Mailserver is NULL!")
                End If

                If strUsername = "" Then
                    EventLog1.WriteEntry("No Username specified!")
                    Exit Sub
                End If
                If IsNothing(strUsername) = True Then
                    EventLog1.WriteEntry("Username is NULL!")
                End If

                If strPassword = "" Then
                    EventLog1.WriteEntry("No Password Specified!")
                    Exit Sub
                End If
                If IsNothing(strPassword) = True Then
                    EventLog1.WriteEntry("Password is NULL!")
                End If


                'create the objects
                popConn = New Auto_PrintEmailAttachment.POP3
                mailMess = New Auto_PrintEmailAttachment.EmailMessage

                'if we have got to this point, try and connect to the server
                popConn.POPConnect(strServer, strUsername, strPassword)

                'now we have a connection, see if there are any mails on the server
                intMessCnt = popConn.GetMailStat()

                'now, see if we have returned any messages
                If intMessCnt > 0 Then



                    'if we returned some messages, loop through each one and get the details
                    For i = 1 To intMessCnt


                        'load the entire content of the mail into a string
                        strMailContent = popConn.GetMailMessage(i)

                        'call the functions to get the various parts out of the email 
                        strFrom = mailMess.ParseEmail(strMailContent, "From:")
                        strSubject = mailMess.ParseEmail(strMailContent, "Subject:")
                        strToo = mailMess.ParseEmail(strMailContent, "To:")

                        'My.Computer.FileSystem.WriteAllText("C:\Temp\emails\strSubject.txt", strSubject & vbNewLine & strFrom, False)

                        If Not strSubject.IndexOf(My.Settings.subjectstringtosearch.ToString) = -1 Then
                            strBody = mailMess.ParseBody()

                            ' 
                            'My.Computer.FileSystem.WriteAllText("C:\Temp\emails\messages.txt", strBody, False)

                        End If

                    Next i
                End If

                'Quit the connection to the server
                popConn.CloseConn()

            Catch ex As Exception
                EventLog1.WriteEntry(ex.ToString)

                Exit Try
            Finally
            End Try

        End Sub


    End Class

    It does work when i run the code via a windows form, so I must be doing something wrong with the starting and stopping?

    Thanks,
    Davy

All Replies

  • Saturday, May 05, 2012 1:56 AM
     
     
    my guess is that EventLog1 is null in OnTimedEvent. Try reinitializing it if it doesn't already exist. I suspect that the onstart/onstop may affect a different instance of the class. just a hunch, but worth a quick try.
    • Edited by Endotherm Saturday, May 05, 2012 1:57 AM
    •  
  • Saturday, May 05, 2012 7:35 AM
     
     

    Hi,

    The ontimedevent sets the "timed event started" eventlog entry.

    How can I check if the onstart/onstop affects a different instance of the class?

    the only reference to the class file (that i can see(newbie dev)) is via Dim popConn As Auto_PrintEmailAttachment.POP3

    Thanks,

    D

  • Saturday, May 05, 2012 12:07 PM
     
     Proposed

    Hi,

    I found something (not yet the total solution yet I think :))

    I tried to add eventlogPOP3.WriteEntry("test") in the POP3 class, but that resulted in the same error.

    When I commented the evenlog init lines, then the error was gone. Somehow services run more "protected" on the OS than regular windows forms apps I think.

    'Class to connect to the passed mail server on port 110
        Sub POPConnect(ByVal strServer As String, ByVal strUserName As String, ByVal strPassword As String)
            'If Not System.Diagnostics.EventLog.SourceExists("Inscope Auto Print Email Attachment Service") Then
            '    System.Diagnostics.EventLog.CreateEventSource("Inscope Auto Print Email Attachment Service",
            '    "Inscope")
            'End If
            'eventlogPOP3.Source = "Inscope Auto Print Email Attachment Service"
            'eventlogPOP3.Log = "Inscope"

    Regards,

    Davy

  • Saturday, May 05, 2012 6:50 PM
     
      Has Code

    I'm not seeing a place in your code where you instantiate the EventLog1 object. I was thinking somthing like this. Create a method to return eventlog1, which will always ensure that it is instantiated and initialized. then replace your instances of eventlog1 with GetEventLog().

    Services do run differantly than windows apps, but you can configure what user the service runs under in services.msc after its been installed, or via your ServiceProcessInstaller.Account property.

    'this must be run as admin under UAC, or within a service. otherwise it will throw a security exception
    public Function GetEventLog() as Diagnostics.EventLog
    	if isnothing(EventLog1) then
    		If Not System.Diagnostics.EventLog.SourceExists("Test Auto Print Email Attachment Service") Then
    			System.Diagnostics.EventLog.CreateEventSource("Test Auto Print Email Attachment Service", "Test")
    		End If
    		EventLog1 = new EventLog("Test", ".", "Test Auto Print Email Attachment Service")
    	end if
    	return EventLog1
    End Function
    
    Private Sub OnTimedEvent(source As Object, e As ElapsedEventArgs)
            GetEventLog().WriteEntry("Timed events initiated.")
            Try
                ....
    
                'make sure some detials have been filled in
                If strServer = "" Then
                    GetEventLog().WriteEntry("No Mail server specified!")
                    Exit Sub
                End If
                If IsNothing(strServer) = True Then
                    GetEventLog().WriteEntry("Mailserver is NULL!")
                End If
    
    	    ....
    End Sub




  • Monday, May 07, 2012 6:47 PM
     
     

    Hi,

    The event log entries are working when they are in the main service.vb

    'Create eventviewer entries
            If Not System.Diagnostics.EventLog.SourceExists("Test Auto Print Email Attachment Service") Then
                System.Diagnostics.EventLog.CreateEventSource("Test Auto Print Email Attachment Service",
                "Test")
            End If
            EventLog1.Source = "Test Auto Print Email Attachment Service"
            EventLog1.Log = "Test"

    and all below entries in that same services.vb also result in an eventvwr entry being added:

    EventLog1.WriteEntry("Service Started.")

    However, I would like to add events as well from the POP3.vb class. But there it doesn't seem to work.

    I can't drag the eventvwr element from the tools into that vb. What is the other way? Do I have to put the eventvwr function in a different class and refer that?

    Thanks,

    Davy

  • Monday, May 07, 2012 7:25 PM
     
     Answered

    if pop3 is being called by teh service.vb file, its rights should be the same as those that service.vb had, so thats weird. it is being invoked by the service, correct? what user account is your service running under?

    I would never bother dragging an evntlog object onto the form, since asside from declaring the variable 'private EventLog1 as EventLog', you have already done all the work in code anyway.

    have you tried passing a live eventlog isntance into pop3, instead of instantiating it there?

  • Wednesday, May 16, 2012 12:53 PM
    Moderator
     
     

    Hi Davy,

    Do you have any updates?

    Best regards,


    Mike Feng
    MSDN Community Support | Feedback to us
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

  • Thursday, May 17, 2012 9:11 PM
     
     

    Hi,

    If I put the below code in:

    Dim Eventlog1 As New EventLog
            Eventlog1.Source = "Tes Auto Print Email Attachment Service"
            Eventlog1.Log = "Test"
            Eventlog1.WriteEntry((Environ("HOMEPATH") & "\Documents\") & "TestEmailAutoPrintAttachment\SentToPrinter\" & pdfdocumentname.ToString, EventLogEntryType.Information)

    Then I have eventlog entries originating from the POP3.vb

    So it works, Thanks !!!! :)