让应用程序只运行一个实例的实现方法

2016-02-19 09:52 29 1 收藏

在这个颜值当道,屌丝闪边的时代,拼不过颜值拼内涵,只有知识丰富才能提升一个人的内在气质和修养,所谓人丑就要多学习,今天图老师给大家分享让应用程序只运行一个实例的实现方法,希望可以对大家能有小小的帮助。

【 tulaoshi.com - 编程语言 】

在我们的程序当中如果要实现类似《360软件管家》的功能,就要解决两个问题,首先是要判断该程序已有一个实例在运行,其次是要将已运行的应用程序实例激活,同时退出第二个应用程序实例。

对于第一个问题,我们可以通过设置命名互斥对象或命名信标对象,在程序启动的时候检测互斥对象或信标对象,如互斥对象或信标对象已存在,则可以判断此程序已有一个实例正在运行。

第二个问题是如何找到已经运行的应用程序实例,如果我们能够找到已运行实例主窗口的指针,即可调用SetForegroundWindow来激活该实例。我们可以通过两种形式找到已运行实例的主窗口,一种形式是通过调用FindWindowEx去查找正在运行的窗口的句柄,这种方式用得比较多一些,而本文通过另一种形式去查找正在运行的窗口的句柄。通过调用SetProp给应用程序主窗口设置一个标记,用GetDesktopWindow 可以获取Windows环境下的桌面窗口的句柄,所有应用程序的主窗口都可以看成该窗口的子窗口,接着我们就可以用GetWindow函数来获得这些窗口的句柄。然后再用Win32 SDK函数GetProp查找每一个应用程序的主窗口是否包含有我们设置的标记,这样就可以找到我们要找的第一个实例主窗口。

下面演示代码是以一个单文档应用程序为例,工程名字是Mutex。
代码如下:

1、在应用程序类InitInstance()函数中判断是否已有一个应用程序实例正在运行。

BOOL CMutexApp::InitInstance()

{

       //创建命名信标对象。

       HANDLE hSem=CreateSemaphore(NULL,1,1,"维新");

       if(hSem)  //信标对象创建成功。

       {

              //信标对象已经存在,则程序已有一个实例在运行。

              if(ERROR_ALREADY_EXISTS==GetLastError())

              {                 

                     CloseHandle(hSem);      //关闭信号量句柄。

//获取桌面窗口的一个子窗口。

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

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

                     while(::IsWindow(hWndPrev))

                     {

                     //判断窗口是否有我们预先设置的标记,如有,则是我们寻找的窗口,并将它激活。

                            if(::GetProp(hWndPrev,"维新"))  

                            {

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

                                   if (::IsIconic(hWndPrev))    

                                          ::ShowWindow(hWndPrev,SW_RESTORE);

                                   //将应用程序的主窗口激活。

                                   ::SetForegroundWindow(hWndPrev);

                                   return FALSE;                      //退出实例。

                            }

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

                            //继续寻找下一个窗口。

                            hWndPrev = ::GetWindow(hWndPrev,GW_HWNDNEXT);

                     }

                   

                     AfxMessageBox("已有一个实例在运行,但找不到它的主窗口!");

              }

       }

       else

       {

              AfxMessageBox("创建信标对象失败,程序退出!");

              return FALSE;

       }

       AfxEnableControlContainer();

       // Standard initialization

       // If you are not using these features and wish to reduce the size

       //  of your final executable, you should remove from the following

       //  the specific initialization routines you do not need.

     

#ifdef _AFXDLL

       Enable3dControls();                     // Call this when using MFC in a shared DLL

#else

       Enable3dControlsStatic();      // Call this when linking to MFC statically

#endif

       // Change the registry key under which our settings are stored.

       // TODO: You should modify this string to be something appropriate

       // such as the name of your company or organization.

       SetRegistryKey(_T("Local AppWizard-Generated Applications"));

       LoadStdProfileSettings();  // Load standard INI file options (including MRU)

       // Register the application's document templates.  Document templates

       //  serve as the connection between documents, frame windows and views.

       CSingleDocTemplate* pDocTemplate;

       pDocTemplate = new CSingleDocTemplate(

              IDR_MAINFRAME,

              RUNTIME_CLASS(CMutexDoc),

              RUNTIME_CLASS(CMainFrame),       // main SDI frame window

              RUNTIME_CLASS(CMutexView));

       AddDocTemplate(pDocTemplate);

       // Parse command line for standard shell commands, DDE, file open

       CCommandLineInfo cmdInfo;

       ParseCommandLine(cmdInfo);

       // Dispatch commands specified on the command line

       if (!ProcessShellCommand(cmdInfo))

              return FALSE;

       // The one and only window has been initialized, so show and update it.

       m_pMainWnd-ShowWindow(SW_SHOW);

       m_pMainWnd-UpdateWindow();

       return TRUE;

}

2、在框架类的OnCreate()函数中设置查找标记。

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

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

              return -1;

     

       if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP

              | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||

              !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

       {

              TRACE0("Failed to create toolbar/n");

              return -1;      // fail to create

       }

       if (!m_wndStatusBar.Create(this) ||

              !m_wndStatusBar.SetIndicators(indicators,

                sizeof(indicators)/sizeof(UINT)))

       {

              TRACE0("Failed to create status bar/n");

              return -1;      // fail to create

       }

       // TODO: Delete these three lines if you don't want the toolbar to

       //  be dockable

       m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);

       EnableDocking(CBRS_ALIGN_ANY);

       DockControlBar(&m_wndToolBar);

     

       //设置查找标记。

       ::SetProp(m_hWnd,"维新",(HANDLE)1);

       return 0;

}

3、在程序退出是删除设置的标记,在框架类中响应WM_DESTROY消息,进行处理。

void CMainFrame::OnDestroy()

{

       CFrameWnd::OnDestroy();

     

       // TODO: Add your message handler code here

       //删除所设置的标记。

       ::RemoveProp(m_hWnd,"维新");

}

至此,使应用程序只运行一个实例的功能就完成了。

来源:http://www.tulaoshi.com/n/20160219/1592453.html

延伸阅读
Oracle客户端精简后的文件,可以实现数据库的通信,直接和软件打包: 第一步:拷贝文件:主要是四个目录:bin,nls,oracore,NETWORK。 文件清单如下(bin下面dll部分是最精简的结果,除了nls的其他部分可以全部拷贝,因为本身文件不大): D:bin\orauts.dll D:bin\oraunls10.dll D:bin\orasrvmhas10.dll D:bin\orasql10.dll D:bin\o...
今天在MSN的核心讨论组上看到两篇文章.讨论的乃是应用程序是否没有响应.原文如下: How is it possible to determine a process is "not responding" like NT Task Manager do? The heuristic works only for GUI processes, and consists of calling SendMessageTimeOut() with SMTO_ABORTIFHUNG. T...
标签: Delphi
  随着Internet/intranet的发展,多层应用和分布式瘦客户数据库应用程序逐渐得到广泛应用。在多层应用的开发方式中,Delphi提供了Midas构件,第三方提供了Asta 、Midware等。经过使用,相比较而言,Asta所提供的构件易学易用方便灵巧,客户端程序无须任何数据库引擎或动态连结库即可方便的实现多层应用,且客户、服务器可实现实时信息...
标签: Delphi
  11.1 Help文件的建立 Help文件是 Micosoft Windows3.0 以上的版本提供的超文本帮助文件。利用这种超文本 , 用户可非常方便地使用帮助文件系统。帮助文件是以主题为主线进行编写的,一个主题可以跳转至相关的主题,也可按关键字进行主题查询。帮助文件与软件开发工具相结合,可实现应用程序的 ' 上下文敏感 ' ,而且帮助系统...
摘要 当一些应用程序崩溃时,它们往往向用户提供一个机会来提交关于该错误的信息。该信息能够帮助开发者追踪并修正错误。本文将向你展示如何在你的JavaScript/AJAX应用程序中实现这样的功能。 一、 引言 如果可以存取终端用户的计算机的话,那么终端用户的JavaScript错误就很容易调试。既然你不能实现这样的操作,那么你可以...

经验教程

822

收藏

79
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部