如何防止应用程序拥有多个实例?

时间:2014-09-16 14:33:52

标签: c++ visual-c++ mfc

目前我正在开发一个mfc应用程序,它应该被命名为setup.exe并完成。在进入我被击中的地方之前,我会告诉你我所做的事情。 首先,我必须阻止我的应用程序的多个实例。在初级阶段,我创建了一个事件并检查:: getlasterror()是否setup.exe已经存在,如果.exe存在,我显示的是messagebox.So,有多少时间我运行exe,多次消息框将重复。 所以,而不是显示那么多的消息框。我有一个想法,如果我的setup.exe已经存在然后把它带到屏幕的前面。所以,我尝试这样,它工作得很好。但这里出现了我的实际问题,即,一旦我安装了一些Windows setup.exe并且它的安装正在进行,同时我尝试运行我的setup.exe然后我将windows setup.exe放到前面而不是我的应用程序& #34; SETUP.EXE&#34 ;. 这实际上是我在InitInstance中实现的,如下所示,

BOOL CMyApp::InitInstance()
{
   CWinApp::InitInstance();
   AppIsAllreadyRunning();
   return TRUE;
}

BOOL CMyApp::AppIsAllreadyRunning(BOOL bShow/*=TRUE*/)
{
   BOOL bRunning = FALSE;

   WCHAR szAppName[MAX_PATH] = {0};
  ::wcscpy_s(szAppName, MAX_PATH, theApp.m_pszExeName);
  ::wcscat_s(szAppName, MAX_PATH, L".exe");
   DWORD dwOwnPID = ::GetProcessId(::GetCurrentProcess());
   HANDLE hSnapShot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
   PROCESSENTRY32* processInfo = new PROCESSENTRY32;
   processInfo->dwSize = sizeof(PROCESSENTRY32);
   int index = 0;
   while(::Process32Next(hSnapShot, processInfo) != FALSE)
   {
     if(!::wcscmp(processInfo->szExeFile, szAppName))
      {
        if(processInfo->th32ProcessID != dwOwnPID)
        {
            if(bShow)
      ::EnumWindows(ShowAppEnum, processInfo->th32ProcessID);

            bRunning = TRUE;
            break;
        }
     }
  }
    ::CloseHandle(hSnapShot);
    delete processInfo;
    return bRunning;

}

 BOOL CALLBACK ShowAppEnum(HWND hwnd, LPARAM lParam)
{
  DWORD dwID = 0;
  ::GetWindowThreadProcessId(hwnd, &dwID) ;
  if(dwID == (DWORD)lParam)
  {
    if (!::IsWindowVisible(hwnd))
        ::ShowWindow(hwnd,SW_SHOW); 
    ::SetForegroundWindow(hwnd);
  }
  return TRUE;
}

这就是我试过的方法。任何人都可以让我知道如何使我的setup.exe与其他setup.exe不同,当我运行我的setup.exe它应该只是来到前面,正如我上面所解释的那样如果我运行不同的setup.exe并且正在进行某些安装,并且在同一时间如果我运行我的setup.exe则必须启动它或者如果它已经存在则必须进入前面。但是不同的setup.exe已经运行的正在弹出(这不应该发生)。

1 个答案:

答案 0 :(得分:0)

在CYourApp.h中:

extern const CString g_sMutexName;

在CYourApp.cpp中:

const CString g_sMutexName = _T("TRA-LA-LA-LA-YOURUNIQUE_ID");


BOOL CYourApp::InitInstance()
{
CWnd* pWnd = CWnd::FindWindow(g_sMutexName, NULL);

if(NULL != pWnd)
{
    // A prevous running instance already created a window with the given class name.
    // Bring it to front then return. 
    pWnd->ShowWindow(SW_SHOWNA);
    if(pWnd->IsIconic())
        pWnd->ShowWindow(SW_RESTORE);
    pWnd->SetForegroundWindow();
    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.
 ...

}

在您的CMainFrame.cpp中:

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if(! CFrameWnd::PreCreateWindow(cs))
    return FALSE;
// TODO: Modify the Window class or styles here by modifying
//  the CREATESTRUCT cs

WNDCLASS wclass;
::ZeroMemory(&wclass, sizeof(WNDCLASS));
wclass.style = CS_DBLCLKS;
wclass.hCursor = ::AfxGetApp()->LoadStandardCursor(IDC_ARROW);
wclass.hIcon = ::AfxGetApp()->LoadIcon(IDR_MAINFRAME);
wclass.lpfnWndProc = ::DefWindowProc;
wclass.lpszClassName = g_sMutexName;
::AfxRegisterClass(&wclass);

cs.lpszClass = g_sMutexName;

return TRUE;
}

当尝试打开您应用的另一个实例时,现有的实例将处于活动状态......

Flaviu。