在C# .NET2.0实现单实例应用程序

【网通】点击此处下载源代码                     【电信、网通】点击此处下载源代码

【电信】点击此处下载演示程序                 【电信、网通】点击此处下载演示程序

点击查看原文地址

【下载说明】
1、单击上面这个地址,打开下载页面。
2、点普通下载--等待30秒--点“下载”按钮--保存

介绍

一个单实例应用程序就是仅让用户打开一个实例的程序。严格的说,第二个实例也已经启动了,但是当它探测到已经有一个实例存在时,就自动关闭了。

在Visual Studio 2005中,做一个单实例的应用程序是很容易的。在VB中,仅需要选中工程设置对话框中的一个Check Box选项,然后在合适的事件中处理就可以了。这些代码会在Microsoft.VisualBasic命名空间中完成,但是也能在一个C#应用程序中这么做。这篇文章将会告诉你怎么去做,同时也会告诉你怎么讲命令行的参数从第二个实例中传递到第一个实例中。

背景

即使在.NET出现之前,单实例应用程序就已经出现了,而且我们有很多种方法去实现它。关键的问题就是多个实例之间的通信。在.NET中,通常是通过远程操作来完成的。在.net 2.0以前,关于单实例应用程序最好的一个文章就是由Detlef Grohs所写的。如果你还在使用.net 1.1,或者对详细的过程感兴趣的话,不妨看看他所写的文章。

代码

这篇文章中的源代码主要有两个文件组成:一个主窗口叫MainForm,aMain.cs里面包含Main函数和App类。

如果你从一个空的C#窗口工程中开始的话,那么第一步你需要做的就是添加一个名为Microsoft.VisualBasic的引用。在解决方案浏览器中,在引用上面点击右键,选择“添加引用”,之后选择.net页,然后选择"Microsoft.VisualBasic“就行了。

在Main函数中,创建了一个App类的实例,并且运行了它,并传递命令行参数,如下代码:

static void Main(string[] args)
{
    App myApp = new App();
    myApp.Run(args);
}

App类是从Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase类派生而来的,这个基类包含检测一个应用程序已经存在的实例的所有代码。这个仅需要在构造函数中开启即可:

public App()
{
  // Make this a single-instance application
  this.IsSingleInstance = true; 
  this.EnableVisualStyles = true;
    
  // There are some other things available in 
  // the VB application model, for
  // instance the shutdown style:
  this.ShutdownStyle = 
    Microsoft.VisualBasic.ApplicationServices.ShutdownMode.AfterMainFormCloses;

  // Add StartupNextInstance handler
  this.StartupNextInstance += 
    new StartupNextInstanceEventHandler(this.SIApp_StartupNextInstance);
}

在构造函数的最后一行中,我们为StartupNextInstance事件添加了一个处理函数。当已经检测到一个已存在的实例时,会激活这个处理函数。在这里使用它,是为了传递命令行参数,但是如果不需要传递命令行参数的话,那么这个事件是需要去处理的。
下一步要做的就是覆盖OnCreateMainForm方法。只有当第一个实例运行的时候,才会调用这个方法。需要创建一个MainForm类的实例,然后将它保存到WindowsFormsApplicationBase的属性中。
通过复制ReadonlyCollection到一个字符串数组,并保存到窗口的一个成员变量中,从而实现将命令行参数传递到窗口。

protected override void OnCreateMainForm()
{
    // Create an instance of the main form 
    // and set it in the application; 
    // but don't try to run() it.
    this.MainForm = new MainForm();

    // We want to pass along the command-line arguments to 
    // this first instance

    // Allocate room in our string array
    ((MainForm)this.MainForm).Args = 
          new string[this.CommandLineArgs.Count];
    
    // And copy the arguments over to our form
    this.CommandLineArgs.CopyTo(((MainForm)this.MainForm).Args, 0);
}

应用程序中的其他的实例可能也想向第一个实例传递命令参数;比如,当第二个文件打开的是偶,一个文件查看器可能需要打开一个新的文档窗口,而不是需要应用程序的一个新的实例。那么可以像下面这么做:

protected void SIApp_StartupNextInstance(object sender, 
    StartupNextInstanceEventArgs eventArgs)
{
    // Copy the arguments to a string array
    string[] args = new string[eventArgs.CommandLine.Count];
    eventArgs.CommandLine.CopyTo(args, 0);

    // Create an argument array for the Invoke method
    object[] parameters = new object[2];
    parameters[0] = this.MainForm;
    parameters[1] = args;

    // Need to use invoke to b/c this is being called 
    // from another thread.
    this.MainForm.Invoke(new MainForm.ProcessParametersDelegate(
        ((MainForm)this.MainForm).ProcessParameters), parameters );
}

新的实例在另一个线程上,因此需要使用delegates和Invoke函数。MainForm.ProcessParameters方法仅仅是将参数添加到窗口的一个文本框上面。

感兴趣的地方

可能最需要单实例程序的地方是在一个资源浏览器的弹出菜单中打开一组文件。这样基本上会同时打开应用程序的多个实例。远程通信并加载其他实例需要很长的事件;在我的系统上,演示程序基本上可以每秒打开5个文件。

当打开50个文件时,发生了一个异常。原因是远程连接到第一个实例时超时了。如果你知道一个更好的方法来实现一个单实例应用程序,请告诉我们。


【更多阅读】

  1. [原]Cls_Ini.cls:VB写的操作ini配置文件的类
  2. [原]QQHelper:QQ大家来找茬 辅助工具 外挂
  3. [译]在C# .NET2.0实现单实例应用程序
  4. [原]GetIcons:C#提取应用程序的图标资源
  5. [原]IniFile.cs:C#来操作ini配置文件
  6. [原]《The C Programming Language》电子书下载
  7. [原]《The C Programming Language》电子书下载
  8. [译]C#控制计算机的并口LPT
  9. [原]ManageStartUpApps:C#操作注册表来读取和修改开机启动项
  10. [原]DownloadWebImages:下载某页面上的所有图片

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值