我正在开发一个将在 Linux、Mac 和 Windows 上运行的 Mono 应用程序,并且需要应用程序(在单个操作系统上)能够相互发送简单的字符串消息。
具体来说,我想要一个单实例应用程序。如果尝试启动第二个实例,它将向已运行的单个实例发送消息。
DBus 已经退出,因为我不想让它成为一个额外的要求。 套接字通信似乎很难,因为 Windows 似乎不允许连接权限。 Mono 似乎不支持内存映射文件。 Mono 似乎不支持命名管道。 Mono 上似乎不支持 IPC。
那么,是否有一种简单的方法可以将单台计算机上的字符串消息发送到在每个操作系统上运行的服务器应用程序,而不需要权限或额外的依赖项?
在我的 ubuntu(10.10 单声道版本:2.6.7)上,我尝试使用 WCF 与 BasicHttpBinding、NetTcpBinding 和 NetNamedPipeBinding 进行进程间通信。前 2 个工作正常,对于 NetNamedPipeBinding 我收到错误:
通道类型 IDuplexSessionChannel 是 不支持
调用 ChannelFactory.CreateChannel() 方法时。
我还尝试过将 Remoting(这是自 WCF 出现以来的一项遗留技术)与 IpcChannel 结合使用;来自此msdn页面的示例在我的机器上启动并运行没有问题。
我想您在 Windows 上使用 WCF 或远程处理也不会有问题,但不确定 Mac 是否如此,因为没有任何可用的工具可供测试。如果您需要任何代码示例,请告诉我。
希望这有帮助,问候
我在 mono-dev 邮件列表上写了这篇文章。考虑了几种通用的进程间消息传递系统,包括 DBus、System.Threading.Mutex 类、WCF、Remoting、命名管道...结论基本上是mono 不支持 Mutex 类(适用于线程间) ,不适用于进程间)并且没有任何平台无关的可用。
我只能想象三种可能的解决方案。都有其缺点。也许有更好的解决方案可用,或者可能只是针对特定目的的更好的解决方案,或者也许存在一些跨平台的第三方库,您可以将其包含在您的应用程序中(我不知道。)但这些是我最好的解决方案到目前为止已经找到了:
出于您需要 IPC 的简单原因,我会寻找另一种解决方案。
此代码已确认可在 Linux 和 Windows 上运行。应该也可以在 Mac 上运行:
public static IList Processes()
{
IList<Process> processes = new List<Process>();
foreach (System.Diagnostics.Process process in System.Diagnostics.Process.GetProcesses())
{
Process p = new Process();
p.Pid = process.Id;
p.Name = process.ProcessName;
processes.Add(p);
}
return processes;
}
只需遍历列表并查找您自己的 ProcessName。
要将消息发送到您的应用程序,只需使用
MyProcess.StandardInput
写入应用程序标准输入。不过,这仅在假设您的应用程序是 GUI 应用程序的情况下才有效。
如果您遇到问题,那么您可以使用专门的“锁定”文件。使用 FileSystemWatcher 类,您可以检查它何时发生变化。这样,第二个实例可以在文件中写入一条消息,然后第一个实例注意到它发生了更改,并且可以读取文件的内容以获取消息。
这个答案并不适用于所有平台
用两种技术解决了我的问题:命名互斥体(以便应用程序可以由不同用户在同一台计算机上运行)和消息文件上的观察程序。该文件被打开并写入以进行通信。这是一个用 IronPython 2.6 编写的基本解决方案:
(mutex, locked) = System.Threading.Mutex(True, "MyApp/%s" % System.Environment.UserName, None)
if locked:
watcher = System.IO.FileSystemWatcher()
watcher.Path = path_to_user_dir
watcher.Filter = "messages"
watcher.NotifyFilter = System.IO.NotifyFilters.LastWrite
watcher.Changed += handleMessages
watcher.EnableRaisingEvents = True
else:
messages = os.path.join(path_to_user_dir, "messages")
fp = file(messages, "a")
fp.write(command)
fp.close()
sys.exit(0)