國內最大的酷站演示中心!
概述
本文是針對《基于.net平臺應用程序唯一運行實例實現》的補充,文章給出功能實現代碼,其中singleinstance類實現只允許一個實例運行,program為測試主程序入口。在代碼中標識說明文字。完整代碼下載。 
主要代碼
singleinstance.cs文件, 
using system;
using system.io;
using system.diagnostics;
using system.threading;
using system.reflection;
using system.runtime.interopservices;
/*------------------------------------------------
鄭佐 2006-07-01  http://blog.csdn.net/zhzuo      
--------------------------------------------------*/
namespace zhengzuo.csharpcode
{
    /// <summary>
    /// 只啟動一個應用程序實例控制類
    /// </summary>
    public static class singleinstance
    {
        private const int ws_shownormal = 1;
        [dllimport("user32.dll")]
        private static extern bool showwindowasync(intptr hwnd, int cmdshow); 
        [dllimport("user32.dll")]
        private static extern bool setforegroundwindow(intptr hwnd);
        //標志文件名稱
        private static string runflagfullname = null;
        //聲明同步基元
        private static mutex mutex = null; 
 
        /// <summary>
        /// static constructor
        /// </summary>
        static singleinstance()
        {
        } 
        #region api實現      
        /// <summary>
        /// 獲取應用程序進程實例,如果沒有匹配進程,返回null
        /// </summary>
        /// <returns>返回當前process實例</returns>
        public static process getrunninginstance()
        {            
            process currentprocess = process.getcurrentprocess();//獲取當前進程
            //獲取當前運行程序完全限定名
            string currentfilename = currentprocess.mainmodule.filename;
            //獲取進程名為processname的process數組。
            process[] processes = process.getprocessesbyname(currentprocess.processname);
            //遍歷有相同進程名稱正在運行的進程
            foreach (process process in processes)
            {
                if (process.mainmodule.filename == currentfilename)
                {
                    if (process.id != currentprocess.id)//根據進程id排除當前進程
                        return process;//返回已運行的進程實例
                }
            }
            return null;
        } 
        /// <summary>
        /// 獲取應用程序句柄,設置應用程序前臺運行,并返回bool值
        /// </summary>
        public static bool handlerunninginstance(process instance)
        {
            //確保窗口沒有被最小化或最大化
            showwindowasync(instance.mainwindowhandle, ws_shownormal);
            //設置真實例程為foreground window
            return setforegroundwindow(instance.mainwindowhandle);
        } 
        /// <summary>
        /// 獲取窗口句柄,設置應用程序前臺運行,并返回bool值,重載方法
        /// </summary>
        /// <returns></returns>
        public static bool handlerunninginstance()
        {
            process p = getrunninginstance();
            if (p != null)
            {
                handlerunninginstance(p);
                return true;
            }
            return false;
        } 
        #endregion
        #region mutex實現
        /// <summary>
        /// 創建應用程序進程mutex
        /// </summary>
        /// <returns>返回創建結果,true表示創建成功,false創建失敗。</returns>
        public static bool createmutex()
        {
            return createmutex(assembly.getentryassembly().fullname);
        } 
        /// <summary>
        /// 創建應用程序進程mutex
        /// </summary>
        /// <param name="name">mutex名稱</param>
        /// <returns>返回創建結果,true表示創建成功,false創建失敗。</returns>
        public static bool createmutex(string name)
        {
            bool result = false;
            mutex = new mutex(true, name, out result);
            return result;  
        } 
        /// <summary>
        /// 釋放mutex
        /// </summary>
        public static void releasemutex()
        {
            if (mutex != null)
            {
                mutex.close();
            }
        } 
        #endregion 
        #region 設置標志實現
        /// <summary>
        /// 初始化程序運行標志,如果設置成功,返回true,已經設置返回false,設置失敗將拋出異常
        /// </summary>
        /// <returns>返回設置結果</returns>
        public static bool initrunflag()
        {
            if (file.exists(runflag))
            {
                return false;
            }
            using (filestream fs = new filestream(runflag, filemode.create))
            { 
            }
            return true;
        } 
        /// <summary>
        /// 釋放初始化程序運行標志,如果釋放失敗將拋出異常
        /// </summary>
        public static void disposerunflag()
        {
            if (file.exists(runflag))
            {
                file.delete(runflag);
            }
        }  
        /// <summary>
        /// 獲取或設置程序運行標志,必須符合windows文件命名規范
        /// 這里實現生成臨時文件為依據,如果修改成設置注冊表,那就不需要符合文件命名規范。
        /// </summary>
        public static string runflag
        {             get
            {
                if(runflagfullname == null)
                {
                    string assemblyfullname = assembly.getentryassembly().fullname;
                    //commonapplicationdata://"c://documents and settings//all users//application data"
                    string path = environment.getfolderpath(environment.specialfolder.commonapplicationdata);
                    //"c://program files//common files"
                    //string path = environment.getfolderpath(environment.specialfolder.commonprogramfiles);
                    runflagfullname = path.combine(path, assemblyfullname);
                }
                return runflagfullname;
            }
            set
            {
                runflagfullname = value;
            }
        }
        #endregion
    }
}
program.cs文件, 
using system;
using system.windows.forms;
using system.diagnostics;
using zhengzuo.csharpcode;
/*------------------------------------------------
  鄭佐 2006-07-01  http://blog.csdn.net/zhzuo
--------------------------------------------------*/
namespace zhengzuo.test.wingui
{
    static class program
    {
        [stathread]
        static void main(string[] args)
        {
            if (args.length == 0) //沒有傳送參數
            {
                process p = singleinstance.getrunninginstance();
                if (p != null) //已經有應用程序副本執行
                {
                    singleinstance.handlerunninginstance(p);
                }
                else //啟動第一個應用程序
                {
                    runapplication();
                }
            }
            else //有多個參數
            {
                switch (args[0].tolower())
                {
                    case "-api":
                        if (singleinstance.handlerunninginstance() == false)
                        {
                            runapplication();
                        }
                        break;
                    case "-mutex":
                        if (args.length >= 2) //參數中傳入互斥體名稱
                        {
                            if ( singleinstance.createmutex(args[1]) )
                            {
                                runapplication();
                                singleinstance.releasemutex();
                            }
                            else
                            {
                                //調用singleinstance.handlerunninginstance()方法顯示到前臺。
                                messagebox.show("程序已經運行!");
                            }
                        }
                        else
                        {
                            if (singleinstance.createmutex())
                            {
                                runapplication();
                                singleinstance.releasemutex();
                            }
                            else
                            {
                                //調用singleinstance.handlerunninginstance()方法顯示到前臺。
                                messagebox.show("程序已經運行!");
                            }
                        }
                        break;
                    case "-flag"://使用該方式需要在程序退出時調用
                        if (args.length >= 2) //參數中傳入運行標志文件名稱
                        {
                            singleinstance.runflag = args[1];                          
                        }
                        try
                        {
                            if (singleinstance.initrunflag())
                            {
                                runapplication();
                                singleinstance.disposerunflag();
                            }
                            else
                            {
                                //調用singleinstance.handlerunninginstance()方法顯示到前臺。
                                messagebox.show("程序已經運行!");
                            }
                        }
                        catch (exception ex)
                        {
                            messagebox.show(ex.tostring());
                        }
                        break;
                    default:
                        messagebox.show("應用程序參數設置失敗。");
                        break;
                }
            }
        } 
        //啟動應用程序
        static void runapplication()
        {
            application.enablevisualstyles();
            application.run(new mainform());
        }
    }
}
功能測試
功能測試類別包括下面五類,
1.本地系統同一應用程序目錄;
2.本地系統同一應用程序修改運行文件名稱使兩次運行名稱不同;
3.本地系統兩次運行程序目錄不同,不修改文件名稱;
4.本地系統不同會話用戶登錄啟動應用程序;
5.遠程計算機程序訪問啟動應用程序(一個程序在遠程另一個在本地)。 運行cmd命令行,
第一種調用方式:
windowsapplication1.exe
或 windowsapplication1.exe –api
第二種調用方式:
windowsapplication1.exe –mutex
或windowsapplication1.exe –mutex {f140ae26-626c-42f8-bd49-45025742205e}
第三種調用方式:
windowsapplication1.exe –flag
或windowsapplication1.exe –flag c:/blog.csdn.net.zhzuo 
測試結果,
| 匹配/互斥/標志 | 1同一目錄 | 2修改名稱 | 3不同目錄 | 4不同用戶 | 5遠程訪問 | 
| 1同一目錄 | o/o/o |  |  |  |  | 
| 2修改名稱 |  | x/o/o |  |  |  | 
| 3不同目錄 |  |  | x/o/o |  |  | 
| 4不同用戶 |  |  |  | #/x/o |  | 
| 5遠程訪問 |  |  |  |  | x/o/o | 
備注:o - 表示成功,x – 表示失敗,# - 程序第二個運行沒有反應 針對遠程訪問的測試,需要在系統管理工具的.net framework 2.0 configuration中進行設置授權該局域網路徑允許訪問,否則會拋出system.security.securityexception異常。
根據測試結果可見三種實現方式適用范圍不同,理想的實現是結合他們的優點進行多點判斷。
 
更多資源
關于.net平臺應用的開發,更多的技術文章可以訪問http://blog.csdn.net/zhzuo,對于本文的建議或意見可在網站上留言。