Windows Service stopped working

T

Trevor

Argh! This problem is driving me nuts! Can you help?

In November of 2003, I installed a web service on Windows Server 2003 built
in VB.NET for v1.1.4322 of the framework. It contains a timer
(System.Timers.Timer) which has an interval of 24 hours. Actually, it reads
a time like 2AM out of the config file, and calculates the time between the
start of the service to 2AM, and sets the timer. When the timer expires, it
re-reads the configuration file (in case it has changed) and re-sets the
timer (which usually ends up being 24 hours).

When the timer expires, it compares the current system time against a global
variable (Private LastExecuted As Date). LastExecuted is set as the current
time when a File Watcher (System.IO.FileSystemWatcher) is tickled. So, when
the timer expires at 2AM, it makes a database update, then checks to see
that LastExecuted is not more than an hour ago, otherwise it sends an e-mail
(the file we expected to receive today didn't arrive).

After running continuously since November 2003, the timer suddenly started
setting itself to sub-second intervals in May, 2005. When people came to
work in the morning to 5,000+ e-mail messages, I got the call. I rebooted
the service, and all was fine until Dec. 2005, when it happened again. Now,
in Feb. 2006, it has happened again, and the only way to stop the sub-second
time intervals was to reboot the whole server. Interstingly, even though
the timer expired several times per second and sending an e-mail every time,
it wasn't re-reading the configuration file (the next subroutine call after
sending the e-mails) and recognizing changes to the values therein. A week
later, though, the timer now has some unknown interval (because it's not
expiring at all, or, the elapsed logic - database update, e-mails and
configuration file read - are not happening).

This server used to be rebooted on a daily basis, but that stopped sometime
in 2004 or 2005. I don't know if that's a clue to the problem. I use the
Event Log a lot. Should I be releasing the memory reserved by the MyLog
variable? Otherwise, I have no idea what might be wrong with the code.
Please help!

In case this helps - the code which sets the interval of the timer:

Private Function ProperTimerInterval() As Double
Dim MyLog As New EventLog
MyLog.Source = "MyCompany"

Dim NextCheckTime As Date
If CInt(Time.Text.Substring(0, 2)) < CInt(Date.Now.Hour) Then
NextCheckTime = Date.Parse(Date.Now.AddDays(1).Date & " " &
Time.Text)
Else
NextCheckTime = Date.Parse(Date.Now.Date & " " & Time.Text)
End If
NextCheckTime = NextCheckTime.AddHours(1)

Dim IntervalToReturn As Double =
NextCheckTime.Subtract(Date.Now).TotalMilliseconds

If Debug.Text.ToLower = "true" Then
MyLog.WriteEntry("The daily timer is set to expire in " &
IntervalToReturn & " milliseconds, which is " & IntervalToReturn / 1000 / 60
/ 60 & " hours.", EventLogEntryType.Information)
End If

Return IntervalToReturn
End Function
 
S

Stephany Young

Did any of the responses posted in response to your original post on this
subject 5 days ago help?
 
T

Trevor

I'm sorry; the original post/responses were not showing up in Outlook
Express, and I thouught the post never went out. I have done some digging
on groups.google.com and found it all.

***I am now offering to pay someone who can fix this.***
***contact me: tsides AT intelligentsystemsconsulting SPOT com***

The file is not transferred via FTP. My mistake. I went looking for FTP
logs, and then remembered: it is simply copied from one server to another,
both of which are on the same domain. The file size is almost always <100Kb
(2,000 CSV records @ approx. 50 bytes per), so it takes less than a second
between file creation and the completion of the write. Processing the file
finishes in a matter of seconds.

The other server is an Interactive Voice Response server. Each record in
the file represents an inbound phone call that the IVR system expects. As
of 2AM, the IVR server must wait until nobody is on the phone giving it
data. At the first opportunity when nobody is on the line, it stops
answering the calls, cuts the file, sends it to me, and waits for my
outbound file in return. While most calls are less than 10 minutes long,
and calls are not likely to be received at 2AM anyway, it never takes long
for the process to kick off. So, if the file hasn't arrived within the
hour, it isn't coming.

In 2.5 years, the file has failed to arrived only once.

The time interval is always updated (AutoReset = False). This way, the
inexperienced operators can change the expected arrival time in the config
file, but they don't have to know how to reboot the service to have it take
effect. Also, the timer expires at the interval, is shut off, and then is
turned back on after the new calculation.

I'll check the file sizes. Even though the inbound file is usually ready
for processing less than a second after it is recognized by
System.IO.FileSystemWatcher, maybe the 20 second wait time is too short.
There'd be no harm in increasing that. However, I suspect the file on this
day was not unusual. Unfortunately, one of the things the process does is
delete files that are older than a month, to make sure the hard drive
doesn't fill up, so I can only back to the most recent one.

There is no "milliseconds since startup" variable that is overloading.

I like the FileSystemWatcher because it enables the service to process a
file no matter when it comes. Also, this allows the operators to drop an
"empty" file out there and get an output file. If , for example, they ever
need to reboot the IVR server and start over with a new set of records
(expected calls). Also, it mamkes the whole thing somewhat foolproof if
someone changes the daily export time from the IVR server, but forgets to
change it on my end.

I suppose I could go to a Windows Scheduler process, but I'd have to
redesign the thing; I'd have to start checking the file system for the
existence of the inbound AND outbound files, I guess. Or I could write
"LastExecuted" time to the database. I'd also have to move the
"UpdateFromConfiguration" process to the FileSystemWatcher, because ther are
other things in there that operators could change during the day, such as
the e-mail address to which errors and warnings are sent. (Regularly, not
all records in the inbound process can be loaded into the database, which is
not entirely unexepected, so they're written into an e-mail which goes out
as a warning for someone to verify.)

But I'd like to see if I can find out what's wrong with this code, first.
Again: ***I will pay someone to fix this***

More code, if it helps:


Private Sub DailyTimer_Elapsed(ByVal sender As System.Object, ByVal e As
System.Timers.ElapsedEventArgs) Handles DailyTimer.Elapsed
Dim MyLog As New EventLog
MyLog.Source = "MyCompany"

DailyTimer.Enabled = False

If Debug.Text.ToLower = "true" Then
MyLog.WriteEntry("The daily timer has expired: performing batch
functions and checking time of last execution.",
EventLogEntryType.Information)
End If

Try
'clean the fieldlink output folder (defined by
OutputFolder.Text, which is populated from the config file automatically)
PurgeDirectory(FieldLinkOutputFolder.Text,
CInt(FieldLinkOutputDaysToKeep.Text))

'clean the out folder (defined by PathOut.Text, which is
populated from the config file automatically)
PurgeDirectory(PathOut.Text, CInt(OutDaysToKeep.Text))

'clean the in folder (defined by FileSystemWatcher1.Path, which
is populated from the config file sautomatically from PathIn)
PurgeDirectory(FileSystemWatcher1.Path, CInt(InDaysToKeep.Text))
Catch ex As Exception
MyLog.WriteEntry("The following problem occured while purging
directories: " & ex.Message, EventLogEntryType.Warning)
End Try

Try
If Debug.Text.ToLower = "true" Then
MyLog.WriteEntry("Executing the SetExpectedMerchandisers
stored procedure to update the Visit table.", EventLogEntryType.Information)
End If

Dim retVal As Int32 =
VisitManager.SetExpectedMerchandisers(ConnectionString.Text, Nothing,
DateTime.Now.Date, "IVRImport")
Catch ex As Exception
MyLog.WriteEntry("The following problem occured while updating
Expected Merchandisers: " & ex.Message, EventLogEntryType.Warning)
End Try

Try
If Debug.Text.ToLower = "true" Then
MyLog.WriteEntry("Executing the
ReleaseValidNonReportedVisits stored procedure to update the Visit table.",
EventLogEntryType.Information)
End If

VisitManager.ReleaseValidNonReportedVisits(ConnectionString.Text,
"AUTO", "IVRImport")
Catch ex As Exception
MyLog.WriteEntry("The following problem occured while releasing
valid non-reported visits: " & ex.Message, EventLogEntryType.Warning)
End Try

'if the last executed date/time is not within the last 1.25 hours,
log an error and send an e-mail
If LastExecuted < Date.Now.AddHours(-1.25) Then
If Debug.Text.ToLower = "true" Then
MyLog.WriteEntry("Sending an e-mail because no Import file
was processed within the last 75 minutes.", EventLogEntryType.Information)
End If

Dim ErrorMessage = String.Format("As of {0:hh:mm} the IVR
Import/Export Launch service has still not detected a successful
Import/Export (which was expected to occur at about {1}). This may be
because the process failed (see previous Event Log entries) or because
{2}\{3} never arrived. Investigation into the problem is recommended.
Note: the IVR Import/Export will always process the expected file no matter
when it arrives.", DateTime.Now, Time.Text, FileSystemWatcher1.Path,
FileSystemWatcher1.Filter)
MyLog.WriteEntry(ErrorMessage, EventLogEntryType.Error)
If ToAddress.Text.ToLower <> "none" Then
SmtpMail.SmtpServer = "localhost"
SmtpMail.Send(FromAddress.Text, ToAddress.Text, "ERROR
NOTIFICATION: IVR Import did not occur", ErrorMessage)
End If
Else
If Debug.Text.ToLower = "true" Then
MyLog.WriteEntry("Determined that an Import file was
processed within the last 75 minutes; no e-mail was sent.",
EventLogEntryType.Information)
End If
End If

UpdateFromConfiguration()
End Sub

Private Sub UpdateFromConfiguration()
Dim MyLog As New EventLog
MyLog.Source = "MyCompany"

If Debug.Text.ToLower = "true" Then
MyLog.WriteEntry("Updating from configuration.",
EventLogEntryType.Information)
End If

CType(Me.FileSystemWatcher1,
System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.DailyTimer,
System.ComponentModel.ISupportInitialize).BeginInit()

Try
'DSR - 8/14/2003
'Use .NET AppSettingsReader instead of parsing XML
Dim AppSettings As AppSettingsReader = New AppSettingsReader

Me.FileSystemWatcher1.Filter =
CType(AppSettings.GetValue("FileNameIn", GetType(System.String)), String)
Me.FileSystemWatcher1.Path =
CType(AppSettings.GetValue("PathIn", GetType(System.String)), String)
Me.Time.Text = CType(AppSettings.GetValue("Time",
GetType(System.String)), String)
Me.PathOut.Text = CType(AppSettings.GetValue("PathOut",
GetType(System.String)), String)
Me.FileNameOut.Text = CType(AppSettings.GetValue("FileNameOut",
GetType(System.String)), String)
Me.OutDaysToKeep.Text =
CType(AppSettings.GetValue("OutDaysToKeep", GetType(System.String)), String)
Me.InDaysToKeep.Text =
CType(AppSettings.GetValue("InDaysToKeep", GetType(System.String)), String)
Me.FieldLinkOutputFolder.Text =
CType(AppSettings.GetValue("FieldLinkOutputFolder", GetType(System.String)),
String)
Me.FieldLinkOutputDaysToKeep.Text =
CType(AppSettings.GetValue("FieldLinkOutputDaysToKeep",
GetType(System.String)), String)
Me.ToAddress.Text = CType(AppSettings.GetValue("ToAddress",
GetType(System.String)), String)
Me.FromAddress.Text = CType(AppSettings.GetValue("FromAddress",
GetType(System.String)), String)
Me.DefaultExtension.Text =
CType(AppSettings.GetValue("MarketCoordinatorDefaultExtension",
GetType(System.String)), String)
Me.ConnectionString.Text =
CType(AppSettings.GetValue("ConnectionString", GetType(System.String)),
String)

Catch ex As Exception
MyLog.WriteEntry("Unable to load configuration settings: " &
ex.Message, EventLogEntryType.Warning)
End Try

CType(Me.FileSystemWatcher1,
System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.DailyTimer,
System.ComponentModel.ISupportInitialize).EndInit()

DailyTimer.Interval = ProperTimerInterval()
DailyTimer.Enabled = True
End Sub
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top