Check On External Process

A

ags5406

I've a Windows Service that keeps a particular executable running. If
the executable fails for whatever reason, the Service restarts it.
Right now I'm using a loop to check if the process is running. I
started with an infinite loop that ate up all of my resources, but
then added a 2 second pause after every check, which seems to have
mostly eliminated the problem of my resources being used up.

However, I'm wondering if there is a better way? Does the service
still "waste" resources while waiting for that two seconds? Is there
some kind of "process ended" event that can trigger the code to
restart the process? Following is pretty much my entire code for the
service. Pretty basic.

Imports System.Threading

Public Class fxpsMain

Friend oStartThread As Thread
Friend oStopThread As Thread

Protected Overrides Sub OnStart(ByVal args() As String)
Dim oRun As ServerTask
oRun = New ServerTask
oStartThread = New Thread(New ThreadStart(AddressOf
oRun.ContinuousRun))
oStartThread.Start()
End Sub

Protected Overrides Sub OnStop()
oStartThread.Abort()

Dim oRun As ServerTask
oRun = New ServerTask
oStopThread = New Thread(New ThreadStart(AddressOf oRun.Kill))
oStopThread.Start()
End Sub

End Class

Public Class ServerTask

Public Sub Launch()

Dim bServerRunning As Boolean = False
Dim procA As Process
Dim processList() As Process
processList = Process.GetProcesses

For Each procA In processList
If procA.ProcessName.ToUpper = "PROCESSNAME" Then
bServerRunning = True
End If
Next

If Not bServerRunning Then
Dim oProc As New Process
oProc.StartInfo.FileName = "c:\somedir\processname.exe"
oProc.StartInfo.UseShellExecute = True
oProc.Start()
End If

End Sub

Public Sub ContinuousRun()

LaunchAgain:
Launch()
'pause for 2 seconds before checking again to conserve
resources
System.Threading.Thread.Sleep(2000)
GoTo LaunchAgain

End Sub

Public Sub Kill()

Dim procA As Process
Dim processList() As Process
processList = Process.GetProcesses

For Each procA In processList
If procA.ProcessName.ToUpper = "c:\somedir
\processname.exe" Then
procA.Kill()
End If
Next

End Sub

End Class
 
T

Tom Shelton

I've a Windows Service that keeps a particular executable running. If
the executable fails for whatever reason, the Service restarts it.
Right now I'm using a loop to check if the process is running. I
started with an infinite loop that ate up all of my resources, but
then added a 2 second pause after every check, which seems to have
mostly eliminated the problem of my resources being used up.

However, I'm wondering if there is a better way? Does the service
still "waste" resources while waiting for that two seconds? Is there
some kind of "process ended" event that can trigger the code to
restart the process? Following is pretty much my entire code for the
service. Pretty basic.

Imports System.Threading

Public Class fxpsMain

Friend oStartThread As Thread
Friend oStopThread As Thread

Protected Overrides Sub OnStart(ByVal args() As String)
Dim oRun As ServerTask
oRun = New ServerTask
oStartThread = New Thread(New ThreadStart(AddressOf
oRun.ContinuousRun))
oStartThread.Start()
End Sub

Protected Overrides Sub OnStop()
oStartThread.Abort()

Dim oRun As ServerTask
oRun = New ServerTask
oStopThread = New Thread(New ThreadStart(AddressOf oRun.Kill))
oStopThread.Start()
End Sub

End Class

Public Class ServerTask

Public Sub Launch()

Dim bServerRunning As Boolean = False
Dim procA As Process
Dim processList() As Process
processList = Process.GetProcesses

For Each procA In processList
If procA.ProcessName.ToUpper = "PROCESSNAME" Then
bServerRunning = True
End If
Next

If Not bServerRunning Then
Dim oProc As New Process
oProc.StartInfo.FileName = "c:\somedir\processname.exe"
oProc.StartInfo.UseShellExecute = True
oProc.Start()
End If

End Sub

Public Sub ContinuousRun()

LaunchAgain:
Launch()
'pause for 2 seconds before checking again to conserve
resources
System.Threading.Thread.Sleep(2000)
GoTo LaunchAgain

End Sub

Public Sub Kill()

Dim procA As Process
Dim processList() As Process
processList = Process.GetProcesses

For Each procA In processList
If procA.ProcessName.ToUpper = "c:\somedir
\processname.exe" Then
procA.Kill()
End If
Next

End Sub

End Class


Actually, a the system.diagnotics.process class does have an Exited
event that you can hook into. You need to obviously keep a reference
to the process, and you need to set the EnableRaisingEvents property
to true. Then you have to add a handler to the Exited event.
 
A

ags5406

Tom -

Thanks I was able to to use your method with success.

I'm having one more pretty major issue with my Windows Service that I
just cannot seem to figure out. I'll describe it below the code.

My new code looks like this...

Imports System.Threading
Imports System.IO

Public Class fxpsmMain

Private oStartThread As Thread
Private oStopThread As Thread

Protected Overrides Sub OnStart(ByVal args() As String)

Dim oRun As ServerControl
oRun = New ServerControl
oStartThread = New Thread(New ThreadStart(AddressOf
oRun.serverlaunch))
oStartThread.Start()

End Sub

Protected Overrides Sub OnStop()

'kill the start thread so it won't restart the exe after I've
killed it
oStartThread.Abort()

Dim oRun As ServerControl
oRun = New ServerControl
oStopThread = New Thread(New ThreadStart(AddressOf
oRun.ServerKill))
oStopThread.Start()

End Sub

End Class

Public Class ServerControl

Private WithEvents procServer As New Process

Public Sub ServerLaunch()

Dim sPathandFilename As String = "sample.exe"


Dim bServerRunning As Boolean = False
Dim procDummy As Process
Dim procList() As Process
procList = Process.GetProcesses

For Each procDummy In procList
If procDummy.ProcessName.ToUpper = "SAMPLE" Then
bServerRunning = True
Exit For
End If
Next procDummy

procServer.EnableRaisingEvents = True
If Not bServerRunning Then
If File.Exists(sPathandFilename) Then
procServer.StartInfo.FileName = sPathandFilename
procServer.StartInfo.UseShellExecute = True
procServer.Start()
End If
End If

End Sub

Public Sub procServer_Exited(ByVal sender As Object, ByVal e As
System.EventArgs) Handles procServer.Exited

ServerLaunch()

End Sub

Public Sub ServerKill()

Dim procDummy As Process
Dim procList() As Process
procList = Process.GetProcesses

For Each procDummy In procList
If procDummy.ProcessName.ToUpper = "SAMPLE" Then
procDummy.Kill()
End If
Next procDummy

End Sub

End Class


Okay my problem is as follows. The sample.exe file acts as a
middleman between several Fortran DLL's and some different client
apps. As the server code is shown, it WILL NOT start sample.exe,
despite the fact that service.exe (the windows service) was installed
from the same location as sample.exe. It wants the full explicit path
to sample.exe.

If I change this line
Dim sPathandFilename As String = "sample.exe"
to
Dim sPathandFilename As String = "C:\full path\sample.exe"
then the service starts and restarts sample.exe like it should.

Seems okay. But it's not. In the same folder as sample.exe are the
FORTAN DLL's and several configuration files (some binary and text
files that the DLL's use to get engineering data). My FORTRAN code
and my sample.exe code has never had explicit file paths. I've always
just kept sample.exe, the DLL's and the configuration files in the
same folder and everything works just fine if I launch sample.exe
manually just by double clicking on it.

But now, through all kinds of testing, I've determined that in order
for this to work when sample.exe is started by the service, I must
have the explicit file paths anywhere I reference an external file in
sample.exe or in the DLL's. For me this is not desirable. I do not
want to force explicit paths.

I cannot for the life of me figure out why explicit file paths are not
needed in my vb.net or fortran code when I launch sample.exe manually,
but they are required when the service launches sample.exe for me. Is
it possible that the service is running sample.exe from some other
location than "C:\full path\sample.exe"?

Thanks.
 
A

ags5406

Okay I may just be creating one long conversation with myself here but
this may help someone else in the future.

I've narrowed the problem down to the "current working directory."
When I launch sample.exe manually from the folder where it is
location, the CWD gets set to that folder. So then the FORTRAN dll's
use that CWD (i'm not sure how they get it) to look for the config
files.

But when the service launches sample.exe, even though it's located in
folder C:\full path\etc\etc..., the CWD gets set to C:\Windows
\System32, and the fortran dll looks there for the config files (and
bombs because they aren't there).

So I'm now trying to figure out how to set the CWD to the location of
the sample.exe when the service launches it. I'm guessing I do this
from within the code for the service.
 
A

ags5406

Okay I may just be creating one long conversation with myself here but
this may help someone else in the future.

I've narrowed the problem down to the "current working directory."
When I launch sample.exe manually from the folder where it is
location, the CWD gets set to that folder. So then the FORTRAN dll's
use that CWD (i'm not sure how they get it) to look for the config
files.

But when the service launches sample.exe, even though it's located in
folder C:\full path\etc\etc..., the CWD gets set to C:\Windows
\System32, and the fortran dll looks there for the config files (and
bombs because they aren't there).

So I'm now trying to figure out how to set the CWD to the location of
the sample.exe when the service launches it. I'm guessing I do this
from within the code for the service.
 
A

ags5406

Solved it finally.

Public Sub ServerLaunch()

Environment.CurrentDirectory = "C:\full path\"

Dim bServerRunning As Boolean = False
Dim procDummy As Process
Dim procList() As Process
procList = Process.GetProcesses

For Each procDummy In procList
If procDummy.ProcessName.ToUpper = "SAMPLE" Then
bServerRunning = True
Exit For
End If
Next procDummy

procServer.EnableRaisingEvents = True
If Not bServerRunning Then
If File.Exists("sample.exe") Then
procServer.StartInfo.FileName = "sample.exe"
procServer.StartInfo.UseShellExecute = True
procServer.Start()
End If
End If

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