Windows services with windows forms in the same pr

2020-06-18 09:29发布

问题:

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.

回答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.



回答2:

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



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



回答4:

Here is a way mixing up Services and Forms

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



回答5:

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);
}


回答6:

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 iamjavademon@gmail.com for a better illustration using screen shots And explain in full



回答7:

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;
}


回答8:

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.