2
votes

I have a WCF Service Using MSMQ hosted on IIS. I want to create a windows application which can stop WCF Service from picking MSMQ message. Once I have seen the MSMQ message in the queue I need to click a button and Start the WCF service to pick the message in MSMQ. Code sample would be apperciated.

3
Just so you know, it's generally not good SO practise to ask for responders to write code for you. Responders will often offer code samples if they think that their answers require them for clarity. Also responders are happy to review code which you have written already. Most will expect you to at least have a go at writing your own code.tom redfern

3 Answers

1
votes

IIS is not an appropriate container to host a MSMQ client in. This is because when the app pool unloads during times of low traffic the queue client also unloads. This behaviour is automatic and you don't have any control over it.

It would be far better to host your client in a windows service. However, the kind of "consume-on-demand" functionality you require is not easy to achieve and certainly is not supported by the standard bindings.

The best I can suggest is consume the message as soon as it's received and persist it somewhere until the user clicks the button, upon which you do whatever you want as the data in the message is already available.

1
votes

I was able to solve this problem by applying a workaround. I created another queue in a different machine. Changed the address of the WCF client endpoint address to this queue in config. I created another external application which moved the message from the alternate queue to the actual queue. Thus the behavior of stopping IIS hosted WCF service with MSMQ binding was achieved

0
votes

Stopping the "Net.Msmq Listener Adapter" Windows service and the "Windows Process Activation Service" will stop the messages from being pulled out of the queue. Starting the services back up will causes the messages to be pulled from the queue again. I'm doing this manually, rather than through another application, but I'd assume you could do it through another application as well. I haven't tested this completely, but something like this would probably work:

    Dictionary<string,List<string>> runningDependentServices = new Dictionary<string,List<string>>();
    private void StartMsmqBinding()
    {
        StartService("WAS");
        StartService("NetMsmqActivator");
    }
    private void StopMsmqBinding()
    {
        StopService("NetMsmqActivator");
        StopService("WAS");
    }
    private void StartService(string serviceName)
    {
        List<string> previouslyRunningServices = null;
        var sc = new ServiceController();
        sc.ServiceName = serviceName;
        if (runningDependentServices.ContainsKey(serviceName))
        {
            previouslyRunningServices = runningDependentServices[serviceName];
        }
        try
        {
            sc.Start();
            sc.WaitForStatus(ServiceControllerStatus.Running);
            if(previouslyRunningServices != null)
            {
                previouslyRunningServices.ForEach(a =>
                {
                    var serviceController = new System.ServiceProcess.ServiceController() { ServiceName = a };
                    serviceController.Start();
                    serviceController.WaitForStatus(ServiceControllerStatus.Running);
                });
            }

        }
        catch (InvalidOperationException)
        {
        }
    }
    private void StopService(string serviceName)
    {
        var sc = new System.ServiceProcess.ServiceController() { ServiceName = serviceName };
        runningDependentServices[serviceName] = sc.DependentServices.Where(a => a.Status == System.ServiceProcess.ServiceControllerStatus.Running).Select(a => a.ServiceName).ToList();
        if (sc.CanStop)
        {
            try
            {
                sc.Stop();
                sc.WaitForStatus(ServiceControllerStatus.Stopped);
            }
            catch (InvalidOperationException)
            {
            }
        }
    }

I'd think a similar approach would work for Net.Tcp binding. You'd probably have to stop the "Net.Tcp Listener Adapter" Windows service (ServiceName: "NetTcpActivator") and the "Windows Process Activation Service" in that case.