bird

 

C#防止程序重复运行

很多的软件都支持一次只能运行一个程序,比如迅雷。一直搞不清楚这个是怎么做的。最近正好做了一个小工具,需要一个用户在一个网域内只能开启一个这个小工具。具体的需求是:说的通俗简单就是,有一台服务器,用户用一台显示器和一个键盘连到这个服务器上。这样这个服务器就可能同时用多个用户,而且这些用户可能在不同的网域内。这个工具就要支持,在同一个网域内,同一个用户只能开启一个这个工具。所以,简单的只能开启一个程序在这里就行不通了。

我的做法是:抓取所有正在运行的这个工具的进程,然后和当前网域当前用户的进程比较,如果存在就返回已经运行的当前网域当前用户的进程,不存在就开启。

刚开是我用到了Process.StartInfo.UserName和Process.StartInfo.Domain来抓取进程的用户名和网域,发现抓出来的全是空字串。没办法只有另寻他路。这里用到了WMI , 关于WMI是什么请参阅MSDN.

还是以实际例子来说明吧。首先建一个WINForm的工程,名字就叫做WINFormTest吧。呵呵呵,命名不规范了。

具体代码如下:

static class Program
    {
       
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern bool BringWindowToTop(IntPtr hwnd);
        [DllImport("User32.dll")]
        private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
        [DllImport("User32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        private const int WS_SHOWNORMAL = 1; //0不可见但仍然运行,1居中,2最小化,3最大化
  
     
        /// <summary>
        /// 應用程式的主要進入點。
        /// </summary>
        [STAThread]
        static void Main()
        {
            string szRepeatRun = "";

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
 

           Process instance = RunningInstance();//判断是否已经有运行的程序,如果有就返回该进程,没有返回Null

            if (instance == null)
            {
                Application.Run(new frmWINFormTest());
            }
            else
            {                 

               if (instance.MainWindowHandle.ToString() =="0")
                        MessageBox.Show("该程序已经运行!");               

                // 将窗口提到桌面的最上层,这里如果窗口自小化了,就不能提到最上层,原因正在解决。
                SetForegroundWindow(instance.MainWindowHandle);
             }
           
            //Application.Run(new EIPNotify());
        }
       public static Process RunningInstance()
        {
            int i, j;
            string szUserName, szProcessName, szDomain;//当前进程的用户名,进程名,和网域
            ArrayList ALProcess = new ArrayList();// 存储所有开启的程序的进程ID,用户名,网域
            tagProcess tProcess = new tagProcess();
            j = 0;
            szUserName = szDomain = "";
           
            szProcessName = "";
            Process current = Process.GetCurrentProcess();//得到当前进程
            Process[] processes = Process.GetProcessesByName(current.ProcessName);//得到和当前进程同名的进程
           // WMI  得到任务管理器中的所有的进程。    
            ManagementObjectSearcher psch=new ManagementObjectSearcher("select * from Win32_Process");
           
            foreach(ManagementObject mob in psch.Get())  
            {
                i = mob["Name"].ToString().LastIndexOf('.');
                if (i>=0)
                    szProcessName = mob["Name"].ToString().Substring(0, i);

               // 和当前进程同名,并且不是当前进程存入到Arraylist中 

               if (szProcessName == current.ProcessName && mob["processID"].ToString() != current.Id.ToString())
                {
                    string[] pob = new string[2];
                    mob.InvokeMethod("GetOwner", (object[])pob);// 得到进程的相关信息,存储在Object 数组中,其中第一个为用户名,第二个为网域,其它的是什么有待继续研究。
                    object UserName = pob[0];//进程的用户名
                    tProcess.szOldUserName = UserName.ToString();
                    object Domain = pob[1];//进程的网域
                    tProcess.szOldDomain = Domain.ToString();
                    tProcess.szProcessID = mob["processID"].ToString();// 进程的ID
                    ALProcess.Add(tProcess);
                }

                if (szProcessName == current.ProcessName && mob["processID"].ToString() == current.Id.ToString())// 获取当前进程的用户名和网域
                {
                    string[] pob = new string[2];
                    mob.InvokeMethod("GetOwner", (object[])pob);
                    object UserName = pob[0];
                    szUserName = UserName.ToString();
                    object Domain = pob[1];
                    szDomain = Domain.ToString();
                }               
            }
            for (j = 0; j < ALProcess.Count; j++)
            {
                tProcess = (tagProcess)ALProcess[j];
                if (tProcess.szOldUserName == szUserName && tProcess.szOldDomain == szDomain)
                {
                    foreach (Process process in processes)
                    {
                        if ((process.ProcessName == current.ProcessName) && (process.Id != current.Id) && (process.Id.ToString() == tProcess.szProcessID))
                        {
                            return process;
                        }
                    }
                }
            }
            return null;
           
        }
        public struct tagProcess
        {
            public string szProcessID;
            public string szOldUserName;
            public string szOldDomain;
        }

}

posted on 2007-08-24 17:52  鸟人  阅读(575)  评论(0编辑  收藏  举报

导航