Windows services with windows forms in the same process

19,002

Solution 1

Two separate processes that communicate using your technology of choice. Services with UI is a bad idea. Don't go down this road - you'll regret it.

I've had very good results having service communication through a simple socket connection - document your service protocol well, keep it as simple as possible, and it'll be easier than you think.

Solution 2

In practice you should not couple your service with the management UI.

Solution 3

I agree with Greg. Perhaps you could examine a different IPC mechanism. Perhaps use sockets and your own protocol. Or, if your service control app can only control the service on the local machine, you can use named pipes (even faster).

Solution 4

I figured out how to do this from this article (click on the "Change" link in the Methods table).

string wmiPath = "Win32_Service.Name='" + SERVICE_NAME + "'";
using (ManagementObject service = new ManagementObject(wmiPath))
{
    object[] parameters = new object[11];
    parameters[5] = true;  // Enable desktop interaction
    service.InvokeMethod("Change", parameters);
}

Solution 5

I have the solution in a few steps, this is the plan

  1. we are not going to create a service project with a a windows form, instead we are going to create a visual studio solution that contains a windows service project, a windows form project and a setup project.

  2. The idea is to have a database or a file or anything you are comfortable with storing data in which you would store the parameters your windows service will always use to run. So your windows service and your windows form application should be able to modify and retrieve data from it.

  3. To the Main Form Of Your Windows Application drag and drop a NotifyIcon on the form, in the properties tab, browse and select an .ico image(You can sreate one in visual studio but that is another topic you can get on google or contact me) That it will display in the system tray when you run the application and the main form is active or shown, try it, run the application.

  4. Add both of them as outputs in the setup project of the solution. To Add a project to a setup project they must be in the same solution. Right click the setup project in the solution explorer, highlight add and then select project output, add the windows service and the windows form outputs and you will see them in the solution explorer under the setup project.

  5. adding a windows service goes further than this but that also is another topic google it

  6. Creating shortcut for the windows application and adding it to the startup folder is also another topic google or contact me.

    NOTE Program your form in such a way that the close button doesn't show and the form goes Me.visible = false and double clicking the icon in the system tray is the only way to set me.visible=true.that way anytime the computer starts up, your windows form application is also started and visible is immediately set to false but since it has a notifyicon with an icon image, it will show in the system tray and double clicking it makes the form visible to edit the settings that you are storing for the service, the service also starts automatically since you would have set it in setting up the service in the setup project. my mail is [email protected] for a better illustration using screen shots And explain in full

Share:
19,002
andrecarlucci
Author by

andrecarlucci

.Net Software Architect | Speaker | Making developer's lives better building beautiful frameworks and scalable APIs.

Updated on June 16, 2022

Comments

  • andrecarlucci
    andrecarlucci almost 2 years

    I have a c# application that runs as a windows service controlling socket connections and other things. Also, there is another windows forms application to control and configure this service (systray with start, stop, show form with configuration parameters).

    I'm using .net remoting to do the IPC and that was fine, but now I want to show some real traffic and other reports and remoting will not meet my performance requirements. So I want to combine both applications in one.

    Here is the problem:

    When I started the form from the windows service, nothing happened. Googling around I've found that I have to right click the service, go to Log on and check the "Allow service to interact with desktop" option. Since I don't want to ask my users to do that, I got some code googling again to set this option in the user's regedit during installation time. The problem is that even setting this option, it doesn't work. I have to open the Log On options of the service (it is checked), uncheck and check again.

    So, how to solve that? How is the best way to have a windows service with a systray control in the same process, available to any user logging in?

    UPDATE: Thanks for the comments so far, guys. I agree it is better to use IPC and I know that it is bad to mix windows services and user interfaces. Even though, I want to know how to do that.

  • mattlant
    mattlant over 15 years
    I totally agree with this. If possible I would look at some communication method not as bloated as remoting. sockets, pipes, etc
  • John Rudy
    John Rudy over 15 years
    @andrecarlucci: When we talk about services with UI, it's not "personal preference," it's architectural fact. Going with TCP/IP sockets and a simple, well-documented protocol will be your best way to get there from here, without the issues associated with Service+UI in the same process.
  • andrecarlucci
    andrecarlucci over 15 years
    Hi all. I agree with you all. DotNet remoting is just that. But that's not the question, the question is how is the best way to do that in the same process and not the best way at all. I will rephrase my update so it doesn't sound rude, sorry about that.
  • Orion Adrian
    Orion Adrian over 15 years
    You can't do it in the same process safely. The problem is that you want part of your program to be session-independent and part of your program to be session-dependent. It's not possible in a modern environment.
  • Cipi
    Cipi over 12 years
    Yeah, I used your code here, and it works. But I made new Console App that is run after the service installation is finished... so, if someone tried to put this somewhere in OnStart() it doesn't work like that.
  • Cipi
    Cipi over 12 years
    And you probably want to edit this and add: parameters[6] = "LocalSystem"; parameters[7] = ""; so the Logon as local system account gets selected. ;)
  • Phil
    Phil over 12 years
    Assuming you want the LocalSystem account. Most of the time I think people will want to keep the account the same rather than make sure the account is LocalSystem.