Threads / Timers Troubles While Creating System Service Under VB.NET 4

Go To StackoverFlow.com

3

I thought that creating a simple system service under VB .NET would be a piece of cake. Boy, was I wrong. First, I find general postings through Google that say you should use the Windows.Forms.Timer. Then, I found conflicting information that says you have to derive the timer from a timer class through code to make it work. Then, people are reporting all sorts of trouble using the various types of threads available. I can't debug threads using the VS 2010 Just-in-Time debugger for obvious reasons (although, I don't know if there is an alternate method to doing this). Wow, how confusing all this is when there is no definitive guide...

My project is an application launcher (similar to cron) that will fire off periodically within a certain amount of seconds. I am trying to use the Process.Start() method. I have a Beep() function as the first instruction, and the Process.Start, along with a Process.WaitForExit method to make it block as the last instruction. I had my code doing this through timers, but now I am starting to use threads. No difference in execution. The over-ridden OnStart method does kick off (as I am certain through debugging), but nothing ever happens when starting the service in production, as if it were ignoring all my code. Putting loops and logic in the OnStart method yields a process that won't start. I know it is a threading issue, but I also know it must be mandatory to use threads. I am now dumbfounded as to how to make this work. I am curious to know the solution.

In addition to the service class, I have a ServiceInstaller and ProcessInstaller implemented that I copied verbatim from MSDN.

Here is some of the code I am trying to work with. Note that this simply reflects the current state of my code in trying to implement the logic within a thread instead of a timer (which to me would be optimal):

    Dim config As String
    Dim configValues(2) As String
    Dim objReader As System.IO.StreamReader
    Dim interval As Integer
    Dim launchProcess As Process

    While True
        Beep()
        ' This sub runs every time the elapsed milli-seconds of the timer pass
        ' Sp add your code here.

        config = "30 c:\WiFiDropOutFix\start.vbs"

        Try
            objReader = New System.IO.StreamReader("C:\WiFiDropOutFix\config.txt")
            config = objReader.ReadToEnd
            objReader.Close()
        Catch ex As Exception

        End Try

        configValues = config.Split(New Char() {" "c})
        interval = Convert.ToInt32(configValues(0))

        If Not interval > 0 And Not interval < 61 Then
            interval = 10
        End If

        launchProcess = Process.Start(configValues(1))
        launchProcess.WaitForExit()

        Thread.Sleep(interval * 1000)

    End While
End Sub

Here is my OnStart Code by Request:

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

    appLaunchLogicThread = New Thread(AddressOf appLaunchLogic)
    appLaunchLogicThread.Start()

End Sub

TIA.

2012-04-05 18:56
by nembutoll
Can we have look at your OnStart code - Brian Gideon 2012-04-05 19:12
OnStart code is now provided. Note that the Sub appLaunchLogic is simply defined as just that: "Sub appLaunchLogic()". A timer tick method would make all this unnecessary - nembutoll 2012-04-05 19:44
Public appLaunchLogicThread As Threa - nembutoll 2012-04-05 19:45
Yeah, I don't see anything flagrant with your OnStart code. I think you are going to have to instrument your code with logging information verbose enough to provide clues as to why this isn't working in production - Brian Gideon 2012-04-05 19:50
One idea...there could be a permissions issue that is causing Process.Start to throw an exception which will terminate the thread. Put a try-catch around all of your code and log all exceptions to a file - Brian Gideon 2012-04-05 19:52
Also how do you know it's not starting the process? Keep in mind that services run not only under another account (permissions) but also in another desktop, so that you won't see any user interface, etc. opened by the process you started - aKzenT 2012-04-05 19:52
Regarding the permissions: it might be that your service account doesn't have permission to access C:\WiFiDropOutFix\config.txt you should remove this code temporarily - aKzenT 2012-04-05 19:54
Ok. The process I'm trying to start is a VBScript file that kicks off UAC Authentication. This is actually what I want. Is there any way to make the service's desktop conform to the user's? I am concerned that I am not getting any beeps out of the system regardless - nembutoll 2012-04-05 20:02


1

Try going to the Service control panel, Editing the properties on your service, and checking the option that says either "Interactive Service" or "Allow Service to Interact With the Desktop". If you are trying to fire up a new process and see it on the screen, nothing will happen unless this option is enabled.

Also, set the logon credentials of the service to Administrator to ensure it is not a permissions problem. If it works, you have discovered the issue.

One other tip: Write all the processing code as a normal app which you can easily debug, and once all the bugs are ironed out and you know the code is flawless, then implement it as a service.

2012-04-05 19:57
by Bork Blatt
Is there any way I can simulate launching the app from the Local System Service Account - nembutoll 2012-04-05 20:12
Also, I am working with a system that has a password-less Administrator account. I can't seem to get the service to login successfully with it. Anyway to bypass this without setting a password - nembutoll 2012-04-05 20:13
Not that I know of - since it is really designed for services. Writing as a normal app though will ensure you get all the non service related headaches out, and then you can be sure you are dealing with security or threading issues related to running as a service. I would (1) write a normal app to process, then (2) take the app and make the processing code run in another thread, then finally when all that is working (3) move the code into a service. Also, seeing as how a service is basically invisible, debugging will usually need to be done using log files - Bork Blatt 2012-04-05 20:15
You can always create another user with a password and add them to the Administrators grou - Bork Blatt 2012-04-05 20:16
I think this article will only be useful in very specific security problem situations, but may be of help: http://blogs.msdn.com/b/adioltean/archive/2004/11/27/271063.asp - Bork Blatt 2012-04-05 20:21
Ok, I have practically given up on this project. I have run the service with an account with Administrator rights, but I still can't get the VBScript to run, even while trying to execute it with wscript.exe. It must have something to do with the UAC authentication. There must be a reason why all of these Windows cron GUIs go for many hundreds of dollars - nembutoll 2012-04-06 02:42


0

Ok, I have managed to find something of a reason behind why my project wasn't working. I do recall seeing someone say that the [STAThread] directive was necessary for launched processes to execute within a service, and it had to be placed right before the Main function. Codeproject has issued a cron project for Windows Services in C#, and it uses this directive. I will have to look at this issued project more, but perhaps it can't be implemented in VB .NET. At this point, I do not understand how to incorporate a service launcher through a Main function / class through the VB .NET Visual Studio Service template, since it seems to launch itself by itself already.

Also, I have finally managed to find a Windows cron service program that will work within seconds that doesn't have a mandatory commercial license, can be used for free, and has an affordable registration (from what is indicated on the Website). It is called WinCron.

2012-04-06 17:49
by nembutoll
Ads