C# dot net core 单实例应用程序将参数传递给第一个实例
Posted
技术标签:
【中文标题】C# dot net core 单实例应用程序将参数传递给第一个实例【英文标题】:C# dot net core single instance app passing parameters to first instance 【发布时间】:2020-04-29 13:10:24 【问题描述】:最近我决定将我用 C# 编写并以 .NET Framework 4.5 为目标的 WPF Windows 桌面应用程序之一迁移到最新的 .NET Core 3.1。一切都很好,直到我不得不添加对单实例应用程序的支持,同时能够将任何参数从第二个实例传递到第一个正在运行的实例。我之前对单实例应用程序的 WPF 实现使用的是 System.Runtime.Remoting,这在 .NET Core 中不可用。因此我不得不做一些新的事情。下面是我想出的实现。它工作得很好,但我觉得它可以改进。请随时讨论和改进建议的解决方案。
我创建了一个 SingleInstanceService,它使用信号量来指示它是否是第一个实例。如果它是第一个实例,我创建一个 TcpListener 并无限期地等待从第二个实例传递的任何参数。如果启动了第二个实例,那么我将第二个实例的参数发送给第一个监听实例,然后退出第二个实例。
internal class SingleInstanceService
internal Action<string[]> OnArgumentsReceived;
internal bool IsFirstInstance()
if (Semaphore.TryOpenExisting(semaphoreName, out semaphore))
Task.Run(() => SendArguments(); Environment.Exit(0); );
return false;
else
semaphore = new Semaphore(0, 1, semaphoreName);
Task.Run(() => ListenForArguments());
return true;
private void ListenForArguments()
TcpListener tcpListener = new TcpListener(IPAddress.Parse(localHost), localPort);
try
tcpListener.Start();
while (true)
TcpClient client = tcpListener.AcceptTcpClient();
Task.Run(() => ReceivedMessage(client));
catch (SocketException ex)
Log.Error(ex);
tcpListener.Stop();
private void ReceivedMessage(TcpClient tcpClient)
try
using (NetworkStream networkStream = tcpClient?.GetStream())
string data = null;
byte[] bytes = new byte[256];
int bytesCount;
while ((bytesCount = networkStream.Read(bytes, 0, bytes.Length)) != 0)
data += Encoding.UTF8.GetString(bytes, 0, bytesCount);
OnArgumentsReceived(data.Split(' '));
catch (Exception ex)
Log.Error(ex);
private void SendArguments()
try
using (TcpClient tcpClient = new TcpClient(localHost, localPort))
using (NetworkStream networkStream = tcpClient.GetStream())
byte[] data = Encoding.UTF8.GetBytes(string.Join(" ", Environment.GetCommandLineArgs()));
networkStream.Write(data, 0, data.Length);
catch (Exception ex)
Log.Error(ex);
private Semaphore semaphore;
private string semaphoreName = $"Global\\Environment.MachineName-myAppNameAssembly.GetExecutingAssembly().GetName().Version-sidProcess.GetCurrentProcess().SessionId";
private string localHost = "127.0.0.1";
private int localPort = 19191;
然后在 App.xaml.cs 中,我有以下代码:
protected override void OnStartup(StartupEventArgs e)
SingleInstanceService singleInstanceService = new SingleInstanceService();
if (singleInstanceService.IsFirstInstance())
singleInstanceService.OnArgumentsReceived += OnArgumentsReceived;
// Some other calls
base.OnStartup(e);
private void OnArgumentsReceived(string[] args)
// ProcessCommandLineArgs(args);
请随意讨论这个主题,我认为这是 Windows 桌面开发人员中非常常见的用例。谢谢。
【问题讨论】:
您可以尝试使用Mutex
,它在.NET core 中可用。您想将哪些参数传递给第二个实例?
我选择了信号量,因为它是一种信号机制,而不是互斥量,它是一种锁定机制。它可以通过两种方式完成,但我更喜欢我发现更容易用于当前目的的信号量。要求是将命令行参数从第二个实例发送到第一个实例。
另一种选择是为此使用 p/invoke 函数,例如 thread
通过迁移到 .NET Core,我建议不要那么简单地使用 p/invoke。
我投票结束这个问题,因为它属于 Code Review Stack Exchange。
【参考方案1】:
使用依赖注入。您将需要定义一个接口,然后实现该接口。在启动代码中,您需要将接口及其实现添加为单例服务。
在您的实现构造函数中,您可以放置您只想运行一次的代码。这将持续对象的生命周期。
还有其他类型的注入,瞬态注入和作用域注入,但对于您的用例,您可能只需要单例。
Program.cs
using System;
using Microsoft.Extensions.DependencyInjection;
namespace example
class Program
static void Main(string[] args)
// create service collection
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
var serviceProvider = serviceCollection.BuildServiceProvider();
serviceProvider.GetService<Startup>().Run();
private static void ConfigureServices(IServiceCollection serviceCollection)
// add services
serviceCollection.AddTransient<IMyService, MyService>();
serviceCollection.AddTransient<Startup>();
Startup.cs
namespace example
public class Startup
private readonly IMyService _myService;
public Startup(IMyService myService)
_myService = myService;
public void Run()
_myService.MyMethod();
互动
namespace example
public interface IMyService
void MyMethod();
服务的实现
namespace example
public class MyService : IMyService
public MyService()
// on signleton service this only gets invoked once
public void MyMethod()
// your imolmentation here
一些在线参考: https://dzone.com/articles/dependency-injection-in-net-core-console-applicati
https://code-maze.com/dependency-inversion-principle/
【讨论】:
很抱歉,但我看不出这与所讨论的主题有什么关系:单实例应用程序并将参数传递给第一个正在运行的实例。以上是关于C# dot net core 单实例应用程序将参数传递给第一个实例的主要内容,如果未能解决你的问题,请参考以下文章
C# Httpclient Asp.net Core 2.0 on Kestrel Waiting, Lock Contention, high CPU
Omnisharp 无法正确处理 vscode 中的默认 dot net core 3 应用程序
Dot Net Core dll 作为带有事件的 COM dll
无法使用 Chrome 登录 Dot Net Core 3 ASP.Net App,但可以使用 Firefox