views:

2487

answers:

9

Hello, 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.

+13  A: 

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.

Greg Hurlman
I totally agree with this. If possible I would look at some communication method not as bloated as remoting. sockets, pipes, etc
mattlant
@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.
John Rudy
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.
andrecarlucci
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.
Orion Adrian
+1  A: 

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

Quintin Robinson
+1  A: 

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).

Peter Meyer
A: 

It is very simply - your need to create one thread for perform application events. Like this( source code for C++ with CLR, but your can make this in C#):

ref class RunWindow{
public:
    static void MakeWindow(Object^ data)
    {
     Application::EnableVisualStyles();
     Application::SetCompatibleTextRenderingDefault(false); 

     Application::Run(gcnew TMainForm());
    };
};

And create thread in main

int main(array<System::String ^> ^args)
{
    bool bService = RunAsService(L"SimpleServiceWithIconInTrayAndWindow");

    if (bService)
    {

     System::Threading::Thread ^thread = gcnew System::Threading::Thread(gcnew ParameterizedThreadStart(RunWindow::MakeWindow));
     thread->Start();

     ServiceBase::Run(gcnew simpleWinService());
     Application::Exit();
    }
    else
    {
     Application::EnableVisualStyles();
     Application::SetCompatibleTextRenderingDefault(false); 

     // Create the main window and run it
     Application::Run(gcnew TMainForm());
    }

    return 0;
}
CoolMagic
A: 

The main problems with interactive services are:

  • Security - other process could send it messages through its message pump, thereby gaining access to a SYSTEM/LOCAL process.

  • Incompleteness - an interactive service never sees shell messages, hence it can't interact with Notification Area icons.

We regularly use TCP and UDP connections to pass info from services to other exes, and, in some cases, MSMQ.

cookre
A: 

Here is a way mixing up Services and Forms

http://www.codeproject.com/KB/system/SystemTrayIconInSvc.aspx

A: 

I need to bump this question. If you should not couple forms and services, which I agree I guess because everyone said not too, how do you configure your service at run time??? Like with an Admin Form or something???

Jesse Seger
A: 

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);
}
Phil
A: 

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

ekeolere olaide