目录
介绍
概念化这个混乱
编码此混乱
- 下载SingletonIPC.zip-4.5 KB
有时,您可能会在某个应用程序中没有必要两次启动主应用程序,但是您可能希望通过传递其他命令行参数来再次运行该应用程序。这样,您可以运行该应用程序,它将打开您的程序,然后您可以再次运行该应用程序,并将其他命令行信息传递给已运行的应用程序。例如,当您想让现有应用程序从命令行打开新文件时,这很有用。因此它像这样处理:
C:\Foo> MyApp myfile1.txt
C:\Foo> MyApp myfile2.txt myfile3.txt
在这种情况下,MyApp仅在第一次启动实际的应用程序。第二次,它检测到它已经在运行,并简单地将传入的命令行发送到已经运行的应用程序进行处理。
为了提供此功能,我们对该应用程序有两个主要方面。
首先,该应用程序需要检测它是否已经在运行,并且根据它是否已经在运行,它将执行不同的操作。
其次,我们需要一种使两个进程进行通信的方法。在这种情况下,主应用程序将等待子序列启动产生的命令行数据。
第一个方面很容易。我们使用命名的互斥锁来防止主应用程序代码两次启动。该用户的所有正在运行的进程都可以看到已命名的互斥锁。
第二个方面要困难一点,但幸运是也不是很难。我们将使用.NET的命名管道功能来促进主应用程序(服务器)与后续启动(客户端)之间的通信。该用户的所有正在运行的进程也可以看到命名管道。
编码此混乱我们使用的代码在这里给出,几乎是完整的。我只是在这里取消了using指令,以节省一些空间。
class Program
{
static string _AppName= Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().GetName().Name);
static void Main(string[] args)
{
// we need to get our app name so that we can create unique names for our mutex and our pipe
var notAlreadyRunning = true;
// wrap the meat of the application code with a named mutex so it runs only once
using (var mutex = new Mutex(true, _AppName + "Singleton", out notAlreadyRunning))
{
if (notAlreadyRunning)
{
// do additional work here, startup stuff
Console.WriteLine("Running. Press any key to exit...");
// ...
// now process our initial main command line
_ProcessCommandLine(args);
// start the IPC sink.
var srv = new NamedPipeServerStream(_AppName+"IPC", PipeDirection.InOut,1,PipeTransmissionMode.Message,PipeOptions.Asynchronous);
// it's easier to use the AsyncCallback than it is to use Tasks here:
// this can't block, so some form of async is a must
srv.BeginWaitForConnection(new AsyncCallback(_ConnectionHandler), srv);
// block here until exit
Console.ReadKey();
// if this was a windows forms app you would put your "Applicantion.Run(new MyForm());" here
// finally, run any teardown code and exit
srv.Close();
}
else // another instance is running
{
// connect to the main app
var cli = new NamedPipeClientStream(".",_AppName + "IPC",PipeDirection.InOut);
cli.Connect();
var bf = new BinaryFormatter();
// serialize and send the command line
bf.Serialize(cli, args);
cli.Close();
// and exit
}
}
}
static void _ConnectionHandler(IAsyncResult result)
{
var srv = result.AsyncState as NamedPipeServerStream;
srv.EndWaitForConnection(result);
// we're connected, now deserialize the incoming command line
var bf = new BinaryFormatter();
var inargs = bf.Deserialize(srv) as string[];
// process incoming command line
_ProcessCommandLine(inargs);
srv.Close();
srv = new NamedPipeServerStream(_AppName + "IPC", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous);
srv.BeginWaitForConnection(new AsyncCallback(_ConnectionHandler), srv);
}
static void _ProcessCommandLine(string[] args)
{
// we received some command line
// arguments.
// do actual work here
Console.Write("Command line recieved: ");
for(var i = 0;i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?
立即登录/注册


微信扫码登录