在c# 4.0 Winform中,一个程序(如MS Word)只打开一个文件一次
本文关键字:一个 Word 文件 一次 MS Winform 程序 | 更新日期: 2023-09-27 17:50:07
我正在开发一个桌面应用程序(c# 4.0 Winforms),其中一个要求是程序可以打开多次。但是,我不希望用户能够多次打开给定的文档(可能会发生不好的事情)。
基本上我希望它的功能类似于MS Word(至少是新版本),如果你试图打开一个已经打开的文档,它会把你带到已经打开该文档的程序实例。
我大部分时间都在做web开发,所以可能有一些简单的解决方案,我只是不知道。
所以我真的有两种不同的需求。
1)避免文件被多次打开2)如果他们试图再次打开它,将实例带到前台。
我能想到几个方法来处理#1,但我很好奇其他人是如何解决这个问题的。
我真的不知道从哪里开始尝试让#2工作,没有一些主表单/过程保持开放并创建子程序。IE创建了另一个窗体,它实际控制当前程序的主窗体的打开和关闭,因此它更像是一个"标签"体验,而不是一个实际的多窗口体验。更像是老式的MDI(仍然会留下第一个问题)。
这里的任何帮助(网站阅读,名称空间查看等…)将非常感谢。
Edit -我看到这已经被标记为副本,并且"副本"在页面的顶部。我的要求之一是该程序必须能够多次开放。你们看了那篇文章吗?还有人可以进来投票重新讨论这个问题吗?
进一步编辑-我采用互斥锁的想法,以防止程序多次打开同一文档。我从来没有找到一种简单的方法来找出哪个程序实例打开了文档并将其带到前面,所以我现在放弃了,只是弹出一个消息框告诉他们它已经打开了。命名管道似乎有点过度,因为它不是我想要做的,并且会涉及很多开销(WCF不是世界上最简单的事情),所以任何进一步的帮助将是感激的。
您正在询问互斥锁。在Windows中,你可以创建一个互斥锁(互斥标志),这样即使进程的第二个实例打开,它也会尝试创建互斥锁,然后失败。互斥锁是os范围内的全局变量(某种程度上),用于IPC/协调。
另一种方法是这样-创建一个带有类名的窗口(类在windows API中,而不是在c#或c++中),其中嵌入了文档名,并使用FindWindow()函数首先查看这样的窗口是否已经打开。然后你可以SendMessage(HWND)发送该窗口的消息,把它带到前面,所以如果用户点击资源管理器"myfile.doc",它已经打开-你只是把它带到前面。要看的api(来自我的大脑ram,我是如何记住这些东西的?):
CreateMutex() / OpenMutex()
FindWindow() / CreateWindow()
SendMessage() / PostMessage()
ShowWindow()/ SetWindowPosition()/BringWinToTop()
我怀疑有几十种方法可以做到这一点,但这里是我的方法:
只有一个应用程序实例,并在应用程序内的新窗口中打开每个请求的文档。
这将需要一些协调,因为打开的后续文档将导致创建一个新实例,但是您可以设置一个进程间通信机制(例如命名管道),应用程序的第一个实例创建该机制,随后的实例检查该机制。
如果它们发现IPC存在,它们将请求的文件名传递给第一个应用实例(它打开指定的文件),然后终止。
这是一篇来自Microsoft的关于命名管道用法的好文章:如何使用命名管道进行网络进程间通信