我正在尝试使用 WPF 创建一个服务,该服务将与 WPF 通信,告诉 WPF 显示图标托盘和气球提示。
我设计了以下代码:
App.xaml.cs
namespace Service_UI
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public LogWriter logwriter = new LogWriter();
System.Windows.Forms.NotifyIcon nIcon = new System.Windows.Forms.NotifyIcon();
Server IPCS = new Server();
protected override void OnStartup(StartupEventArgs e)
{
nIcon.Icon = new Icon($@"{AppDomain.CurrentDomain.BaseDirectory}/app.ico");
nIcon.Text = "Service";
Task.Run(async () => await ServerMessages());
MainWindow mainWindow = new MainWindow();
mainWindow.Hide(); // Start hidden
}
private async Task ServerMessages()
{
await IPCS.Connect();
while (true)
{
string serverMessage = await IPCS.ReadMessages();
if (serverMessage == "Service_Start")
{
Dispatcher.Invoke(() =>
{
nIcon.Visible = true;
nIcon.ShowBalloonTip(5000, "S3ID NetTime Sync", "UI will open up Shortly", System.Windows.Forms.ToolTipIcon.Info);
nIcon.ContextMenuStrip = new System.Windows.Forms.ContextMenuStrip();
nIcon.ContextMenuStrip.Items.Add("Settings", Image.FromFile(@"Resources\cogs_icon.ico"), OnSettingsClicked);
nIcon.ContextMenuStrip.Items.Add("Exit", Image.FromFile(@"Resources\exit_icon.ico"), OnExitClicked);
// This section is about selecting the View MainWindow and running the application:
MainWindow = new MainWindow();
MainWindow.Show();
logwriter.LogWrite("Application is running now", MessageLevels.Info);
//base.OnStartup(e);
});
}
else if (serverMessage == "Service_Stop")
{
Dispatcher.Invoke(() =>
{
nIcon.Dispose();
//base.OnExit(e);
IPCS.Dispose();
//base.OnExit(e);
MainWindow.Hide();
});
}
}
}
private void OnExitClicked(object sender, EventArgs e)
{
nIcon.Dispose();
MainWindow.Hide();
logwriter.LogWrite("Application has been minimised", MessageLevels.Info);
}
private void OnSettingsClicked(object sender, EventArgs e)
{
MainWindow.Show();
logwriter.LogWrite("Application is displayed", MessageLevels.Info);
}
}
}
服务文件
namespace MainService
{
public partial class MainService : ServiceBase
{
Timer tmr = new Timer();
LogWriter logWriter = new LogWriter();
Client IPCC = new Client();
public MainService()
{
InitializeComponent();
this.ServiceName = "MainService";
}
protected override void OnStart(string[] args)
{
logWriter.LogWrite($"Service initiated on {DateTime.Now}", MessageLevels.Info);
tmr.Elapsed += new ElapsedEventHandler(OnElapsedTime);
tmr.Interval = 5000;
tmr.Enabled = true;
logWriter.LogWrite($"Service will initiate the WPF on {DateTime.Now}", MessageLevels.Info);
Process.Start(@"Service UI.exe");
Task.Run(async () => await IPCC.Connect("Service_Start"));
}
protected override void OnStop()
{
logWriter.LogWrite($"Service stopped running on {DateTime.Now}", MessageLevels.Info);
Task.Run(async () => await IPCC.Connect("Service_Stop"));
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
logWriter.LogWrite($"Service started running on {DateTime.Now}", MessageLevels.Info);
}
}
}
服务器.cs
namespace InterProcessCommunication
{
public class Server : IDisposable
{
public LogWriter Logwriter = new LogWriter();
public bool ServerConnectionSuccessfull;
public NamedPipeServerStream ServerPipe;
private bool disposed = false;
public Server() { }
public async Task Connect()
{
try
{
while (true)
{
ServerPipe = new NamedPipeServerStream("Pipe", PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
Logwriter.LogWrite("Waiting for client connection...", MessageLevels.Info);
await ServerPipe.WaitForConnectionAsync();
ServerConnectionSuccessfull = true;
Logwriter.LogWrite("Client connected.", MessageLevels.Info);
// Read the messages from the client
string message = await ReadMessages();
Logwriter.LogWrite($"Received from client: {message}", MessageLevels.Info);
// Close the connection
ServerPipe.Disconnect();
ServerPipe.Dispose();
}
}
catch (Exception ex)
{
Logwriter.LogWrite($"Exception: {ex.Message}", MessageLevels.Error);
Logwriter.LogWrite($"Stack Trace: {ex.StackTrace}", MessageLevels.Error);
}
}
public void Dispose()
{
if (!disposed)
{
try
{
ServerPipe?.Dispose();
}
catch (Exception ex)
{
Logwriter.LogWrite($"Exception during Dispose: {ex.Message}", MessageLevels.Error);
Logwriter.LogWrite($"Stack Trace: {ex.StackTrace}", MessageLevels.Error);
}
finally
{
disposed = true;
}
}
}
public async Task<string> ReadMessages()
{
try
{
if (ServerPipe == null || !ServerPipe.IsConnected)
{
Logwriter.LogWrite("Pipe server is not initialized.", MessageLevels.Error);
return null;
}
using var sr = new StreamReader(ServerPipe);
string message = await sr.ReadToEndAsync();
return message;
}
catch (IOException ioEx)
{
Logwriter.LogWrite($"IOException: {ioEx.Message}", MessageLevels.Error);
Logwriter.LogWrite($"Stack Trace: {ioEx.StackTrace}", MessageLevels.Error);
return null;
}
catch (Exception ex)
{
Logwriter.LogWrite($"Exception: {ex.Message}", MessageLevels.Error);
Logwriter.LogWrite($"Stack Trace: {ex.StackTrace}", MessageLevels.Error);
return null;
}
}
}
}
客户端.cs
namespace InterProcessCommunication
{
public class Client
{
public LogWriter Logwriter = new LogWriter();
public bool ClientConnectionSuccessfull;
public Client() { }
public async Task Connect(string message)
{
while (!ClientConnectionSuccessfull)
{
try
{
using (var client = new NamedPipeClientStream(".", "Pipe", PipeDirection.Out, PipeOptions.None))
{
Logwriter.LogWrite("Connecting to server...", MessageLevels.Info);
await client.ConnectAsync();
Logwriter.LogWrite("Connected to server.", MessageLevels.Info);
ClientConnectionSuccessfull = true;
// write data through the pipe
await SendMessages(client, message);
}
}
catch (Exception ex)
{
Logwriter.LogWrite($"Error Message: {ex}", MessageLevels.Error);
await Task.Delay(5000); // Retry after 5 seconds if the connection fails
ClientConnectionSuccessfull = false;
}
}
}
public async Task SendMessages(NamedPipeClientStream target,string message)
{
try
{
using var sw = new StreamWriter(target);
sw.AutoFlush = true;
//sw.WriteLine(message);
await sw.WriteLineAsync(message);
}
catch (Exception ex)
{
Logwriter.LogWrite($"Exception: {ex.Message}", MessageLevels.Error);
Logwriter.LogWrite($"Stack Trace: {ex.StackTrace}", MessageLevels.Error);
}
}
}
}
对于我的情况,我想要做的是建立一个开放的连接,客户端在不同时间(基于条件语句)向服务器发送消息,服务器告诉 WPF 要显示什么气球提示以及要显示什么图标(例如带有信息气球提示的启动服务显示图标;当服务关闭时,图标将带有错误气球提示等)。
我似乎无法让它发挥作用。我的代码可能存在什么问题?
我遇到的问题示例:
Thursday, 2024-07-25 13:35:55 LevelI: Service initiated on 25/07/2024 13:35:55
Thursday, 2024-07-25 13:35:55 LevelI: Service will initiate the WPF on 25/07/2024 13:35:55
Thursday, 2024-07-25 13:35:55 LevelI: Connecting to server...
Thursday, 2024-07-25 13:35:55 LevelI: Waiting for client connection...
Thursday, 2024-07-25 13:35:55 LevelI: Connected to server.
Thursday, 2024-07-25 13:35:55 LevelI: Client connected.
Thursday, 2024-07-25 13:35:55 LevelI: Received from client: Service_Start
Thursday, 2024-07-25 13:35:55 LevelI: Waiting for client connection...
Thursday, 2024-07-25 13:36:00 LevelI: Service started running on 25/07/2024 13:36:00
Thursday, 2024-07-25 13:36:05 LevelI: Service started running on 25/07/2024 13:36:05
Thursday, 2024-07-25 13:36:10 LevelI: Service started running on 25/07/2024 13:36:10
Thursday, 2024-07-25 13:36:15 LevelI: Service started running on 25/07/2024 13:36:15
Thursday, 2024-07-25 13:36:20 LevelI: Service started running on 25/07/2024 13:36:20
Thursday, 2024-07-25 13:36:25 LevelI: Service started running on 25/07/2024 13:36:25
Thursday, 2024-07-25 13:36:30 LevelI: Service started running on 25/07/2024 13:36:30
Thursday, 2024-07-25 13:36:35 LevelI: Service started running on 25/07/2024 13:36:35
Thursday, 2024-07-25 13:36:40 LevelI: Service started running on 25/07/2024 13:36:40
Thursday, 2024-07-25 13:36:45 LevelI: Service started running on 25/07/2024 13:36:45