0

I have successfully compiled and run Windows Service with WCF. With installutil, the Windows Service is successfully getting installed and started. I think I am at the end of my development and just need to invoke/call the method DoJobs() inside WCF. I don't need any user interaction and so I don't have any Windows forms or anything. I just want to invoke/call my WCF function programmatically just after serviceHost.Open();

The base address in app.config file is

http://localhost:8733/Design_Time_Addresses/WcfServiceLibrary1/Service1/

I am deploying my WCF from Windows service with the following code.

// Create a ServiceHost for the CalculatorService type and provide the base address.
serviceHost = new ServiceHost(typeof(WcfServiceLibrary1.Service1));

// Open the ServiceHostBase to create listeners and start listening for messages.
serviceHost.Open();

I have also added the service reference and created the below proxy, but not sure of its use.

WcfServiceLibrary1.WCFServiceRef.Service1Client

I have searched tutorials, the examples show how to invoke the WCF function on button_click event of any form after running Windows service. I just want to do that programmatically on start-up of Windows Service.

EDIT: The code inside my DoJobs() fetches the active tab url of firefox with DDE Client, which throws exception when done only in a Windows Service project but runs successfully when done in WCF project. Please see this for reference. So I made a C#.Net solution with WCF called from a Windows Service and then I called DoJobs() inside Windows Service as shown below.

WcfServiceLibrary1.WCFServiceRef.Service1Client wcfObj = null;
...
protected override void OnStart(string[] args)
{
    if (serviceHost != null)
    {
        serviceHost.Close();
    }

    serviceHost = new ServiceHost(typeof(WcfServiceLibrary1.Service1));
    serviceHost.Open();

    if (wcfObj == null)
    {
        wcfObj = new WcfServiceLibrary1.WCFServiceRef.Service1Client();
        wcfObj.DoJobs();
    }
}

But, it makes the call happen at the windows service layer, and is throwing the same DdeClient exceptions.

Can the base address url help any way to programmatically invoke DoJobs() in Web-Service? OR there are some other solutions.

Any help is highly appreciated.

Thanks.

TrueD
  • 75
  • 2
  • 10
  • Are you saying you want the Windows Service to in effect call into the WCF service it is hosting (call itself) **or** a client process invoke the WCF service (external process)? –  Sep 07 '14 at 10:21
  • I don't have anything like win form to invoke, so I think the OnStart() method of Windows Service is the only place to where I can invoke wcf DoJobs() through code right after serviceHost.Open() – TrueD Sep 07 '14 at 10:46
  • Yes, assuming your WCF service has a method called `DoJobs()` then I recommend that too –  Sep 07 '14 at 11:40
  • You can't use _Dynamic Data Exchange_ (DDE) in a Windows Service because the latter does not have a message pump. You can use DDE in programs which do have a message pump does as a GUI. [See this article for more](http://msdn.microsoft.com/en-us/library/windows/desktop/ms648993(v=vs.85).aspx) –  Sep 07 '14 at 13:49
  • Truly appreciate all your help. Is that the only solution Micky? I was really hopeful for some better solutions. In that case, I need to add a win form project consuming the WCF DoJobs() method and call the win form from Windows Service OnStart() after serviceHost.Open(). To make it silent or invisible I also need to hide the win form through C# code at start-up. Am I right? – TrueD Sep 07 '14 at 14:54
  • That's right - make an invisible GUI app. It will have a message pump and therefore allow for DDE :) I only other thing I can think of is manually adding a message pump but its more effort than benefit - may as well just make it GUI in the first place. If you look at Spy++ there are quite a few Microsoft hidden GUIs you never knew where there - some even required by the OS –  Sep 07 '14 at 14:59
  • I'll jump into coding following your solution and definitely update. Still I would appreciate a solution, if you can provide at least for knowledge, about how to add a message pump manually to accomplish my mission without win form. I may even give it a try later. Many thanks. – TrueD Sep 07 '14 at 15:21
  • I wouldn't recommend it because it falls into the category of _because you can do a thing, does not mean you should do a thing_. A topic for another time. It's very similar to a recent SO question about how to display a WinForm in a console app - by default you can't and if you managed to you end up with an odd hybrid with much re-inventing of wheels. Not to mention its an **ugly hack**. :) –  Sep 07 '14 at 15:33
  • That is true and makes sense. If others agree, Mickey's solution should be voted up. – TrueD Sep 07 '14 at 16:03
  • @MickyDuncan i suggest you summarize your comments, and post it as an answer so it can be voted and selected as answered :) – Noctis Sep 07 '14 at 21:57
  • @Biswa please consider my answer below. –  Sep 08 '14 at 07:00

2 Answers2

0

Assuming you have :

// I'm assuming this is your proxy?
var proxy = WcfServiceLibrary1.WCFServiceRef.Service1Client; 

// All you need to do is :
proxy.DoJobs() ;

Having seen your update and Micky`s answers, I'm just wondering why you're using DDE. Not sure what your requirements look like, but you can always use your MSMQ to send messages and queue things.

Noctis
  • 11,507
  • 3
  • 43
  • 82
  • Earlier I did that. It calls the function but makes the call happen at the windows service layer, which I don't want. The code inside my DoJobs() fetches the active tab url of firefox with DDE Client, which throws exception in windows service but runs successfully in wcf separately. Please see this for reference (http://social.msdn.microsoft.com/Forums/vstudio/en-US/80739391-7ee4-4e78-aa0f-6733298c927b/dynamic-data-exchange-with-windows-service). Should I somehow expose the base address programmatically and make some call to DoJobs(). Please help. – TrueD Sep 07 '14 at 11:03
  • @Biswa Can you update your question then to reflect this comment. It is difficult to know exactly what your situation is –  Sep 07 '14 at 11:42
  • Noctis, I think that first line should read `var proxy = new WcfServiceLibrary1.WCFServiceRef.Service1Client()` ? –  Sep 07 '14 at 11:48
  • @MickyDuncan , probably. I don't know how he's instantiating nor creating it, but definitely he'll need the `()` there. probably a `new` as well. – Noctis Sep 07 '14 at 14:41
  • @Noctis, as I mentioned earlier in the above comment, I need to log the url of the active tab of firefox browser, which can be done through DDEClient. But Windows Service does not allow sending Windows messages across desktop programs as answered [here](http://social.msdn.microsoft.com/Forums/vstudio/en-US/80739391-7ee4-4e78-aa0f-6733298c927b/dynamic-data-exchange-with-windows-service). That's why I want to use DDE inside WCF as suggested in that same link and call WCF method through Windows Service each time my machine starts up. – TrueD Sep 08 '14 at 10:05
  • @Biswa , well, if Micky's answer works for you, problem solved :). Otherwise, you can look at other options, like MSMQ. – Noctis Sep 08 '14 at 10:28
  • Yes Noctis, I am trying Mickey's solution and surely update with the result. Regarding MSMQ, I can try that separately in another version later, because for that the code will need Message Queuing already installed, if not then it should be installed first through "turn windows features on/off". But I am required to do my job only through coding. Any option that can be achieved only through pure coding, is fine for me. So I can follow this answer [here](http://stackoverflow.com/questions/6679084/install-msmq-using-c-sharp), right? – TrueD Sep 08 '14 at 11:49
  • it'll need to be installed, correct. The how / why, is up to you I guess. I didn't have to deal with doing it via code :) – Noctis Sep 08 '14 at 13:23
0

This is my aggregated answer from my various comments I made to your post and to Noctis's answer (specifically that we did not know you were using DDE in the OP):

You can't use Dynamic Data Exchange (DDE) in a Windows Service because the latter does not have a message pump. Also DDE requires a Window handle to be passed as a parameter to DDE functions. You can use DDE in programs which do have a message pump does as a WinForms app. See this article for more information

Once your GUI app is running you can either minimize it to a Sys Tray icon or hide the app completely so the user is unaware. Regardless of its visible nature you should have no problem utilising DDE since it will have a message pump.

Now it may be the case you could add a message pump to a Windows Service but I wouldn't recommend it because it falls into the category of because you can do a thing, does not mean you should do a thing. A topic for another time. It's very similar to a recent SO question about how to display a WinForm in a console app - by default you can't and if you managed to you end up with an odd hybrid with much re-inventing of wheels. Not to mention its an ugly hack.

In summary, my best advice is to proceed with a GUI app.

  • I tried, but no luck. I am at the same position. The Windows Service will not allow calling a form to show or doing Process.Start() to start a win form exe. And Process.Start() from Windows Service also throws the same DdeClient exception as earlier since my DoJobs() method is now inside the win form constructor. Please see [link1](http://stackoverflow.com/questions/12953148/show-a-windows-form-from-a-window-service), [link2](http://stackoverflow.com/questions/418119/c-sharp-run-windows-form-application-from-service-and-in-vista). What can be the solution? What should I do now? Please help. – TrueD Sep 12 '14 at 10:51
  • That is not what I said. **Do not attempt to show a `WinForm` or utilise DDE inside a Windows Service (WS)** nor spawn interactive child processes from a WS. Why? Because there is a chance the spawned GUI app won't run if a user is not logged in. Instead, as we discussed, when you make your "invisible" GUI app, there **wont** be a need for a WS at all and the requirement will be such that a user **must** be logged in. [Justin's answer on this page you will find is what I have been saying all along](http://stackoverflow.com/questions/12953148/show-a-windows-form-from-a-window-service) –  Sep 13 '14 at 01:32
  • ok, yes I understand. But I need my application to log data every time my computer starts. How can I do that without WS? I found one option [here](http://www.codeproject.com/Articles/110568/Alternative-way-for-Window-services-to-interact-wi). Should I try this? – TrueD Sep 13 '14 at 06:15
  • @Biswa Only one question per SO topic please –  Sep 13 '14 at 12:05
  • Right Micky. Actually, I am in search of the proper recommended solution. I need to know whether Windows Task Scheduler would be the right one to implement instead of Windows Service for this kind of application that requires desktop interaction like DdeClient. – TrueD Sep 16 '14 at 07:00
  • I understand, but you can not use a `Windows Service` **period**. I would open a new Stack Overflow question regarding your new concern because honestly I'm not sure what would happen when trying to launch a message-pump based Task Scheduler task when the trigger is set to **At startup** (this is prior to user login). Wishing you well –  Sep 16 '14 at 08:04