[MFC] VC++ 프로그램 중복 실행 방지

2008. 2. 4. 14:07Coders

프로그램이 두 번 실행되는 것을 방지하는 코드들... 출처는 여기저기.

☞ 프로그램을 작성하다보면, 프로그램이 두 번 이상 실행되는 것을 막아야 하는 경우가 있다. 실제 내가 작업하는 프로그램상에서는 3번 Mutex 를 사용하고 있다.
☞ 물론, 이미 실행중이라면, 실행중인 해당 프로세스를 찾아서, 화면상에 윈도우가 나타나야 할 프로그램이라면, 프로세스만 떠 있고, 윈도우를 찾아서 윈도우가 없을 경우에는 무엇인가 뻑으로 보고 해당 프로세스를 죽여버리고 새 프로세스(현재 내 프로세스)를 그대로 실행시켜주고, (이전에 실행된)프로세스의 윈도우를 찾았을 때에는 해당 윈도우를 최상위로 가져오는 등(그 실행되고 있는 프로세스, 윈도우를 앞으로 꺼내오기가 좀 복잡하다.)의 작업까지 이루어져야 하지만, 우선은 중복 실행 방지에 대한 코드들만 모아 보았다.
☞ 이런 거 가져다 써 놓으면 세세한 설명을 자상하게 써 놓으면 좋겠지만, 기본기 없이 맨땅에 헤딩하는 식으로 살아온 나로서는 그냥 갖다 쓸 수 있을 정도로만 적어 놓는 것 만으로도 벅찬 일이다.


1. Class Name 이용
  1. #define MY_CLASS_NAME _T( "MyNewClass" )
  2. //유일한 Class Name 을 적는다.

  3. BOOL TestApp::InitInstance()
  4. {
  5.         //if a previous instance of the application
  6.         //is already running, then activeate it and
  7.         //return FALSE from InitInstance to end the
  8.         //execution of this Instance
  9.         if (!FirstInstance()) return FALSE;
  10.  
  11.         WNDCLASS wndcls;
  12.         memset( &wndcls, 0, sizeof(WNDCLASS));
  13.         wndcls.style = CS_DBLCLKS : CS_HREDRAW : CS_VREDRAW;
  14.         wndcls.lpfnWndProc = ::DefWindowProc;
  15.         wndcls.hInstance = AfxGetInstanceHandle();
  16.         wndcls.hIcon = LoadIcon ( IDR_MAINFRAME );
  17.         wndcls.hCursor = LoadCursor( IDC_ARROW );
  18.         wndcls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  19.         wndcls.lpszMenuName = NULL;
  20.         wndcls.lpszClassName = MY_CLASS_NAME;
  21.  
  22.         if(!AfxRegisterClass(&wndcls))
  23.         {
  24.                 TRACE("Class Registeration Failedn");
  25.                 return FALSE;
  26.         }
  27.  
  28.         bClassRegistered = TRUE;
  29. }
  30.  
  31. BOOL TestApp::FirstInstance()
  32. {
  33.         CWnd *pWndPrev, *pWndChild;
  34.         pWndPrev = CWnd::FindWindow(MY_CLASS_NAME, NULL);
  35.         if(!pWndPrev) return TRUE;
  36.         pWndChild = pWndPrev -> GetLastActivePopup();
  37.         if(pWndPrev -> IsIconic())
  38.                 pWndprev -> ShowWindow(SW_RESTORE);
  39.  
  40.         pWndChild -> SetForegroundWindow();
  41.         return FALSE;
  42. }

2. 공유 메모리 이용 -> 이건 잘 모르겠음...
  1. //아래 부분은 메소드 안에 쓰는게 아닙니다.
  2. //그냥 cpp file상단에 넣어 주세요.
  3. #pragma data_seg("Shared")
  4. //데이타 세그먼트를 생성하는데 Shared란 섹션을 만들어라.
  5. long m_lUsageCnt=0;
  6. //Shared란 데이타 세그먼트 섹션에 들어가는 변수.
  7.  
  8.  
  9. //반드시 초기화를 해주어야합니다. 이유는 초기화를 안할시 우리가 원하는 섹션으로
  10. //가는것이 아니라 bbs섹션으로 들어가기 때문입니다.
  11. #pragma data_seg()
  12.  
  13. #pragma comment(linker, "test /section:Shared,rws")
  14. //여기서 test는 exe화일 이름입니다.
  15. //링커에게 이섹션은 쓰기, 읽기, 공유로 링크함을 알림
  16.  
  17. //이렇게 써주면 m_lUsageCnt변수는 공유를 하게됩니다.
  18. //이것을 이용해서 우리의 어플리케이션이 몇개가 실행중인지를 알 수 있습니다.
  19. //initinstance에서 m_IUsageCnt를 하나 증가 시키고 1크면 return FALSE; 하면 됩니다.

  20. BOOL TestApp::InitInstance()
  21. {
  22.         m_IUsageCnt++;
  23.         if(m_IUsageCnt > 1)
  24.                 return FALSE;
  25.  
  26.         ...
  27. }

3. Mutex 이용
  1. #define MY_UNIQUE_MUTEXT _T( "633741A7-2449-4209-804E-86E29BE36D24" )
  2. //Mutex 는 O/S 상에서 유일하다.

  3. BOOL TestApp::InitInstance()
  4. {
  5.         // Mutex 생성
  6.         HANDLE hMutexOneInstance =
  7.         ::CreateMutex(NULL, TRUE, MY_UNIQUE_MUTEXT);
  8.  
  9.         BOOL bFound = FALSE;
  10.         // 만약 이미 만들어져 있다면 Instance가 이미 존재함
  11.         if(::GetLastError() == ERROR_ALREADY_EXISTS)
  12.                 bFound = TRUE;
  13.  
  14.         if(hMutexOneInstance)
  15.                 ::ReleaseMutex(hMutexOneInstance);
  16.  
  17.         // 이미 하나의 Instance가 존재하면 프로그램 종료
  18.         if(bFound) {
  19.                 AfxMessageBox("이미 실행중입니다");
  20.                 return FALSE;
  21.         }
  22.         ........
  23. }

4. API 이용(FindWindow)
  1. LPSTR gAppName = "MyApplicationName_20080204";
  2. //Unique 한 이름을 적어준다.
  3.  
  4. int PASCAL WinMain(
  5.         HANDLE hInstance,
  6.         HANDLE hPrevInstance,
  7.         LPSTR lpszCmdLine,
  8.         int nCmdShow)
  9. {
  10.         HWND hWnd;
  11.         MSG    msg;
  12.         WNDCLASS wc;
  13.  
  14.         if (FindWindow(gAppName, NULL))
  15.         {
  16.                 PostQuitMessage(0);
  17.                 return FALSE;
  18.         }
  19.         ........
  20. }

'Coders' 카테고리의 다른 글

[Visual Studio] 2005 상에서 쓰이는 Macro 환경 변수  (0) 2008.03.26
[App] 내 PC에 눈이 내리네...  (0) 2008.02.01
[MSSQL] M$SQL 2000 웃긴다.  (0) 2007.12.27