WPF本身并没有内置的单体模式支持(以后的版本会支持),而WindowsFormsApplicationBase类中有对单体模式的支持(全名是Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase),所以我们用WindowsFormsApplicationBase做一个wrapper就可以实现单体模式了。 

实现单体有三个知识点需要了解:

(*) The IsSingleInstance property enables a single-instance application. You set this property
to true in the constructor.
(*) The OnStartup() method is triggered when the application starts. You override this
method and create the WPF application object at this point.
(*) The OnStartupNextInstance() method is triggered when another instance of the application
starts up.

另外在实现的时候需要注意:

(*) 需要添加Microsoft.VisualBasic.dll的程序集引用

(*) the application needs to start with a traditional Main() method, rather than an App.xaml file.

代码实现

添加一个新的文件,例如名叫Startup.cs,在里面添加如下代码:

  1. namespace 你的命名空间 
  2.     public class Startup 
  3.     { 
  4.         [STAThread] 
  5.         public static void Main(string[] args) 
  6.         { 
  7.             SingleInstanceApplicationWrapper wrapper = new SingleInstanceApplicationWrapper(); 
  8.             wrapper.Run(args); 
  9.         } 
  10.     }  
  11.  
  12.     public class SingleInstanceApplicationWrapper : 
  13.         Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase 
  14.     { 
  15.         private App app; // 这才是真正的WPF Application  
  16.  
  17.         public SingleInstanceApplicationWrapper() 
  18.         { 
  19.             this.IsSingleInstance = true
  20.         }  
  21.  
  22.         // 第一次打开调这个方法 
  23.         protected override bool OnStartup( 
  24.             Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e) 
  25.         { 
  26.             app = new App(); 
  27.             app.Run();  
  28.  
  29.             return false
  30.         }  
  31.  
  32.         // 再次打开调这个方法 
  33.         protected override void OnStartupNextInstance( 
  34.             Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs e) 
  35.         { 
  36.             // 当用户试图再次打开这个程序的时候 
  37.             MessageBox.Show("您正在运行该程序"); 
  38.         } 
  39.     }  
  40.  
  41.     /// <summary> 
  42.     /// Interaction logic for App.xaml 
  43.     /// </summary> 
  44.     public partial class App : Application 
  45.     { 
  46.     } 

注意:

你刚开始建的项目类型可能是WPF,在项目的属性里,application标签下有个Startup Object,一开始默认应该是“你的namespace.App”,除此之外就只有Not Set了,没别的可选。是因为Main函数才是程序的入口,VS会根据Main函数去搜寻哪些可以作为Startup Object。但我们查看App这个类的代码会发现,默认情况下里面并没有Main函数,这是怎么回事呢?原来VS在编译时会结合xaml自动把代码补充完整。xaml里面的x:Class="你的namespace.App”,其中"你的namespace.App”会作为可选的Startup Object出现。
当在别的类里面新加入了Main函数,就会把这个类也列在Startup Object的可选列表中(有时候可能要重启VS才能在Startup Object里看到新的项)。 针对上面的例子(文件名是Startup.cs)则把“命名空间.Startup”作为Startup Object.

 

总结

以上实现的是真正的single instance,而不是仅仅通过查找有没有相同的进程名来查看程序是否已经启动。用查看相同进程名的方法实现single instance很不可靠。设想:如果有一个恶意程序,每秒查看一下所有的进程,看其中是否有a.exe(假如这恰好是你的程序名)如果没有,则启动一个a.exe,这个a.exe哪怕什么都不干,就为了在哪里占用这个进程名。那么你如果用查看相同进程名来实现single instance的话,除非在一秒钟之内杀死a.exe进程并启动你自己的a.exe,否则可能永远都启动不了你自己的a.exe。当然了,如果这个恶意程序执行的是:定期查看有没有这个进程,如果有则立即杀死,那就更麻烦了。

转自博客园:http://www.cnblogs.com/dc10101/archive/2009/11/24/1609146.html#top