0

Long Story short I built a console application that worked just fine, then was told that it needed to be a windows service. So I constructed a windows service project pretty much following Microsoft's recommendations and the service runs and starts and stops fine but it doesn't start the application that I converted from a console app to the service. I'm having trouble understanding why.

Question: How do you start a long running process using a windows service? Can windows services not utilize code in class library's?

public partial class CallQService : ServiceBase

{
private static System.Threading.Timer _timer;
private static CallQ _callQ;

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

public CallQService(string[] args)
{
    // Update the service state to Start Pending.  
    ServiceStatus serviceStatus = new ServiceStatus();
    serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING;
    serviceStatus.dwWaitHint = 100000;
    SetServiceStatus(ServiceHandle, ref serviceStatus);

    InitializeComponent();

    string eventSourceName = "MySource";
    string logName = "MyNewLog";
    if (args.Any())
    {
        eventSourceName = args[0];
    }
    if (args.Length > 1)
    {
        logName = args[1];
    }
    eventLog1 = new EventLog();
    if (!SourceExists(eventSourceName))
    {
        CreateEventSource(eventSourceName, logName);
    }
    eventLog1.Source = eventSourceName;
    eventLog1.Log = logName;

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

protected override void OnStart(string[] args)
{
    Debugger.Launch();

    eventLog1.WriteEntry("The Service Has Started");

    System.Timers.Timer timer = new System.Timers.Timer
    {
        Interval = 60000 // 60 seconds  
    };
    timer.Elapsed += new ElapsedEventHandler(OnTimer);
    timer.Start();

      //This is where the process starts that is supposed to run my application and generate my data. It does not do that at all. it hits this and runs through the code in this class file, but once it is supposed to move into code in one of my class library's it just stops and doesn't do anything else.
    Initialize();
}

private void OnTimer(object sender, ElapsedEventArgs e)
{
    // TODO: Insert monitoring activities here.  
    eventLog1.WriteEntry("Monitoring the System", EventLogEntryType.Information);
}

protected override void OnContinue()
{
    eventLog1.WriteEntry("In OnContinue.");

    // Update the service state to Running.  
    ServiceStatus serviceStatus = new ServiceStatus();
    serviceStatus.dwCurrentState = ServiceState.SERVICE_CONTINUE_PENDING;
    serviceStatus.dwWaitHint = 100000;
    SetServiceStatus(ServiceHandle, ref serviceStatus);

    serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING;
    SetServiceStatus(this.ServiceHandle, ref serviceStatus);
}

protected override void OnPause()
{
    // Update the service state to Start Pending.  
    ServiceStatus serviceStatus = new ServiceStatus();
    serviceStatus.dwCurrentState = ServiceState.SERVICE_PAUSE_PENDING;
    serviceStatus.dwWaitHint = 100000;
    SetServiceStatus(ServiceHandle, ref serviceStatus);

    eventLog1.WriteEntry("The Service has Stopped.");

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

protected override void OnStop()
{
    // Update the service state to Start Pending.  
    ServiceStatus serviceStatus = new ServiceStatus();
    serviceStatus.dwCurrentState = ServiceState.SERVICE_STOP_PENDING;
    serviceStatus.dwWaitHint = 100000;
    SetServiceStatus(ServiceHandle, ref serviceStatus);

    eventLog1.WriteEntry("The Service has Stopped.");

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

public static void Initialize()
{
    var callDataRepo = CreateCallDataRepo();
    var skillsRepo = CreateSkillsRepo();

    _callQ = new CallQ(skillsRepo, callDataRepo);
    _callQ.Start();
    SetUpTimer(new TimeSpan(06, 46, 00));
}

private static ISkillsRepo CreateSkillsRepo()
{
    // Generates an instance of Config data for pulling down skills from OADB database
    ISkillsDataRepoConfig skillDataRepoConfig = new SkillsDataRepoConfig();
    // generates an instance of skills repo and pulling in call data repo OADB databse config
    ISkillsRepo skillsRepo = new SkillsRepo(skillDataRepoConfig);
    return skillsRepo;
}

private static ICallDataRepo CreateCallDataRepo()
{
    // Generates an instance of Config data for pulling down skills from OADB database
    ICallDataRepoConfig callDataRepoConfig = new CallDataRepoConfig();
    // generates an instance of call data repo and pulling in call data repo OADB databse config
    ICallDataRepo callDataRepo = new CallDataRepo(callDataRepoConfig);
    return callDataRepo;
}

private static void SetUpTimer(TimeSpan alertTime)
{
    DateTime current = DateTime.Now;
    TimeSpan timeToGo = alertTime - current.TimeOfDay;
    if (timeToGo < TimeSpan.Zero)
    {
        return;//time already passed
    }
    _timer = new System.Threading.Timer(x =>
    {
        _callQ.StopGenerators();
        _callQ.Start();
    }, null, timeToGo, Timeout.InfiniteTimeSpan);
}

}

  • Did you try moving code present in initialize method to OnStart method and see if application is starting? – Pankaj Kapare Aug 15 '17 at 15:11
  • Check the Windows error logs. Sometimes there is a run-time error, which causes the service not to run. These errors usually get logged in OS error logs. – Sparrow Aug 15 '17 at 15:11
  • @OwenPauling I'll try to create a background thread for this and see if that helps. I do want to note that unlike what is happening in the other post, my service doesn't stop running. – michaeltc1989 Aug 15 '17 at 15:13
  • @PankajKapare Moving the code in initialize into onstart does not change anything – michaeltc1989 Aug 15 '17 at 15:13
  • @Sparrow No errors are being reported. it reports every minute as a timer like i have set but their are no errors. – michaeltc1989 Aug 15 '17 at 15:14
  • @OwenPauling Creating a new background thread did not change the way the service is acting – michaeltc1989 Aug 15 '17 at 15:19
  • Not sure of the time where you are, but are you adjusting the time in `SetUpTimer` so that when you start the service `timeToGo` is greater than the current time? – Scrobi Aug 15 '17 at 15:28
  • _If_ you are in Detroit then 11:31 is after 6.45 so the `SetupTimer` just return and not set up the timer for `_callQ` – Scrobi Aug 15 '17 at 15:33
  • the timer has nothing to do with the initial start of the application. it is designed to begin a process of shutting down and restarting the entire application every day at 6:46AM – michaeltc1989 Aug 15 '17 at 18:03
  • You seem to be confusing two different ways of designing a service in .NET code. You can do it yourself by calling the API functions such as SetServiceStatus, **or** you can use ServiceBase. You're not supposed to do both at once! (Also, you haven't posted your main function.) – Harry Johnston Aug 15 '17 at 22:34
  • ... I'm also suspicious of that call to `InitializeComponent` which doesn't seem right in a service. – Harry Johnston Aug 15 '17 at 22:36

1 Answers1

0

Normally if you have some objects which should exist for the lifetime of a service, it is not a good idea to have them as local variables in your OnStart method. It is likely to go out of scope and garbage collected.

i.e., make your timer a member variable of your Class and see whether this makes any difference.

Subbu
  • 2,130
  • 1
  • 19
  • 28