|
|
1
467
这是一个非常好的 article 关于互斥解决方案。本文所描述的方法有两个优点。 首先,它不需要依赖Microsoft.VisualBasic程序集。如果我的项目已经依赖于这个组件,我可能会提倡使用公认的答案中所示的方法。但事实上,我不使用microsoft.visualBasic程序集,我也不想在我的项目中添加不必要的依赖项。 其次,本文展示了当用户试图启动另一个实例时,如何将应用程序的现有实例置于前台。这是一个非常好的触摸,这里描述的其他互斥解决方案没有解决。 更新截至2014年8月1日,我链接到上面的文章仍然是活跃的,但是博客已经有一段时间没有更新了。这让我担心,最终它可能会消失,随之而来的是所提倡的解决方案。我在为子孙后代复制这篇文章的内容。这些词只属于博客所有者 Sanity Free Coding .
|
|
|
2
96
您可以使用mutex类,但很快就会发现您需要实现代码来传递参数,这样您自己就可以了。嗯,当我阅读时,我在WinForms中编程时学会了一个技巧 Chris Sell's book . 这个技巧使用了框架中已经存在的逻辑。我不了解你,但是当我了解到我可以在框架中重用的东西时,这通常是我走的路线,而不是重新设计轮子。当然,除非它不能满足我的需要。 当我进入WPF时,我想出了一种方法来使用相同的代码,但是在一个WPF应用程序中。这个解决方案应该根据您的问题满足您的需求。 首先,我们需要创建我们的应用程序类。在这个类中,我们将重写onStartup事件并创建一个名为activate的方法,稍后将使用该方法。
第二,我们需要创建一个类来管理我们的实例。在此之前,我们实际上要重用Microsoft.VisualBasic程序集中的一些代码。因为在本例中,我使用的是C,所以我必须引用程序集。如果您使用的是vb.net,则无需执行任何操作。我们将使用的类是WindowsFormsApplicationBase,并从中继承实例管理器,然后利用属性和事件来处理单个实例。
基本上,我们使用vb位来检测单个实例并进行相应的处理。当加载第一个实例时,将激发OnStartup。再次运行应用程序时,将激发OnStartupNextInstance。如您所见,我可以通过事件参数得到命令行上传递的内容。我将值设置为实例字段。您可以在这里解析命令行,或者通过构造函数和对activate方法的调用将它传递给应用程序。 第三,是时候创建入口点了。我们将利用我们的单实例管理器,而不是像通常那样更新应用程序。
好吧,我希望您能够跟踪所有的事情,并且能够使用这个实现并使之成为您自己的实现。 |
|
|
3
77
从 here . 跨进程互斥体的一个常见用途是确保一次只能运行程序的实例。完成方法如下:
互斥体的一个好特性是,如果应用程序在没有首先调用release mutex的情况下终止,CLR将自动释放互斥体。 |
|
|
4
52
实际上,msdn有一个用于C和VB的示例应用程序来执行以下操作: http://msdn.microsoft.com/en-us/library/ms771662(v=VS.90).aspx
框架已经对此提供了支持——只是某个白痴将DLL命名为
提示:如果您按原样使用这种方法,并且已经有了一个包含资源等的app.xaml,那么您将希望 take a look at this too . |
|
|
5
21
此代码应转到主方法。看 here 有关WPF中主要方法的详细信息。
方法2
注: 以上方法假定您的进程/应用程序具有唯一的名称。因为它使用进程名来查找是否有任何现有的处理器。因此,如果您的应用程序有一个非常常见的名称(即:记事本),那么上述方法将不起作用。 |
|
|
6
16
好吧,我有一个一次性类,可以很容易地用于大多数用例: 这样使用:
这里是:
|
|
7
12
一个新的方法是使用mutex和ipc,并将任何命令行参数传递给正在运行的实例。 WPF Single Instance Application . |
|
8
9
代码 C# .NET Single Instance Application 这是对标记答案的参考,是一个很好的开始。 但是,我发现它不能很好地处理已经存在的实例打开模式对话框时的情况,无论该对话框是托管对话框(像其他窗体,如about框)还是非托管对话框(像OpenFileDialog,即使使用标准.NET类)。使用原始代码时,主窗体被激活,但模式窗体保持不活动状态,这看起来很奇怪,而且用户必须单击它才能继续使用该应用程序。 所以,我已经创建了一个单实例实用程序类来自动处理WinForms和WPF应用程序的所有这些问题。 WiFrices : 1)如下修改程序类:
2)这样修改主窗口类:
WPF: 1)像这样修改应用程序页面(并确保将其生成操作设置为页面,以便能够重新定义主方法):
2)这样修改主窗口类:
这是实用程序类:
|
|
|
9
9
下面是一个允许您拥有应用程序的单个实例的示例。当加载任何新实例时,它们将参数传递给正在运行的主实例。
|
|
|
10
8
只是一些想法: 在某些情况下,要求只有一个应用程序实例不是像您认为的那样“跛脚”。如果一个应用允许一个用户访问一个数据库的多个应用实例(你知道,所有更新用户机器上应用程序多个实例中打开的所有记录的操作,等等),那么数据库应用程序等的难度就大得多。 首先,对于“名称冲突”的事情,不要使用人可读的名称-使用一个guid,或者更好的是guid+人可读的名称。名称冲突的可能性刚刚从雷达上消失,而互斥体则不在乎。正如有人指出的那样,DoS攻击会很糟糕,但是如果恶意的人遇到了获取互斥体名称并将其合并到他们的应用程序中的麻烦,那么不管怎样,你基本上是一个目标,你必须做更多的工作来保护自己,而不仅仅是篡改互斥体名称。 此外,如果使用以下变量: 新的互斥体(true,“some guid plus name”,out aifirstinstance),您已经有了互斥体是否是第一个实例的指示器。 |
|
|
11
6
对于这样一个看似简单的问题,有这么多答案。只是稍微改变一下,这是我解决这个问题的方法。 创建互斥体可能很麻烦,因为jit-er只看到您在代码的一小部分中使用它,并希望将其标记为准备好进行垃圾收集。它非常想聪明,你认为你不会在这么长时间内使用这个互斥。实际上,只要您的应用程序正在运行,您就希望保持这个互斥体。告诉垃圾收集器不要使用mutex的最好方法是告诉它在不同代的车库收集之外保持它的活动状态。例子:
我从这一页中提出了这个想法: http://www.ai.uga.edu/~mc/SingleInstance.html |
|
12
6
|
|
13
6
下面的代码是我注册单个实例应用程序的wcf命名管道解决方案。这很好,因为当另一个实例尝试启动并接收另一个实例的命令行时,它还会引发一个事件。
它面向WPF,因为它使用
此代码需要引用
用途:
源代码:
|
|
14
5
您不应该使用命名的互斥体来实现单个实例应用程序(或者至少不用于生产代码)。恶意代码很容易做到( Denial of Service 你的屁股… |
|
|
15
4
这是我用的。它结合了进程枚举来执行切换和互斥,以防止“活动的点击器”:
|
|
|
16
4
我发现了更简单的解决方案,类似于DaleRagan的,但有点修改。它几乎可以满足您的所有需要,并且基于标准的Microsoft WindowsFormsApplicationBase类。 首先,创建singleInstanceController类,可以在使用Windows窗体的所有其他单实例应用程序中使用:
然后您可以在程序中使用它,如下所示:
程序和单实例控制器的网络解决方案都应参考Microsoft.VisualBasic。如果您只想在用户尝试重新启动正在运行的程序时将正在运行的应用程序作为普通窗口重新激活,则singleInstanceController中的第二个参数可以为空。在给定的示例中,窗口最大化。 |
|
17
4
看看下面的代码。这是一个伟大而简单的解决方案,可以防止一个WPF应用程序的多个实例。
|
|
|
18
2
但不使用互斥,简单回答:
把它放进
您可以添加
|
|
19
2
更新2017-01-25。 在尝试了几件事情之后,我决定使用visualbasic.dll,它更简单,工作更好(至少对我来说)。我让我以前的答案作为参考… 就像参考文献一样,这是我在不传递参数的情况下所做的(我找不到任何理由这样做…我指的是一个单独的应用程序,其参数可以从一个实例传递到另一个实例)。 如果需要文件关联,则应为每个文档安装一个应用程序(根据用户的标准期望)。如果必须将args传递给现有的应用程序,我想我将使用vb dll。 不传递args(只是单实例应用程序),我更喜欢不注册新的窗口消息,也不重写MattDavis解决方案中定义的消息循环。虽然添加一个VisualBasic DLL并不是什么大问题,但是我不希望只添加一个新的引用来执行单实例应用程序。此外,我更喜欢用main来声明一个新类,而不是从app.startup override调用shutdown,以确保尽快退出。 希望有人会喜欢它…或者会有点启发:—) 项目启动类应设置为“singleInstanceApp”。
WindowHelper:
|
|
|
20
1
使用互斥解决方案:
|
|
|
21
1
这是我使用的一个轻量级解决方案,它允许应用程序将已经存在的窗口带到前台,而无需使用自定义的Windows消息或盲目搜索进程名称。
编辑:您还可以静态地存储和初始化互斥体并创建新的互斥体,但完成后,您需要显式地释放/释放互斥体。就我个人而言,我更喜欢将互斥体保持在本地,因为即使应用程序关闭而没有到达主系统的末尾,互斥体也会自动被处理掉。 |
|
|
22
1
您也可以使用 CodeFluent Runtime 这是一套免费的工具。它提供了一个 SingleInstance 类来实现单个实例应用程序。 |
|
|
23
1
这是通过事件实现的相同的事情。
|
|
|
24
1
基于命名互斥体的方法不是跨平台的,因为命名互斥体在mono中不是全局的。基于进程枚举的方法没有任何同步,可能导致不正确的行为(例如,同时启动的多个进程可能都会根据时间自动终止)。在控制台应用程序中,基于窗口系统的方法是不可取的。这个基于Divin答案的解决方案解决了所有这些问题:
|
|
|
25
1
我找不到 短解 我希望有人会喜欢这个:
(顺便说一下,把代码放在 “程序CS” )
//可选代码。如果不希望有人运行,请使用不同名称的“.exe”:
|
|
|
26
0
我向NativeMethods类添加了一个sendmessage方法。 显然,如果应用程序没有显示在任务栏中,那么postmessage方法就可以工作,但是使用sendmessage方法可以解决这个问题。
|
|
|
27
0
通常,每当我们执行一个.exe时,每次它创建一个独立的Windows进程时,都有自己的地址空间、资源等。但我们不希望这样的标准,因为这样会阻止我们创建单个流程。可以使用C中的互斥体创建单实例应用程序,其中 is discussed in this article 此外,如果我们想让应用程序处于顶层,我们可以使用
|
|
28
0
通常,这是我用于单个实例的代码 Windows Forms 应用:
其中本机组件是:
|
|
|
29
0
以下是一个解决方案:
|
|
|
30
0
我就是这样处理这个问题的。请注意,调试代码仍在测试中。此代码在app.xaml.cs文件的onstartup中。(WPF)
这可能有一些我还没有发现的问题。如果我遇到任何问题,我会更新我的答案。 |
|
|
fiedel · 为什么互斥锁可以被两个线程锁定? 2 年前 |
|
|
da cheng · 在c++11中使用条件变量使程序陷入死锁 8 年前 |
|
|
Eunjeong Choi · 为什么此代码返回意外结果?(条件变量) 8 年前 |
|
|
Razonixx · 从线程内增加全局计数器变量,而不必等待每个线程 8 年前 |
|
|
Administrator · c#-等待完成2个线程中的1个 8 年前 |