具有Windows窗体的Windows服务在同一进程中

时间:2008-10-01 18:38:42

标签: c# windows windows-services

我有一个c#应用程序,它作为控制套接字连接和其他东西的Windows服务运行。 此外,还有另一个Windows窗体应用程序来控制和配置此服务(带有配置参数的start,stop,show form的系统托盘)。

我正在使用.net远程处理来完成IPC,这很好,但现在我想显示一些真实的流量和其他报告,远程处理将无法满足我的性能要求。所以我想将两个应用程序合二为一。

问题在于:

当我从Windows服务启动表单时,没有任何反应。谷歌搜索我发现我必须右键单击该服务,转到登录并选中“允许服务与桌面交互”选项。由于我不想让我的用户这样做,我在安装期间再次在用户的regedit中设置了一些代码谷歌搜索。问题是即使设置此选项,它也不起作用。我必须打开服务的登录选项(已选中),取消选中并再次检查。

那么,如何解决?在同一进程中使用系统托盘控件的Windows服务的最佳方法是什么?任何用户登录都可以使用?

更新:感谢您的评论到目前为止,伙计们。我同意使用IPC更好,我知道混合Windows服务和用户界面是不好的。即便如此,我想知道如何做到这一点。

8 个答案:

答案 0 :(得分:18)

使用您选择的技术进行通信的两个独立流程。使用UI的服务是糟糕的主意。不要走这条路 - 你会后悔的。

我通过简单的套接字连接获得了很好的服务通信效果 - 很好地记录您的服务协议,尽可能保持简单,并且比您想象的要容易。

答案 1 :(得分:1)

在实践中,您不应将服务与管理UI结合使用。

答案 2 :(得分:1)

我同意格雷格的观点。也许您可以检查一个不同的IPC机制。也许使用套接字和您自己的协议。或者,如果您的服务控制应用程序只能控制本地计算机上的服务,则可以使用命名管道(甚至更快)。

答案 3 :(得分:1)

这是一种混合服务和表单的方式

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

答案 4 :(得分:1)

我想出了如何从this article执行此操作(单击“方法”表中的“更改”链接)。

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

答案 5 :(得分:1)

我通过几个步骤获得解决方案,这是计划

  1. 我们不打算用Windows窗体创建服务项目,而是创建一个包含Windows服务项目,Windows窗体项目和安装项目的visual studio解决方案。

  2. 我们的想法是拥有一个数据库或文件或任何您喜欢存储数据的内容,您可以在其中存储Windows服务将始终用于运行的参数。因此,您的Windows服务和Windows窗体应用程序应该能够修改和检索数据。

  3. 在Windows应用程序的主窗体上拖放NotifyIcon在窗体上,在属性选项卡中,浏览并选择.ico图像(您可以在visual studio中创建一个但是这是另一个主题,你可以get google或者联系我)当你运行应用程序并且主表单处于活动状态或显示时,它将显示在系统托盘中,试一试,运行应用程序。

  4. 在解决方案的安装项目中将它们都添加为输出。要将项目添加到安装项目,它们必须位于同一解决方案中。右键单击解决方案资源管理器中的安装项目,突出显示添加,然后选择项目输出,添加Windows服务和Windows窗体输出,您将在安装项目下的解决方案资源管理器中看到它们。

  5. 添加一个Windows服务比这更进一步,但这也是google的另一个话题

  6. 创建Windows应用程序的快捷方式并将其添加到启动文件夹也是google的另一个主题或与我联系。

    注意编程表单时关闭按钮不显示且表单变为Me.visible = false并双击系统托盘中的图标是设置me.visible = true.that的唯一方法在计算机启动的任何时候,你的Windows窗体应用程序也会启动,并且可见会立即设置为false,但由于它有一个带有图标图像的notifyicon,它将显示在系统托盘中并双击它使表单可见以编辑您为服务存储的设置,该服务也会自动启动,因为您可以在设置项目中设置服务时进行设置。 我的邮件是iamjavademon@gmail.com使用屏幕截图更好地说明并完整解释

答案 6 :(得分:0)

非常简单 - 您需要创建一个线程来执行应用程序事件。 像这样(带有CLR的C ++源代码,但你可以在C#中做到这一点):

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

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

在主

中创建线程
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;
}

答案 7 :(得分:0)

互动服务的主要问题是:

  • 安全性 - 其他进程可以通过其消息泵向其发送消息,从而获得对SYSTEM / LOCAL进程的访问权。

  • 不完整性 - 交互式服务从不会看到shell消息,因此无法与通知区域图标进行交互。

我们经常使用TCP和UDP连接将信息从服务传递给其他exes,在某些情况下,还传递给MSMQ。