转如何确保应用只有一个实例运行

原文地址:http://www.cnblogs.com/zhangronghua/archive/2006/11/17/564085.html

思路:也即能有一个变量来表示程序是否已启动!

 1.通过注册表...当程序初次启动时,向注册表写入一个节点(自定义名称),关闭时删除写入的节点...启动时判断是否已存在,存在则提示"已启动",否则写入并启动程序..

  static class Program
    {
        
/// <summary>
        
/// 应用程序的主入口点。
        
/// </summary>
        [STAThread]
        
static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(
false);
            
try
            {
                
//Microsoft.Win32.Registry key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"software\wo9421");
                Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"software\wo9421");
                
if (key == null)
                {
                    Microsoft.Win32.RegistryKey writeKey 
= Microsoft.Win32.Registry.LocalMachine.CreateSubKey(@"software\wo9421");
                    writeKey.SetValue(
"instanceFlag""1");
                    Application.Run(
new Form1());
                }
                
else
                {
                    MessageBox.Show(
"程序已启动");
                }
            }
            
catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            
//Application.Run(new Form1());
        }
    }

ps:是RegistryKey,而不是Registry,否则会提示出错:无法声明静态类型“Microsoft.win32.Registry”的变量。

ps: (@"software\wo9421")是自定义的名称,前后要保持一致.别错了

ps:一定要在程序关闭时删除该信息,否则会造成程序以后无法启动! 如在Form1_FormClosing事件中添加如下代码:

 private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            
try
            {
                Microsoft.Win32.RegistryKey key 
= Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"software"true);
                
if (key != null)
                {
                    key.DeleteSubKey(
@"wo9421");
                }
            }
            
catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

ps:打开的是software而不是software\wo9421..并且带参数true表示是可写入的.否则不能删除..

ps:删除的是 software下的wo9421节点,也不能错了

 通过注册表有个弊端::就是当异常关闭时,没能执行closing事件,没能删除注册表信息,导致无法启动..(如当程序运行时,通过任务管理器关掉程序,则不能再次打开,会提示已启动)

 2.通过Mutex(类似利用线程)

 可以使用   mutex   对象保护共享资源不被多个线程或进程同时访问。mutex   对象的状态或者设置为终止(当它不属于任何线程时),或者设置为非终止(当它属于某个线程时)。同时只能有一个线程拥有一个   mutex   对象。

 static class Program
    {
        
/// <summary>
        
/// 应用程序的主入口点。
        
/// </summary>
        [STAThread]
        
static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(
false);
            
bool bCreatedNew = true;
            System.Threading.Mutex mt 
= new System.Threading.Mutex(false"9421Frame"out bCreatedNew);
            
if (bCreatedNew)
            {

                Application.Run(
new Form1());
            }
            
else
            {
                MessageBox.Show(
"程序已启动");
            }
            
//Application.Run(new Form1());
        }
    }

ps:在给Mutex起名字的时候,不要太简单,以防止和其他程序的Mutex重复,从而达不到所预想的效果。

 3.利用process(进程?)

    static class Program
    {
        
/// <summary>
        
/// 应用程序的主入口点。
        
/// </summary>
        [STAThread]
        
static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(
false);
            
if (RuningInstance() == null)
            {
                Application.Run(
new Form1());
            }
            
else
            {
                MessageBox.Show(
"程序已启动");
            }
        }

        
public static System.Diagnostics.Process RuningInstance()
        {
            System.Diagnostics.Process current 
= System.Diagnostics.Process.GetCurrentProcess();
            System.Diagnostics.Process[] processes 
= System.Diagnostics.Process.GetProcessesByName(current.ProcessName);

            
foreach (System.Diagnostics.Process pro in processes)
            {
                
//Ignore the current process 
                if (pro.Id != current.Id)
                {
                    
//Make sure that the process is running from the exe file. 
                    if (System.Reflection.Assembly.GetExecutingAssembly().Location.Replace("/""\\"== current.MainModule.FileName)
                    {
                        
//Return the other process instance
                        return pro;
                    }
                }
            }

            
//No other instance was found, return null.
            return null;
        }
    }


原文地址:https://www.cnblogs.com/9421/p/1646702.html