zoukankan      html  css  js  c++  java
  • 如何控制一个程序只能有一个进程?[From csdn]

    Windows是多进程操作系统,框架生成的应用程序可以多次运行,形成多个运行实  
      例。但在有些情况下为保证应用程序的安全运行,要求程序只能运行一个实例,比  
      如程序要使用只能被一个进程单独使用的特殊硬件(例如调制解调器)时,必须限  
      制程序只运行一个实例。  
      这里涉及两个基本的问题,一是在程序的第二个实例启动时,如何发现该程序已有  
      一个实例在运行,而是如何将第一个实例激活,而第二个实例退出。  
       
      对于第一个问题,可以通过给应用程序设置信号量,实例启动时首先检测该信号量  
      ,如已存在,则说明程序已运行一个实例。  
       
      第二个问题的难点是获取第一个实例的主窗对象指针或句柄,然后便可用  
      SetForegroundWindow来激活。虽然FindWindow函数能寻找正运行着的窗口,但该  
      函数要求指明所寻找窗口的标题或窗口类名,不是实现通用方法的途径。我们可以  
      用Win   32   SDK函数SetProp来给应用程序主窗设置一个特有的标记。用  
      GetDesktopWindow可以获取Windows系统主控窗口对象指针或句柄,所有应用程序  
      主窗都可看成该窗口的子窗口,即可用GetWindow函数来获得它们的对象指针或句  
      柄。用Win   32   SDK函数GetProp查找每一应用程序主窗是否包含有我们设置的特定  
      标记便可确定它是否我们要寻找的第一个实例主窗。使第二个实例退出很简单,只  
      要让其应用程序对象的InitInstance函数返回FALSE即可。此外,当主窗口退出时  
      ,应用RemoveProp函数删除我们为其设置的标记。 

    BOOL CTestApp::InitInstance()

    {

        /********************************/

        //   用应用程序名创建信号量 

        HANDLE   hSem   =   CreateSemaphore(NULL, 1, 1, m_pszExeName);  

        //   信号量已存在? 

        //   信号量存在,则程序已有一个实例运行 

        if   (GetLastError() == ERROR_ALREADY_EXISTS)  

        {  

            //关闭信号量句柄 

            CloseHandle(hSem);  

            //寻找先前实例的主窗口 

            HWND   hWndPrevious   = ::GetWindow(::GetDesktopWindow(), GW_CHILD);  

            while(::IsWindow(hWndPrevious))  

            {  

                // 检查窗口是否有预设的标记?  

                //有,则是我们寻找的主窗 

                if   (::GetProp(hWndPrevious,   m_pszExeName))  

                {  

                    //   主窗口已最小化,则恢复其大小 

                    if   (::IsIconic(hWndPrevious))  

                        ::ShowWindow(hWndPrevious,    

                        SW_RESTORE);  

                    //   将主窗激活 

                    ::SetForegroundWindow(hWndPrevious);  

                    //   将主窗的对话框激活 

                    ::SetForegroundWindow(  

                        ::GetLastActivePopup(hWndPrevious));  

                    //   退出本实例 

                    return   FALSE;  

                }  

                //   继续寻找下一个窗口 

                hWndPrevious   =   ::GetWindow(hWndPrevious,    

                    GW_HWNDNEXT);  

            }  

            //   前一实例已存在,但找不到其主窗 

            //   可能出错了 

            //   退出本实例 

            return   FALSE;  

        }

    AfxEnableControlContainer();

        //... ...

    }

    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

    {

        if (CFrameWnd::OnCreate(lpCreateStruct) == -1)

            return -1;

        //设置寻找标记 ljs  

        ::SetProp(m_hWnd,   AfxGetApp()->m_pszExeName,(HANDLE)1);  

        m_GameLobbyDlg.Create(this);

        m_bInit = TRUE;

        return 0;

    }

    CMainFrame::~CMainFrame()

    {

        //删除寻找标记 

        ::RemoveProp(m_hWnd, AfxGetApp()->m_pszExeName); 

    }

    法二:

    互斥体

        ::CreateMutex(NULL,TRUE,m_pszExeName);  

        if(GetLastError()==ERROR_ALREADY_EXISTS)  

        {  

            //   寻找先前实例的主窗口 

            HWND   hWndPrevious   =   ::GetWindow(::GetDesktopWindow(),   GW_CHILD);  

            while(::IsWindow(hWndPrevious))  

            {  

                if(::GetProp(hWndPrevious,m_pszExeName))  

                {  

                    //   主窗口已最小化,则恢复其大小 

                    if   (::IsIconic(hWndPrevious))  

                        ::ShowWindow(hWndPrevious,   SW_RESTORE);  

                    //   将主窗激活 

                    ::SetForegroundWindow(hWndPrevious);  

                    //   将主窗的对话框激活 

                    ::SetForegroundWindow(::GetLastActivePopup(hWndPrevious));  

                    //   退出本实例 

                    return   FALSE;  

                }  

                hWndPrevious   =   ::GetWindow(hWndPrevious,   GW_HWNDNEXT);  

            }  

            return   FALSE;   

        }

     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    c#:

    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    using System.Diagnostics;
    using System.Reflection;

    public class OneInstnace
    {
        [STAThread]
        public static void Main()
        {
            //Get   the   running   instance.  
            Process instance = RunningInstance();
            if (instance == null)
            {
                //There   isn't   another   instance,   show   our   form.  
                Application.Run(new Form());
            }
            else
            {
                //There   is   another   instance   of   this   process.  
                HandleRunningInstance(instance);
            }
        }

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

            //Loop   through   the   running   processes   in   with   the   same   name  
            foreach (Process process in processes)
            {
                //Ignore   the   current   process  
                if (process.Id != current.Id)
                {
                    //Make   sure   that   the   process   is   running   from   the   exe   file.  
                    if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") ==
                    current.MainModule.FileName)
                    {
                        //Return   the   other   process   instance.  
                        return process;
                    }
                }
            }

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


        public static void HandleRunningInstance(Process instance)
        {
            //Make   sure   the   window   is   not   minimized   or   maximized  
            ShowWindowAsync(instance.MainWindowHandle, WS_SHOWNORMAL);
            //Set   the   real   intance   to   foreground   window  
            SetForegroundWindow(instance.MainWindowHandle);
        }

        [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;
    }

     也可以使用互斥体Mutex类型完成此功能。见如下代码:  
              [STAThread]  
              public   static   void   Main(string[]   args)    
              {  
                        //声明互斥体。  
                        Mutex   mutex   =   new   Mutex(false,   "ThisShouldOnlyRunOnce");  
                        //判断互斥体是否使用中。  
                        bool   Running   =   !mutex.WaitOne(0,   false);  
                        if   (!   Running)  
                                Application.Run(new   FormLogin());  
                        else  
                                MessageBox.Show("应用程序已经启动!");  
              }  

  • 相关阅读:
    备胎的养成记KeepAlived实现热备负载
    入坑系列之HAProxy负载均衡
    将Error异常日志从普通日志中剥离
    一步一步在Windows中使用MyCat负载均衡 下篇
    年终的第一篇总结 结束南漂 写在2017
    Android实现TCP断点上传,后台C#服务实现接收
    为什么我会反对大家写工作日报
    ANSI C、ISO C、Standard C联系与区别
    c、c++ char*和wchar*互相转换
    宽字符与Unicode (c语言 汉语字符串长度)
  • 原文地址:https://www.cnblogs.com/anorthwolf/p/process.html
Copyright © 2011-2022 走看看