Topshelf - starting threads based on custom parameters
Asked Answered
C

2

2

I've made a topshelf webservice that uses custom parameter:

string department = null;

// *********************Below is a TopShelf
HostFactory.Run(hostConfigurator =>
{
    //Define new parameter
    hostConfigurator.ApplyCommandLine();                                                
    //apply it  
    hostConfigurator.AddCommandLineDefinition("department", f => { department = f; });

    Helpers.LogFile("xxx", "Got department:"+department);  

    hostConfigurator.Service<MyService>(serviceConfigurator =>
    {
        //what service we are using
        serviceConfigurator.ConstructUsing(() => new MyService(department));
        //what to run on start
        serviceConfigurator.WhenStarted(myService => myService.Start());
        // and on stop             
        serviceConfigurator.WhenStopped(myService => myService.Stop());                 
    }

    hostConfigurator.RunAsLocalService();

    //****************Change those names for other
    string d = "CallForwardService_" + department;

    hostConfigurator.SetDisplayName(d);
    hostConfigurator.SetDescription("CallForward using Topshelf");
    hostConfigurator.SetServiceName(d);                
});



public class MyService
{
    string depTask;
    public MyService(string d)
    {
        //***********************Three tasks for three different destinations
        depTask = d;
        _taskL = new Task(Logistics);
        _taskP = new Task(Planners);
        _taskW = new Task(Workshop);
        Helpers.LogFile(depTask, "started working on threads for "+d);   

        public void Start()
        {
            if (depTask == "logistics")
            {
                _taskL.Start();
                Helpers.LogFile(depTask, "proper thread selected");      
            }
        }
    }
}

Where Helpers.logfile simply writes to text file. Aa you can see from the code above the parameter department is passed to the MyService(string d). It all works fine when I'm debugging using i.e. the "-department:workshop" as debugging parameter. But when I'm trying to install the program as a service using callforward.exe install -department:logistics I do create service callforwardservice_logistics bu when I check the log the parameter hasn't been passed to the MyService.

What am I doing wrong?

Cheek answered 24/4, 2015 at 2:16 Comment(0)
H
2

It seems that by default Topshelf does not support adding custom parameters to the service start configuration and after installation the ImagePath value under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MyService does not contain an additional parameter -department:.... You could inherit the default WindowsHostEnvironment and overload the Install method, but I think it would be easier (maybe less nicer) to just add the following code to your host configuration code:

// *********************Below is a TopShelf code*****************************//
HostFactory.Run(hostConfigurator =>
{
    ...
    hc.AfterInstall(ihc =>
    {
        using (RegistryKey system = Registry.LocalMachine.OpenSubKey("System"))
        using (RegistryKey currentControlSet = system.OpenSubKey("CurrentControlSet"))
        using (RegistryKey services = currentControlSet.OpenSubKey("Services"))
        using (RegistryKey service = services.OpenSubKey(ihc.ServiceName, true))
        {
            const String v = "ImagePath";
            var imagePath = (String)service.GetValue(v);
            service.SetValue(v, imagePath + String.Format(" -department \"{0}\"", department));
        }
    });
    ...
}
Hirschfeld answered 24/4, 2015 at 7:47 Comment(1)
This is a highly requested feature though, and would be a welcome pull request. I'm sure I will get to it eventually, it's just naught high on my radar at this point.Impossibly
C
0

I've solved the issue in the end: Setting up the parameter is not enough, you have to also create a named instance.

So in my case instead

callforward.exe install -department"logistics"

I've used

callforward.exe install -department"logistics" -instance:logistics

And then start the instance by the instance name:

net start CallForwardService_$logistics

This lets me to create multiple instances of the same service with different names controlled by the parameter:

enter image description here

Cheek answered 26/5, 2020 at 1:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.