6

我有 ac# 应用程序,它作为 Windows 服务运行,控制套接字连接和其他东西。此外,还有另一个 Windows 窗体应用程序来控制和配置此服务(带有启动、停止、显示配置参数的表单的系统托盘)。

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

这是问题所在:

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

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

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

4

8 回答 8

19

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

通过一个简单的套接字连接进行服务通信,我取得了非常好的结果 - 很好地记录您的服务协议,使其尽可能简单,这将比您想象的要容易。

于 2008-10-01T18:40:03.863 回答
1

在实践中,您不应该将您的服务与管理 UI 结合起来。

于 2008-10-01T18:41:24.063 回答
1

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

于 2008-10-01T18:41:37.840 回答
1

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

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

于 2009-07-23T12:51:50.433 回答
1

我从这篇文章中知道了如何做到这一点(单击方法表中的“更改”链接)。

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);
}
于 2009-11-24T15:02:14.007 回答
1

我有几个步骤的解决方案,这是计划

  1. 我们不会使用 Windows 窗体创建服务项目,而是创建一个包含 Windows 服务项目、Windows 窗体项目和设置项目的 Visual Studio 解决方案。

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

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

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

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

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

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

于 2010-03-18T21:19:44.320 回答
0

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

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

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

并在 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;
}
于 2008-10-21T12:49:43.307 回答
0

交互式服务的主要问题是:

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

  • 不完整 - 交互式服务永远不会看到 shell 消息,因此它不能与通知区域图标交互。

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

于 2009-01-08T03:02:22.833 回答