본문 바로가기

Programming/MFC

시스템의 종료/재부팅/로그오프 (Shutdown/Rebooting/Logooff)

출처 꿈 따러 가세 | 키사
원문 http://blog.naver.com/kisatsg/20005912469


<!--title & PF logo-->

시스템의 종료/재부팅/로그오프 (Shutdown/Rebooting/Logoff)


사용자 삽입 이미지
MFC 인덱스
사용자 삽입 이미지
윈도우즈 시스템 인덱스

사용자 삽입 이미지

<!--contents-->목차
  1. 윈도우즈 시스템의 셧다운
  2. 셧다운 관련 API 함수
  3. 사용 예제
  4. 윈도우즈 NT에서는...
  5. 기타

1. 윈도우즈 시스템의 셧다운
윈도우즈에서 시스템을 셧다운 시키는 방법은 2가지이다. 그냥 종료시키는 것과 종료후 다시 시작하는 방법이 그것이다. 그 외에 현재 사용자를 로그오프 시키는 방법이 있지만 이는 시스템의 종료와는 상관없이 (즉, 시스템은 종료되지 않은 채) 처음의 로그온 상태로 돌아가 새로운 사용자로 로그인하기 위한 방법만을 제공한다.

[그림1]은 윈도우즈 95의 시작메뉴에서 '시스템 종료' 메뉴를 실행했을때 사용자가 종료방법을 결정하도록 인도하는 대화상자의 모습이다.

▼ [그림1] 시스템 종료 대화상자

사용자 삽입 이미지

① 시스템 종료: 컴퓨터의 전원을 끌 수 있도록 시스템을 안전하게 종료시킴.

② 시스템 재시작: 시스템을 종료하고 다시 시작한다.

③ MS-DOS 모드에서 시스템 재시작: 윈도우즈를 종료하고 DOS 프롬프트를 뛰운다.

④ 모든 프로그램을 종료하고 다른 사용자 이름으로 로그온: 현재 사용자가 실행하던 모든 응용프로그램을 종료하고 새로운 사용자 모드로 윈도우즈를 시작한다.

▼ [그림2] 시스템 로그-온 대화상자
사용자 삽입 이미지

▼ [그림3] 제어판의 사용자 설정창

사용자 삽입 이미지

'④'의 경우 윈도우즈가 설치된 PC를 혼자 사용할 경우 나타나지 않을수도 있는 옵션이다.

윈도우즈 시스템은 비록 한 대의 컴퓨터에 설치되었더라도 여러명의 사용자가 각각 설정값을 달리하여 자신만의 환경을 만들어 사용할 수 있다.

만약 그렇게 되었다면 윈도우즈는 처음 시동할 때 또는 새로운 사용자 모드로 실행하기 위해 로그오프할 때 [그림2]와 같은 대화상자를 보여주고 입력받은 사용자가 설정해 놓은 환경으로 초기화를 해준다.

만약, 윈도우즈를 설치할 때 특별히 사용자를 지정해 두지 않은 경우라면제어판의 '사용자'프로그램을 실행하여 새로운 사용자의 ID와 암호를 등록할 수 있다.
[그림3]은 사용자 설정창의 모습이다.


2. 셧다운 관련 API 함수
윈도우즈를 종료하거나 현재 사용자를 로그오프 시키기 위해 다음과 같은 Win32 API 함수들이 사용된다.

시스템 셧다운 함수들
BOOL ExitWindows( DWORD dwReserved, UINT uReserved );// 2개의 파라메터 모두 예약된 값으로 '0'을 주어야 함.BOOL ExitWindowsEx( UINT uFlags, DWORD dwReserved );// uFlags 파라메터는 셧다운 옵션상수.// dwReserved 파라메터는 예약된 값으로 '0'을 주어야 함.

ExitWindows는 새로운 사용자로 로그온 할 수 있도록 현재 사용자를 로그오프 시킨다. 이 과정이 진행되는 동안 실행중인 모든 응용 프로그램은 종료되며 다른 응용 프로그램을 실행시킬 수 없게된다.

ExitWindowsEx는 다양한 셧다운 작업을 지시할 수 있는데 첫번째 파라메터로 다음과 같은 값들이 사용된다.

  • EWX_LOGOFF: 현재 사용자를 로그오프시키고 새로운 사용자가 로그온 할 수 있도록 한다.
  • EWX_SHUTDOWN: 시스템을 종료시킨다.
  • EWX_REBOOT: 시스템을 종료한 후, 다시 부팅한다.
  • EWX_POWEROFF: 시스템을 종료한 후, 시스템이 전원을 끄는 기능을 가지고 있을경우 전원을 차단한다.

이상의 옵션들은 추가적으로 다음 상수들과 함께 사용될 수 있다.

  • EWX_FORCE: 현재 실행중인 응용 프로그램들을 강제로 종료시킨다.
  • EWX_FORCEIFHUNG: 윈도우즈 NT 5.0 이후 버전에서만 사용.

두 함수 모두 실행중인 모든 응용프로그램들에 대해WM_QUERYENDSESSION메시지를 보내게 된다. 주의할 점은 윈도우즈 NT의 경우엔 종료함수를 호출한 응용 프로그램 자신도 이 메시지를 받지만 윈도우즈 95는 그렇지 않다는 것이다. 따라서 윈도우즈 95라면 종료함수를 호출할때 자신의 프로그램은 스스로 종료시켜야 한다. (어차피 종료되는 거라면 상관없지만 단지 로그오프만 시킬경우엔 로그온 대화창이 떴을 때까지 그대로 남아있게 된다.)

WM_QUERYENDSESSION 메시지를 받은 각 응용 프로그램들은 편집중인 데이터의 저장과 같은 적절한 조치를 취해야 하며 윈도우즈가 종료되어도 좋다면 'TRUE'를 반환하게 된다. 만약 어느 한 프로그램이라도 WM_QUERYENDSESSION 메시지에 대해 'FALSE'를 리턴했다면 윈도우즈는 종료되지 않는다.

반면EWX_FORCE를 지정할 경우엔 WM_QUERYENDSESSION 메시지를 보내지 않는다. 즉, 실행중인 응용 프로그램에게 종료해도 되는가를 물어보지 않고 강제적으로 시스템을 종료하게 한다. 따라서 EWX_FORCE의 사용은 수정중이던 데이터를 잃어버리게 되므로 신중해야 한다.

참고: WM_QUERYENDSESSION 메시지의 처리
MFC에는 이 메시지를 처리하는 CWnd::OnQueryEndSession 핸들러 함수가 있다. 따라서 이 메시지 핸들러를 작성하고 프로그램이 종료되기 전에 반드시 해야할 일들을 정의해 주면 된다.
그러나 프로그래머의 특별한 코딩이 없더라도 수정중인 문서의 저장과 같은 작업은 이루어진다. WM_QUERYENDSESSION 메시지를 받을때 MFC 프레임워크의 내부에서는 CFrameWnd::OnQueryEndSession 이 호출되고 거기서 CWinApp::SaveAllModified 함수를 호출하는 식으로 수정된 문서의 저장이 처리된다. 따라서 문서저장과 같은 작업을 코딩해야 한다면 WM_QUERYENDSESSION 메시지 핸들러 보다 CWinApp::SaveAllModified 함수를 오버라이드하여 처리하는게 좋을 것이다.


3. 사용 예제
다음은 시스템을 종료시키는 명령을 메인 프레임에서 처리하는 예이다. 강제로 종료할 것인가는 별도의 체크박스나 체크메뉴를 사용하여 입력받는 것으로 가정한다.

시스템을 종료시키는 코드의 예
// m_bForce 변수는 강제로 종료시킬것인지, 아니면 모든 프로그램에게// 시스템을 종료해도 되는가를 물어볼 것인지를 결정하기 위해 사용한다.// 로그오프 명령의 실행void CMainFrame::OnLogoff() {   UINT fuOptions = EWX_LOGOFF;   if ( m_bForce ) fuOptions |= EWX_FORCE;   ExitWindowsEx( fuOptions, 0 );     // 시스템 종료명령   SendMessage( WM_CLOSE, 0, 0 );     // Win95라면 자신도 종료해야 함.}// 시스템 종료의 실행void CMainFrame::OnShutdown() {   UINT fuOptions = EWX_SHUTDOWN;   if ( m_bForce ) fuOptions |= EWX_FORCE;   ExitWindowsEx( fuOptions, 0 );   SendMessage( WM_CLOSE, 0, 0 );}// 시스템 재부팅의 실행void CMainFrame::OnReboot() {   UINT fuOptions = EWX_REBOOT;   if ( m_bForce ) fuOptions |= EWX_FORCE;   ExitWindowsEx( fuOptions, 0 );   SendMessage( WM_CLOSE, 0, 0 );}// 윈도우즈 NT 라면 ExitWindowEx를 호출한 프로그램의 WM_QUERYENDSESSION 메시지 핸들러에서// 다음처럼 한 번 더 실행을 확인할 수 있다.BOOL CMainFrame::OnQueryEndSession() {   if (!CFrameWnd::OnQueryEndSession()) return FALSE;   if ( IDYES == MessageBox( "시스템을 종료해도 될까요?", "시스템 종료", MB_YESNO ))      return TRUE;   else      return FALSE;      // 'FALSE'의 리턴은 WM_QUERYENDSESSION 메시지의 처리를 중지시킨다.}// ExitWindows 함수의 이용void CMainFrame::OnSimple() {   ExitWindows( 0, 0 );   // 이것은 다음과 동일하다.   // ExitWindowsEx( EWX_LOGOFF, 0 );}

EWX_FORCE 플래그를 테스트할 땐 간단히 메모장 프로그램을 이용하기 바란다. 뭔가 써놓고 저장하지 않은 상태에서 시스템을 종료해 보면 어떻게 다른지를 알 수 있다.


4. 윈도우즈 NT에서는...
시스템을 로그오프시키는 것 이외의 작업을 윈도우즈 NT에서 실행할 경우엔 ExitWindowsEx를 호출하는 프로그램이SE_SHUTDOWN_NAME권한을 가져야 한다. 이것에 대해서는 다음 기회로 설명을 미뤄야 하겠지만 (저도 아직 잘 몰라용~) 그 권한을 획득하려면 어떻게 해야 하는가는 알려줄 수 있다.
다음은 VC++ 온라인 도움말에서 따온 것이다.

윈도우즈 NT에서 셧다운 권한 얻기
HANDLE hToken; TOKEN_PRIVILEGES tkp;  // Get a token for this process.  if ( !OpenProcessToken( GetCurrentProcess(),          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))    error("OpenProcessToken"); // Get the LUID for the shutdown privilege. LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid); tkp.PrivilegeCount = 1;  // one privilege to set    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // Get the shutdown privilege for this process. AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0); // Cannot test the return value of AdjustTokenPrivileges. if (GetLastError() != ERROR_SUCCESS)    error("AdjustTokenPrivileges"); // Shut down the system and force all applications to close. if (!ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE, 0))    error("ExitWindowsEx");


5. 기타
시스템을 종료하고 다시 부팅하는 수단은 응용 프로그램 설치작업시 많이 이용된다. 프로그램의 복사와 함께 시스템 설정값을 변경했다면 그 값들을 다시 읽어들여야 하기 때문이다.

시스템을 재부팅한 후에도 계속 후속 설치작업이 이루어져야 한다면 특별한 조치를 취해 두어야 한다. 재부팅되는 순간엔 셧다운 되기 전에 어떤 일이 있었는지를 시스템이 알 수는 없지 않은가?

자세한 방법은 딸려서 (그것에 관한 지식이...) 설명할 순 없지만 한 가지 힌트는 생각할 수 있다. 후속작업을 실행하는 프로그램을 윈도우즈 시작메뉴에 넣어두던가 아니면 윈도우즈 디렉토리에 있는win.ini파일에 기록해 두는 것이다.

win.ini 파일을 열어보면 'windows' 섹션이 있고 거기에 'run' 이라는 키가 존재한다. 그런 키가 없다면 여러분이 윈도우즈 시작시 실행할 프로그램 실행파일명과 함께 직접 적어두면 된다. 다음처럼...

[windows]
run=c:\NewProgram\setup.exe

어떻게 기록하는가는 알죠? 모르면 자료실의 '레지스트리 & INI' 항목을 뒤져볼 것.

*** 마지막으로
시스템을 종료한 뒤에 도스 프롬프트로 떨어지게 하는 방법을 공장장은 아직 모른다. 하긴 기어이 알고싶은 맘도 없다. 어차피 도스란 놈은 곧 윈도우즈와는 완전히 결별할 운명이라는 것이 가장 큰 이유이고 두번째 이유는 시스템 셧다운 프로그램의 테스트보다 더 짜증나는 작업은 없기 때문이다.
한 번 생각해 봐유. 윈도우즈가 뭐, TV처럼 그냥 '똑' 하면 '딱'하고 켜지남? 그런걸 껏다켰다 반복하고 앉아 있자니, 누구라도 열받을 껄! (이거 누가 부탁했어? ^^)

--fromhttp://www.bame.pe.kr/oldpf/ref/mfc/system/system-001.html