C# Windows 桌面应用只运行一个实例(总结)

1) 根据“程序集的签名”获取已运行的实例
///   <summary>
///  根据“程序集的签名”获取已运行的实例
///     .EXE 文件改名或路径改变,此方法可正常工作
///   </summary>
///   <param name="runningProcess"> 前一个实例的 Process </param>
///   <returns> 是否有相同的实例在运行 ture/false </returns>
///   <remarks> 需要对程序集进行签名。存在问题:速度稍慢。 </remarks>
private   static   bool  GetRunningProcessByAssemblyName( out  Process runningProcess)
{
    
bool  returnValue  =   false ;
    runningProcess 
=   null ;

    AssemblyName currentAssemblyName 
=  
             AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location);
    AssemblyName processAssemblyName 
=   new  AssemblyName();

    Process current 
=  Process.GetCurrentProcess();
    Process[] processes 
=  Process.GetProcesses();
    
foreach  (Process process  in  processes)
    {
        
//  排除一些其他进程,可以加快点速度。
         if  (process.Id  !=  current.Id  &&  
            process.ProcessName 
!=   " System "   &&
            process.ProcessName 
!=   " csrss "   &&
            process.ProcessName 
!=   " svchost "   &&  
            process.ProcessName 
!=   " services "   &&
            process.ProcessName 
!=   " smss "   &&
            process.ProcessName 
!=   " winlogon "   &&
            process.ProcessName 
!=   " explorer "   &&
            process.ProcessName 
!=   " pds "   &&
            process.ProcessName 
!=   " alg "   &&
            process.ProcessName 
!=   " msdtc "   &&
            process.ProcessName 
!=   " spoolsv "   &&
            process.ProcessName 
!=   " lsass "   &&
            process.ProcessName 
!=   " Idle "   &&
            process.ProcessName 
!=   " iexplore "   &&
            process.ProcessName 
!=   " sqlserver "   &&
            process.ProcessName 
!=   " notepad "   &&
            process.ProcessName 
!=   " 360tray "   &&
            process.ProcessName 
!=   " XDict "
            )
        {
            
try
            {
                
//  获取文件的程序集
                processAssemblyName  =  AssemblyName.GetAssemblyName(process.MainModule.FileName);
            }
            
catch  (Exception)
            {
                processAssemblyName 
=   null ;
            }

            
//  通过 GetPublicKey() 来获取程序集的公钥;需要对程序集签名,否则 GetPublicKey() 返回的是 Null。
             if  (processAssemblyName  !=   null   &&
                CompareBytes(currentAssemblyName.GetPublicKey(), 
                                     processAssemblyName.GetPublicKey()))
            {
                runningProcess 
=  process;
                returnValue 
=   true ;
                
break ;
            }
        }
    }
    
return  returnValue;
}

2) 根据“进程名称”获取已运行的实例
///   <summary>
///  根据“进程名称”获取已运行的实例
///   </summary>
///   <param name="runningProcess"> 前一个实例的 Process </param>
///   <returns> 是否有相同的实例在运行 ture/false </returns>
///   <remarks> 存在问题:1)有可能有相同的进程名; 2)修改了文件名,此方法失效。 </remarks>
private   static   bool  GetRunningProcessByProcessName( out  Process runningProcess)
{
    
bool  returnValue  =   false ;
    runningProcess 
=   null ;

    Process current 
=  Process.GetCurrentProcess();
    Process[] processes 
=  Process.GetProcessesByName(current.ProcessName);
    
foreach  (Process process  in  processes)
    {
        
if  (process.Id  !=  current.Id)
        {
            
if  (process.ProcessName  ==  current.ProcessName)
            {
                runningProcess 
=  process;
                returnValue 
=   true ;
                
break ;
            }
        }
    }
    
return  returnValue;
}

3) 根据“进程名称和路径”获取已运行的实例
///   <summary>
///  根据“进程名称和路径”获取已运行的实例
///   </summary>
///   <param name="runningProcess"> 前一个实例的 Process </param>
///   <returns> 是否有相同的实例在运行 ture/false </returns>
///   <remarks> 存在问题:修改了文件名或改变了文件路径,此方法失效。 </remarks>
private   static   bool  GetRunningProcessByProcessFullName( out  Process runningProcess)
{
    
bool  returnValue  =   false ;
    runningProcess 
=   null ;

    Process current 
=  Process.GetCurrentProcess();
    Process[] processes 
=  Process.GetProcessesByName(current.ProcessName);
    
foreach  (Process process  in  processes)
    {
        
if  (process.Id  !=  current.Id)
        {
            
if  (process.MainModule.FileName  ==
               Assembly.GetExecutingAssembly().Location)
            {
                runningProcess 
=  process;
                returnValue 
=   true ;
                
break ;
            }
        }
    }
    
return  returnValue;
}

4) 根据“Mutex”判断是否有相同的实例在运行
///   <summary>
///  根据“Mutex”判断是否有相同的实例在运行
///   </summary>
///   <param name="runningProcess"> 总是 null </param>
///   <returns> 是否有相同的实例在运行 ture/false </returns>
///   <remarks> 存在问题:不能返回前一个实例的 Process </remarks>
private   static   bool  GetRunningProcessByMutex( out  Process runningProcess)
{
    
bool  returnValue  =   false ;
    runningProcess 
=   null ;

    
bool  isCreated;
    Mutex m 
=   new  Mutex( false " OneInstance " out  isCreated);
    
if  ( ! (isCreated))
    {
        MessageBox.Show(
" 已经有相同的实例在运行。 " " 提示 "
             MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    returnValue 
=   ! isCreated;
    
return  returnValue;
}

其他相关代码

私有方法

#region Windows API 声明
/// <summary>
/// 恢复一个最小化的程序,并将其激活
/// </summary>
/// <param name="hWnd">窗口句柄</param>
/// <returns>非零表示成功,零表示失败</returns>

[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool OpenIcon(IntPtr hWnd);

/// <summary>
/// 窗口是否已最小化
/// </summary>
/// <param name="hWnd">窗口句柄</param>
/// <returns>非零表示成功,零表示失败</returns>

[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool IsIconic(IntPtr hWnd);

/// <summary>
/// 将窗口设为系统的前台窗口
/// </summary>
/// <param name="hWnd">窗口句柄</param>
/// <returns>非零表示成功,零表示失败</returns>

[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern int SetForegroundWindow(IntPtr hWnd);


/// <summary>
/// 与ShowWindow相似,只是这时的ShowWindow命令会投递到指定的窗口,然后进行异步处理。
///     这样一来,就可控制从属于另一个进程的窗口的可视情况。
///     同时无须担心另一个进程挂起的时候,自己的应用程序也会牵连其中返回值
/// </summary>
/// <param name="hWnd">窗口句柄</param>
/// <param name="cmdShow">为窗口指定可视性方面的一个命令</param>
/// <returns>如窗口之前是可见的,则返回TRUE(非零),否则返回FALSE(零)</returns>

[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
private const int SW_HIDE = 0;           //隐藏窗口,活动状态给令一个窗口 
private const int SW_SHOWNORMAL = 1;     //用原来的大小和位置显示一个窗口,同时令其进入活动状态 
private const int SW_SHOWMINIMIZED = 2;  //最小化窗口,并将其激活 
private const int SW_SHOWMAXIMIZED = 3;  //最大化窗口,并将其激活 
private const int SW_SHOWNOACTIVATE = 4//用最近的大小和位置显示一个窗口,同时不改变活动窗口 
private const int SW_RESTORE = 9;        //用原来的大小和位置显示一个窗口,同时令其进入活动状态 
private const int SW_SHOWDEFAULT = 10;   //根据默认 创建窗口时的样式 来显示
#endregion
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值