|
-
May 27th, 2017, 01:35 PM
#1
Thread Starter
New Member
Windows Service, Using timer, VB.net
Hi everyone. I am kind of newbie when it comes to writing windows services but I'm pretty sure the problem I'm experiencing is not just a mistake in understanding.
I had set up a windows service and had it working, firing off a timer every 60 seconds and writing an entry into my EventLog. It appears as if the minute I place any other code into it and I mean any other code, the timer stops working and won't even write the log entry.
I would think if it were a problem with some piece of the code following it; that it would at least write that line and then error.
Anyway Here is what I'm doing. I'm hoping maybe someone who has gone through this could give me a little direction to kick start the issue. Thanks in advance.
Code:
Imports System.Runtime.InteropServices
Imports WinSCP
Imports System.Threading
Public Class MyNewService
Public eventID As Integer
Declare Auto Function SetServiceStatus Lib "advapi32.dll" (ByVal handle As IntPtr, ByRef serviceStatus As ServiceStatus) As Boolean
Public Sub New()
MyBase.New()
' This call is required by the designer.
InitializeComponent()
Try
' Add any initialization after the InitializeComponent() call.
Me.EventLog1 = New System.Diagnostics.EventLog
If Not System.Diagnostics.EventLog.SourceExists("MyNewService") Then
System.Diagnostics.EventLog.CreateEventSource("MyNewService", "MyNewLog")
End If
EventLog1.Source = "MyNewService"
EventLog1.Log = "MyNewLog"
Catch err As System.Diagnostics.Eventing.Reader.EventLogException
MsgBox(err.InnerException)
End Try
End Sub
Protected Overrides Sub OnStart(ByVal args() As String)
Dim serviceStatus As ServiceStatus = New ServiceStatus()
serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING
serviceStatus.dwWaitHint = 100000
SetServiceStatus(Me.ServiceHandle, serviceStatus)
serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING
SetServiceStatus(Me.ServiceHandle, serviceStatus)
' Add code here to start your service. This method should set things
' in motion so your service can do its work.
EventLog1.WriteEntry("Service Started")
Dim timer As System.Timers.Timer = New System.Timers.Timer()
timer.Enabled = True
timer.Interval = 60000
AddHandler timer.Elapsed, AddressOf Me.OnTimer
timer.Start()
End Sub
Private Sub OnTimer(sender As Object, e As Timers.ElapsedEventArgs)
' TODO: Insert Monitoring Activies Here.
Try
EventLog1.WriteEntry("Checking For New Files", EventLogEntryType.Information, eventID)
' Setup session options
Dim sessionOptions As New SessionOptions
EventLog1.WriteEntry("SessionOptions", EventLogEntryType.Information, eventID)
With sessionOptions
.Protocol = Protocol.Sftp
.HostName = "XXXXXXXXXXX"
.UserName = "XXXXXXXXXXX"
.Password = "XXXXXXXXXXX"
.SshHostKeyFingerprint = "XXXXXXXXXXXXXXXX"
End With
Using session As New Session
' Connect
session.Open(sessionOptions)
EventLog1.WriteEntry("Session To Cheyney FTP Open")
' Download files
Dim transferOptions As New TransferOptions
transferOptions.TransferMode = TransferMode.Binary
Dim transferResult As TransferOperationResult
transferResult = session.GetFiles("/Inbox1/*", "C:\Localfolder\", False, transferOptions)
' Throw on any error
transferResult.Check()
' Print results
For Each transfer In transferResult.Transfers
EventLog1.WriteEntry(".....Transferring File:" & transfer.filename)
Next
End Using
Catch err As Exception
EventLog1.WriteEntry("Service Exception: " & err.InnerException.ToString)
End Try
eventID = eventID + 1
End Sub
Protected Overrides Sub OnStop()
Dim serviceStatus As ServiceStatus = New ServiceStatus()
serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED
SetServiceStatus(Me.ServiceHandle, serviceStatus)
' Add code here to perform any tear-down necessary to stop your service.
EventLog1.WriteEntry("Service Stopped")
End Sub
Public Enum ServiceState
SERVICE_STOPPED = 1
SERVICE_START_PENDING = 2
SERVICE_STOP_PENDING = 3
SERVICE_RUNNING = 4
SERVICE_CONTINUE_PENDING = 5
SERVICE_PAUSE_PENDING = 6
SERVICE_PAUSED = 7
End Enum
<StructLayout(LayoutKind.Sequential)>
Public Structure ServiceStatus
Public dwServiceType As Long
Public dwCurrentState As ServiceState
Public dwControlsAccepted As Long
Public dwWin32ExitCode As Long
Public dwServiceSpecificExitCode As Long
Public dwCheckPoint As Long
Public dwWaitHint As Long
End Structure
End Class
Last edited by Shaggy Hiker; May 28th, 2017 at 10:45 AM.
Reason: Added CODE tags.
-
May 28th, 2017, 04:53 AM
#2
Re: Windows Service, Using timer, VB.net
For future reference, please us appropriate formatting tags when posting code snippets.
vb.net Code:
Imports System.Runtime.InteropServices Imports WinSCP Imports System.Threading Public Class MyNewService Public eventID As Integer Declare Auto Function SetServiceStatus Lib "advapi32.dll" (ByVal handle As IntPtr, ByRef serviceStatus As ServiceStatus) As Boolean Public Sub New() MyBase.New() ' This call is required by the designer. InitializeComponent() Try ' Add any initialization after the InitializeComponent() call. Me.EventLog1 = New System.Diagnostics.EventLog If Not System.Diagnostics.EventLog.SourceExists("MyNewService") Then System.Diagnostics.EventLog.CreateEventSource("MyNewService", "MyNewLog") End If EventLog1.Source = "MyNewService" EventLog1.Log = "MyNewLog" Catch err As System.Diagnostics.Eventing.Reader.EventLogException MsgBox(err.InnerException) End Try End Sub Protected Overrides Sub OnStart(ByVal args() As String) Dim serviceStatus As ServiceStatus = New ServiceStatus() serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING serviceStatus.dwWaitHint = 100000 SetServiceStatus(Me.ServiceHandle, serviceStatus) serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING SetServiceStatus(Me.ServiceHandle, serviceStatus) ' Add code here to start your service. This method should set things ' in motion so your service can do its work. EventLog1.WriteEntry("Service Started") Dim timer As System.Timers.Timer = New System.Timers.Timer() timer.Enabled = True timer.Interval = 60000 AddHandler timer.Elapsed, AddressOf Me.OnTimer timer.Start() End Sub Private Sub OnTimer(sender As Object, e As Timers.ElapsedEventArgs) ' TODO: Insert Monitoring Activies Here. Try EventLog1.WriteEntry("Checking For New Files", EventLogEntryType.Information, eventID) ' Setup session options Dim sessionOptions As New SessionOptions EventLog1.WriteEntry("SessionOptions", EventLogEntryType.Information, eventID) With sessionOptions .Protocol = Protocol.Sftp .HostName = "XXXXXXXXXXX" .UserName = "XXXXXXXXXXX" .Password = "XXXXXXXXXXX" .SshHostKeyFingerprint = "XXXXXXXXXXXXXXXX" End With Using session As New Session ' Connect session.Open(sessionOptions) EventLog1.WriteEntry("Session To Cheyney FTP Open") ' Download files Dim transferOptions As New TransferOptions transferOptions.TransferMode = TransferMode.Binary Dim transferResult As TransferOperationResult transferResult = session.GetFiles("/Inbox1/*", "C:\Localfolder\", False, transferOptions) ' Throw on any error transferResult.Check() ' Print results For Each transfer In transferResult.Transfers EventLog1.WriteEntry(".....Transferring File:" & transfer.filename) Next End Using Catch err As Exception EventLog1.WriteEntry("Service Exception: " & err.InnerException.ToString) End Try eventID = eventID + 1 End Sub Protected Overrides Sub OnStop() Dim serviceStatus As ServiceStatus = New ServiceStatus() serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED SetServiceStatus(Me.ServiceHandle, serviceStatus) ' Add code here to perform any tear-down necessary to stop your service. EventLog1.WriteEntry("Service Stopped") End Sub Public Enum ServiceState SERVICE_STOPPED = 1 SERVICE_START_PENDING = 2 SERVICE_STOP_PENDING = 3 SERVICE_RUNNING = 4 SERVICE_CONTINUE_PENDING = 5 SERVICE_PAUSE_PENDING = 6 SERVICE_PAUSED = 7 End Enum <StructLayout(LayoutKind.Sequential)> Public Structure ServiceStatus Public dwServiceType As Long Public dwCurrentState As ServiceState Public dwControlsAccepted As Long Public dwWin32ExitCode As Long Public dwServiceSpecificExitCode As Long Public dwCheckPoint As Long Public dwWaitHint As Long End Structure End Class
-
May 28th, 2017, 10:49 AM
#3
Re: Windows Service, Using timer, VB.net
I edited the post to add [CODE][/CODE] tags, which you can do by pressing the # button and pasting the code between the resulting tags. The other type of formatting, which JMC showed, results from the VB button (which looks like VE on most browsers). I find the CODE tags a bit easier, and that code copies and pastes a bit more easily, but doesn't look as nice in the post.
As to the question: Where do you add this code that causes the problem? I suppose I'd also ask what that code would be, but from the way you asked the question, I assume it could be a wide variety of anything. Perhaps an example may be useful, but I think the location might be the most important part.
My usual boring signature: Nothing
 
-
May 28th, 2017, 03:23 PM
#4
Re: Windows Service, Using timer, VB.net
Here's a guess, this is a bit subtle.
When you create the timer, you store it in a variable that is local to OnStart(). When OnStart() ends, that variable doesn't exist anymore, so nothing references the Timer. That means the next time the Garbage Collector runs, it can decide to destroy the Timer.
If you want something to live as long as your Service, it should be a field of a class that stays in memory. There's a few ways to go about it, the easiest would be to make the Timer a Shared field of your MyNewService class.
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
-
May 30th, 2017, 09:16 AM
#5
Thread Starter
New Member
Re: Windows Service, Using timer, VB.net
Still doesn't work. IF there is an exception occurring when the first object is defined WHY doesn't the try..catch... grab an error. Since it doesn't I can only assume there wasn't one!
-
May 30th, 2017, 11:03 AM
#6
Re: Windows Service, Using timer, VB.net
There's a couple of reasons an exception could be being thrown but not displayed to you.
First, you're only catching one kind of exception. If any other kind of exception is being thrown, you don't handle that one.
Second, services can't display UI by default, so even if it's the exception you expect the MsgBox() call might be ignored.
Replace it with something that catches any exception andwrites the exception to a file, generally you can do that without issue. Something like:
Code:
Catch ex As Exception
Dim desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
Dim filePath = Path.Combine(desktopPath, "serviceLog.txt")
File.WriteAllText(filePath, ex.ToString())
End Try
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|