Search code examples
c#.netwindows-serviceswindowserror

Windows Service Error: 1053, Can't figure out why


I've been working on creating a windows service that receives a JSON result from an API. It then takes that data, deserializes it into a list of objects. Then uses information from those objects to send an email.

So far i've been writing and testing using it like a console application via a method described here: https://social.technet.microsoft.com/wiki/contents/articles/30957.c-windows-service-in-console-mode-for-debug-and-admin.aspx

This worked really well and the service accomplished everything I wanted it to do. Now it was time to build it into a true service and install on my machine and test it that way.

The solution builds just fine and the installer works as well. Once installed, if I try to start the service I am met with Error: 1053 and the service is stuck as "Starting". I then have to uninstall and restart the computer to make any changes and build again to test.

So far I have tried:

  1. Changing the timeout settings in the registry
  2. Making sure the service is using the highest .Net Framework installed on the machine
  3. I created a new windows service project that doesn't use the 'console mode' mentioned above
  4. The project is set to release mode everywhere I could change the setting
  5. I removed the use of EventLog
  6. I moved most of everything out of my OnStart into a separate method and call it using a thread

My OnStart:

//prints function we are in to the debug console and sets the service
//status, as well as adds an entry to the event log
Debug.WriteLine("In OnStart.");
ServiceStatus serviceStatus = new ServiceStatus();
serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING;
serviceStatus.dwWaitHint = 100000;
SetServiceStatus(this.ServiceHandle, ref serviceStatus);
//eventLog1.WriteEntry("In OnStart.", EventLogEntryType.Information);

Thread t = new Thread(new ThreadStart(MainRunner));
t.Start();

// Update the service state to Running.
serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING;
SetServiceStatus(this.ServiceHandle, ref serviceStatus);

MainRunner():

//timer used for evaluating every hour from start time
System.Timers.Timer timer = new System.Timers.Timer();
timer.Elapsed += new ElapsedEventHandler(this.OnTimer1);
timer.Interval = /*3600000;*/ 60000;// for 1 minute testing

//starts the timer
timer.Start();

DateTime hour = new DateTime(1, 1, 1, 17, 0, 0);


//checks faulty vehicles for the day, everyday at 5pm
while (true) //infinite loop
{
    //gets the current DateTime
    DateTime Now = DateTime.Now;

    //verifies that the current DateTime is 5pm and not a Saturday or Sunday
    if (Now.Hour == hour.Hour && Now.Minute == hour.Minute && Now.Second == hour.Second
        && Convert.ToInt32(Now.DayOfWeek) != 0 && Convert.ToInt32(Now.DayOfWeek) != 6)
    {
        TwenFourHour(); //calls the daily check
        //prints to debugger that daily check is done
        Debug.WriteLine("Out of TwenFourHour");
        //eventLog1.WriteEntry("Out of TwenFourHour", EventLogEntryType.Information);
     }
}

SetServiceStatus():

[DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool SetServiceStatus(System.IntPtr handl, ref ServiceStatus serviceStatus);

This comes directly from Microsoft here: https://learn.microsoft.com/en-us/dotnet/framework/windows-services/walkthrough-creating-a-windows-service-application-in-the-component-designer?redirectedfrom=MSDN

I'm sure there are better ways to do what im doing in here (like a scheduled task, but it's not what was asked of me) but it's what I came up with. Essentially I need to access one GET response from the API every hour. This does not send an email. I also need to access a separate GET response every day at 5pm, this sends an email. I needed to exclude weekends from this as well. Weekends for the hourly check are handled in the timer's method.


Solution

  • I figured out the issue.

    It's with the while loop. I'm surprised as I saw this mentioned as a method of time checking within a service in a few posts here but I guess it's very unhappy with it.

    What i've done instead is now run a timer every minute. The timer then checks against the hour and minute (ignoring seconds, since the timer could be started anywhere from 0-59). This way it's bound to tick once anywhere within 5pm.