我编写了一个C#windows服务,可以将消息写入自定义EventLog或任意数量的文件。这些消息都标有一些优先级(例如,只有ERROR和WARNING存储在EventLog中,但如果需要,可以将更多内容存储到文件中)。
我现在要做的是创建一个可以侦听这些消息并实时显示的GUI。允许用户观看当前消息(无论其所需的优先级),而无需将所有内容存储到文件中。我认为这是一个单独的程序,在服务中有某种形式的钩子,但我不确定从哪里开始。
这是我的第一个真正的Windows服务,所以我似乎缺少一些关键字,以了解如何执行此操作...是否有任何代码示例,教程,参考等,如何做这样的事情?< / p>
更新
很多有用的答案,我喜欢它,有很多方法可以解决问题!我想我将实现一个基于WCF的自托管解决方案。我仍然非常关注细节,因为我正在尝试了解WCF(我相信它对我在其他项目中非常有用)...但到目前为止,我已经找到了视频here作为介绍方法,是最有帮助的。
答案 0 :(得分:8)
您可以做的是让Windows服务注册一个事件(您可以通过使用Windows Communication Foundation来完成此操作)。当您的错误出现时,它会触发该事件,并且会通知您的winforms应用程序。它被称为双工合同:
http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/0eb69998-0388-4731-913e-fb205528d374/
http://msdn.microsoft.com/en-us/library/ms731184.aspx
实际上真的很酷的是你可以通过这种方式监听多个应用程序。因此,您可以在屏幕上显示它,并让其他应用程序记录它,而不需要两个外部应用程序了解彼此。
答案 1 :(得分:3)
我知道这已经提到了,但是使用Windows Communication Foundation(WCF)。具体而言,请使用Publish-Subscribe Framework的作者Juval Lowy开发的Programming WCF Services。详细信息在this excellent MSDN article中介绍,源代码可在Lowy's website免费获取。
这个框架的巧妙之处在于它将发布者(例如,您的Windows服务)与任何订阅者(例如您的GUI)分离。发布者“发布”Pub / Sub服务感兴趣的事件,该事件始终可用。从发布者的角度来看,是否有任何订阅者并不重要。发布/订阅服务负责将事件路由到任何和所有注册订阅者。通过这种方式,您的Windows服务会在事件发生时发布,您的GUI将在加载/退出时订阅/取消订阅发布/订阅服务,并且发布/订阅服务将在发生事件时通知您的GUI。
我在我的项目中使用过此设置,效果非常好。
答案 2 :(得分:2)
我实际上使用了BitFactory Logger,它有一个可用于此目的的套接字记录器。
答案 3 :(得分:2)
您所描述的是进程间通信,这可能会变得混乱。
最简单,最优雅,但可能是最不活跃的,是将服务写入条目作为小文本文件(或附加到日志),并让您的GUI使用FileSystemWatcher来检测新文件或更新日志文件,并阅读文件。您必须确保该服务打开文件以“共享”方式附加,允许在写入时进行只读访问。否则,您将阻止一个进程或另一个进程,可能导致丢失的消息。
流程可以通过一些内置管道进行通信。如果您的服务将消息写入其StandardOutput管道,则GUI可以远程附加侦听器并在写入消息时接收事件。这可能是最优雅的非文件方式来做你想要的。研究Process类,尤其是OutputDataReceived事件。您必须使用GetProcess()通过一些唯一标识信息从GUI查找过程。
答案 4 :(得分:0)
您需要寻找“同步”和“进程间通信”。在您的情况下,服务将使用全局事件或信号量来指示数据的存在,GUI进程将检查事件/信号量状态并从事件日志或文件中读取更新。
存在更复杂的情景,但以上是一个很好的起点。
答案 5 :(得分:0)
观察者模式!
也许您可以与服务挂钩的所有可观察模型的代表?
答案 6 :(得分:0)
通过IPC渠道进行.NET远程处理。
答案 7 :(得分:0)
我发现与系统托盘应用程序的命名管道通信是显示Windows服务通知的最简单方法。这是因为在Windows 10中,服务以与登录用户不同的权限运行,因此通知应用程序需要对该服务执行IPC。
在这里您可以将其放入服务器:
using System;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleServerApp
{
class Program
{
static void Main(string[] args)
{
StartServer();
Task.Delay(1000).Wait();
}
static void StartServer()
{
Task.Factory.StartNew(() =>
{
var server = new NamedPipeServerStream("PipesOfPiece");
server.WaitForConnection();
StreamReader reader = new StreamReader(server);
StreamWriter writer = new StreamWriter(server);
while (true)
{
var line = reader.ReadLine();
writer.WriteLine(String.Join("", line.Reverse()));
writer.Flush();
}
});
}
}
}
然后将其放入您的客户端:
using System;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleClientApp
{
class Program
{
static void Main(string[] args)
{
//Client
var client = new NamedPipeClientStream("PipesOfPiece");
client.Connect();
StreamReader reader = new StreamReader(client);
StreamWriter writer = new StreamWriter(client);
while (true)
{
string input = Console.ReadLine();
if (String.IsNullOrEmpty(input)) break;
writer.WriteLine(input);
writer.Flush();
Console.WriteLine(reader.ReadLine());
}
}
}
}
然后将您的ConsoleServerApp更改为Winforms应用程序,以便在Windows服务向其发送消息时可以显示通知:
public Form1()
{
InitializeComponent();
StartServer();
Task.Delay(_threadJoinTimeout).Wait();
}
public void DisplayMessage()
{
this.notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;
this.notifyIcon1.BalloonTipText = "Welcomd!";
this.notifyIcon1.BalloonTipTitle = "Title";
this.notifyIcon1.ShowBalloonTip(2000);
}
void StartServer()
{
Task.Factory.StartNew(() =>
{
var server = new NamedPipeServerStream("PipesOfPiece");
server.WaitForConnection();
StreamReader reader = new StreamReader(server);
while (true)
{
var line = reader.ReadLine();
DisplayMessage();
}
});
}
然后将ConsoleClientApp放入Windows服务。
有关管道的详细信息,请参见Example of Named Pipes 有关系统任务栏应用程序,请参见http://www.tutorialspanel.com/create-system-tray-icon-windows-forms-application-using-c-vb-net/#:~:text=Below%20is%20an%20example%20of%20how%20to%20create,Step%203.%20Add%20an%20icon%20to%20the%20NotifyIcon 以下是使用TopShelf NuGet软件包的提示,该软件包使您可以将Windows服务作为控制台应用程序进行调试:https://www.codeproject.com/Articles/881511/SignalR-with-Self-hosted-Windows-Service