0
votes

I created some self-hosting with Nancy then I want the app run as services. So i use topshelf to build it. Then when I debug my program or run .exe, program running well. But when I install .exe as service and start the service. I can't call the API I create with nancy (in browser only "waiting localhost.." not return error or succes). Is it because working directory, threading or anything else? thank you

Here is my code : Program.cs

public class Program
{
    [STAThread]
    public static void Main()
    {
        var thread = new Thread(WorkerMethod);
        thread.SetApartmentState(ApartmentState.STA);
        thread.IsBackground = false;
        thread.Start();
    }

    public static void WorkerMethod(object state)
    {
        HostFactory.Run(x =>
        {
            x.Service<HostingAPI>(s =>
            {
                s.ConstructUsing(name => new HostingAPI());
                s.WhenStarted(tc => tc.Start());
                s.WhenStopped(tc => tc.Stop());
            });

            x.RunAsLocalSystem();
            x.SetDescription("Hardware hosting API");
            x.SetDisplayName("Hosting Services for Hardware");
            x.SetServiceName("Hardware Services");
        });
    }
}

CDM_Module (the nancy module)

public class CDM_Module : NancyModule
{
    public CDM_Module()
    {
        try
        {
            Get["/CDM/Machine/Start"] = parameters =>
            {
                var ins = HostingAPI.Instance;
                bool result = ins.InitCDM_Thread();

                return Response.AsJson(result);
            };

            Get["/CDM/Machine/OpenGate"] = parameters =>
            {
                var ins = HostingAPI.Instance;
                bool result = ins.StartProcess_Thread();

                return Response.AsJson(result);
            };

            Get["/CDM/Machine/CloseGate"] = parameters =>
            {
                var ins = HostingAPI.Instance;
                bool result = ins.StopProcess_Thread();

                return Response.AsJson(result);
            };
        }
        catch
        {
        }
    }
}

HostingAPI.cs (start and stop function and one function called for API)

public class HostingAPI
{
    //global variable
    private NancyHost mainHost;
    public static HostingAPI Instance;
    private string hostUrl;
    //public static MainCDM Ins = new MainCDM();

    public clsCSDDPMControl ObjDPMControl = new clsCSDDPMControl();
    public ClsPrinterControl ObjPrinterControl = new ClsPrinterControl();

    //webservice
    HttpClient httpClient = new HttpClient();

    public void Start()
    {
        //set hosturl dari document xml nantinya
        //sementara default
        //under construction
        Config.ReadConfiguration();

        //set awal entity
        buildEntity();

        AddEventCDM();
        AddEventPrinter();

        Instance = this;

        if (hostUrl == null) hostUrl = "http://localhost:5030";

        mainHost = new NancyHost(new Uri(hostUrl));
        mainHost.Start();

        //Console.WriteLine("Hardware Hosting API is running on " + hostUrl);

    }

    public void Stop()
    {
        mainHost.Stop();
        //Console.WriteLine("Service stopped!");
    }

    public bool InitCDM_Thread()
    {
        var thread = new Thread(InitCDM);
        thread.SetApartmentState(ApartmentState.STA);
        thread.IsBackground = false;
        thread.Start();
        Dummy.m_autoreset.WaitOne();
        return rtn;
    }

    private void AddEventCDM()
    {
        ObjDPMControl.EvtBoxFullReceived += new clsCSDDPMControl.EvtBoxFullReceivedEventHandler(ObjDPMControl_EvtBoxFullReceived);
        ObjDPMControl.EvtDocDataReceived += new clsCSDDPMControl.EvtDocDataReceivedEventHandler(ObjDPMControl_EvtDocDataReceived);
        ObjDPMControl.EvtDocumentCounterReceived += new clsCSDDPMControl.EvtDocumentCounterReceivedEventHandler(ObjDPMControl_EvtDocumentCounterReceived);
        ObjDPMControl.EvtDPMShellMsgReceived += new clsCSDDPMControl.EvtDPMShellMsgReceivedEventHandler(ObjDPMControl_EvtDPMShellMsgReceived);
        ObjDPMControl.EvtErrMsgReceived += new clsCSDDPMControl.EvtErrMsgReceivedEventHandler(ObjDPMControl_EvtErrMsgReceived);
        ObjDPMControl.EvtEventsReceived += new clsCSDDPMControl.EvtEventsReceivedEventHandler(ObjDPMControl_EvtEventsReceived);
        ObjDPMControl.EvtImageStoredReceived += new clsCSDDPMControl.EvtImageStoredReceivedEventHandler(ObjDPMControl_EvtImageStoredReceived);
        ObjDPMControl.EvtImageStoredErrorReceived += new clsCSDDPMControl.EvtImageStoredErrorReceivedEventHandler(ObjDPMControl_EvtImageStoredErrorReceived);
        ObjDPMControl.EvtStatusReceived += new clsCSDDPMControl.EvtStatusReceivedEventHandler(ObjDPMControl_EvtStatusReceived);
        ObjDPMControl.AxEvtBackTraceFileReady += new clsCSDDPMControl.AxEvtBackTraceFileReadyEventHandler(ObjDPMControl_AxEvtBackTraceFileReady);
        ObjDPMControl.AxEvtComPortError += new clsCSDDPMControl.AxEvtComPortErrorEventHandler(ObjDPMControl_AxEvtComPortError);
        ObjDPMControl.AxEvtExtraImageError += new clsCSDDPMControl.AxEvtExtraImageErrorEventHandler(ObjDPMControl_AxEvtExtraImageError);
        ObjDPMControl.AxEvtFrontDitherReady += new clsCSDDPMControl.AxEvtFrontDitherReadyEventHandler(ObjDPMControl_AxEvtFrontDitherReady);
        ObjDPMControl.AxEvtOutOfOrder += new clsCSDDPMControl.AxEvtOutOfOrderEventHandler(ObjDPMControl_AxEvtOutOfOrder);
        ObjDPMControl.AxEvtRearDitherReady += new clsCSDDPMControl.AxEvtRearDitherReadyEventHandler(ObjDPMControl_AxEvtRearDitherReady);

        DeviceReplyCode = Convert.ToInt32(ObjDPMControl.InitDevices(Config.DpmIniFile));

    }

    private void InitCDM()
    {
        DeviceReplyCode = Convert.ToInt32(ObjDPMControl.InitDevices(Config.DpmIniFile));

        if (DeviceReplyCode == ObjDPMControl.CSDeviceSuccessCode)
        {
            if (ObjDPMControl.StartDPMEngine() == true)
            {
                if (ObjDPMControl.DPMSetTimeouts() == true)
                {
                    rtn = true;
                }
                else
                {
                    rtn = false;
                }
            }
            else
            {
                rtn = false;
            }
        }
        else
        {
            rtn = false;
        }

        Dummy.m_autoreset.Set();
    }
}

EDIT

Already try to catch exception but no one caught. I try to comment Dummy.m_autoreset.WaitOne() and Dummy.m_autoreset.Set(). Now the API works but the function inside InitCDM() not executed? In that function i call some library for machine than the machine give back feedback directly or by eventhandler. I think the eventhandler i create with AddEventCDM() not reach by library because the thread is not available anymore? Any advise?

1
The first thing I see is an empty catch block. Catch exceptions and log them. How would we know what went wrong, when you intentionally throw away the potential error messages? - nvoigt
Sorry. now I already add throw exception in NancyModule and InitCDM() HostingCDM.cs. But no exception has been thrown. - Ahmad Azam

1 Answers

0
votes

Try to start the NancyHost on a new thread in the Start() method. In my case the Start() method did not return making it impossible to start as a Windows service.