c# 实现一个程序仅能运行一个副本

恩,也就是说一个程序如果已经运行了,则不能再运行这个程序的一个副本.如果运行副本,则程序自动关闭,并把已经运行的程序的窗口打开.

开始使用mutex来实现的,但是这个我只能实现到判断副本的运行,不能把已经运行的窗口自动打开,后来使用其它方式实现的。

使用一个文件做一个标志,标志着一个副本在运行,并且一至不停的检测这个标志,代码:

 

 using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Threading;

namespace WindowsApplication8
{
 static class Program
 {
  ///


  /// 应用程序的主入口点。
  ///
  [STAThread]
  static void Main()
  {
   if (File.Exists(Application.StartupPath + "/mutex.tmp"))
   {
    File.Delete(Application.StartupPath + "/mutex.tmp");
    Thread.Sleep(1000);
    if (File.Exists(Application.StartupPath + "/mutex.tmp"))
     return;

   }

   Application.EnableVisualStyles();
   Application.SetCompatibleTextRenderingDefault(false);
   Application.Run(new Form1());
  }
 }
}

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.IO;
using System.Windows.Forms;

namespace WindowsApplication8
{
 public partial class Form1 : Form
 {
  public Form1()
  {
   InitializeComponent();
  }

  private void Form1_Load(object sender, EventArgs e)
  {
   this.timer1.Start();
  }

  private void timer1_Tick(object sender, EventArgs e)
  {
   if (!File.Exists(Application.StartupPath + "/mutex.tmp"))
   {
    FileStream fs= File.Create(Application.StartupPath + "/mutex.tmp");
    fs.Close();

    this.WindowState = FormWindowState.Normal;
   }

  }
 }
}

 虽然办法有些苯,但总归实现了.其它很多方法只能是先但进行运行,窗口没法自动出来,现在这个办法是我能想到的最简的地了.


看CSDN中lovefootball的帖子,使用他介绍的:http://www.codeproject.com/csharp/cssingprocess.asp

这个比我的实现方式要好,经过测试非常好用,代码如下:

 using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace WindowsApplication9
{
 static class Program
 {
  /// <summary>
  /// 应用程序的主入口点。
  /// </summary>
  [STAThread]
  static void Main()
  {
   using (SingleProgramInstance spi = new SingleProgramInstance("x5k6yz"))
   {
    if (spi.IsSingleInstance)
    {
     Application.EnableVisualStyles();
     Application.SetCompatibleTextRenderingDefault(false);
     Application.Run(new Form1());
    }
    else
    {
     spi.RaiseOtherProcess();
    }
   }

  }
 }
}

 

 using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Reflection;

namespace WindowsApplication9
{
 //SingleProgamInstance uses a mutex synchronization object
 // to ensure that only one copy of process is running at
 // a particular time.  It also allows for UI identification
 // of the intial process by bring that window to the foreground.
 public class SingleProgramInstance : IDisposable
 {

  //Win32 API calls necesary to raise an unowned processs main window
  [DllImport("user32.dll")]
  private static extern bool SetForegroundWindow(IntPtr hWnd);
  [DllImport("user32.dll")]
  private static extern bool ShowWindowAsync(IntPtr hWnd,int nCmdShow);
  [DllImport("user32.dll")]
  private static extern bool IsIconic(IntPtr hWnd);

  private const int SW_RESTORE = 9;

  //private members
  private Mutex _processSync;
  private bool _owned = false;
  
 
  public SingleProgramInstance()
  { 
   //Initialize a named mutex and attempt to
   // get ownership immediatly
   _processSync = new Mutex(
    true, // desire intial ownership
    Assembly.GetExecutingAssembly().GetName().Name,
    out _owned);
  }

  public SingleProgramInstance(string identifier)
  { 
   //Initialize a named mutex and attempt to
   // get ownership immediately.
   //Use an addtional identifier to lower
   // our chances of another process creating
   // a mutex with the same name.
   _processSync = new Mutex(
    true, // desire intial ownership
    Assembly.GetExecutingAssembly().GetName().Name + identifier,
    out _owned);
  }

  ~SingleProgramInstance()
  {
   //Release mutex (if necessary)
   //This should have been accomplished using Dispose()
   Release();
  }

  public bool IsSingleInstance
  {
   //If we don't own the mutex than
   // we are not the first instance.
   get {return _owned;}
  }

  public void RaiseOtherProcess()
  {
   Process proc = Process.GetCurrentProcess();
   // Using Process.ProcessName does not function properly when
   // the name exceeds 15 characters. Using the assembly name
   // takes care of this problem and is more accruate than other
   // work arounds.
   string assemblyName = Assembly.GetExecutingAssembly().GetName().Name;
   foreach (Process otherProc in Process.GetProcessesByName(assemblyName))
   {
    //ignore this process
    if (proc.Id != otherProc.Id)
    {
     // Found a "same named process".
     // Assume it is the one we want brought to the foreground.
     // Use the Win32 API to bring it to the foreground.
     IntPtr hWnd = otherProc.MainWindowHandle;
     if (IsIconic(hWnd))
     {
      ShowWindowAsync(hWnd,SW_RESTORE);
     }
     SetForegroundWindow(hWnd);
     return;
    }
   }
  }

  private void Release()
  {
   if (_owned)
   {
    //If we owne the mutex than release it so that
    // other "same" processes can now start.
    _processSync.ReleaseMutex();
    _owned = false;
   }
  }

 #region Implementation of IDisposable
  public void Dispose()
  {
   //release mutex (if necessary) and notify
   // the garbage collector to ignore the destructor
   Release();
   GC.SuppressFinalize(this);
  }
 #endregion
 }
}

 

这个代码就是使用mutex实现的,非常的不错。效率等方面应该比我那种简单的方式强很多,推荐使用。

posted on 2010-12-30 13:19  米高佐敦  阅读(275)  评论(0编辑  收藏  举报