서비스 프로그램을 작성하다 보면..
간혹 데스크탑과 연동해야 하는 일이 발생한다.

입력없는 콘솔 프로그램 같은 경우는 그냥 서비스에서 바로 수행하면 되지만
입력을 받는 콘솔이나, GUI를 가진 프로그램을 띄워야할 경우는
프로세스 목록에만 나오고.. 깜깜 무소식이다.

일반 응용프로그램에서야 WTSRegisterSessionNotification 함수를 이용하여 아주 쉽게
로그온된 시점을 구할 수 있지만 불행하게도 서비스에서는 사용할 수 없다.


또한 서비스 시작시에 응용 프로그램을 수행시키면, 아직 로그온 되기 전이기때문에
저런 설정을 다 해놓는다 하여도 로그온된 화면에는 아무것도 보이지 않을 수 있다.

1. 꼭 서비스로 관리해야하는가?
2. 입력을 가지는 콘솔이나 GUI를 가졌는가?
3. 서비스 구동시에 시작해야 하는가?
4. 로그온 된 데스크탑에 보여주어야 하는가?

위 사항들을 잘 판단하고 그래도 꼭 필요하다면 다음과 같은 정보를 구해야한다.
1. 서비스로 개발하기
2. 데스크탑과 연동하는 옵션
3. 로그온된 시점 구하기

1. 서비스로 개발하기
위 사항은 이미 자료가 많이 나와있고, 대부분 알려진 자료이므로 그냥 좋은 자료를 찾는다 ^^;

2. 데스크탑과 연동하는 옵션
       첫번째로 가장 쉬운 방법은 서비스 관리자를 이용하는 방법이다.

사용자 삽입 이미지

     그림에서 보이는것 처럼 로그온 설정시에 서비스와 데스크탑 상호 작용 허용에 첵크를
     해줌으로써 아주 간단하게 해결할 수 있다.

     두번째는 서비스를 인스톨할 때, 즉 CreateService 함수를 이용하여 서비스를 설치할 때
     다섯번째 인자에 SERVICE_INTERACTIVE_PROCESS 를 함께 넣어주는 것이다.
     이것은 첫번째 방법을 프로그램적으로 해결하는 것이다.

3. 로그온된 시점 구하기
로그온된 시점을 구하는 방법도 그리 어렵지 않다. 하지만 제약사항이 많아서..
특히나 지금 처리하는 방법은 Windows XP 이상, Windows Server 2003 이상에서만
동작하는 방법이므로, 하위 버전 윈도우를 처리하는 경우에는 해당사항이 없다. -_-;;;
(예전에는 이벤트 로그를 뒤적거려서 처리했었다...)

서비스를 핸들하기 위하여 RegisterServiceCtrlHandler 함수 대신에 좀더 구체적인 정보를
전달해주는 RegisterServiceCtrlHandlerEx 를 이용하는 방법이다.

RegisterServiceCtrlHandlerEx API는 시스템의 세션정보 변화를 감지하는 이벤트인
WM_WTSSESSION_CHANGE 를 처리할 수 있도록 해준다.

SetServiceStatus 에서 SERVICE_STATUS 값의 dwControlsAccepted 값에 꼭
SERVICE_ACCEPT_SESSIONCHANGE 를 함께 넣어주도록 하자.

이렇게 RegisterServiceCtrlHandlerEx 에 전달된 콜백함수에는 다음과 같은 인자가 있다.
DWORD WINAPI HandlerEx(
  [in]                 DWORD dwControl,
  [in]                 DWORD dwEventType,
  [in]                 LPVOID lpEventData,
  [in]                 LPVOID lpContext
);

저기서 첫번째 인자에 SERVICE_CONTROL_SESSIONCHANGE 가 넘어오면 로그온 세션에
무언가 변화가 생긴것이다.

두번째 인자로 어떤 변화가 발생하였는지를 감지할 수 있다. MSDN의 설명을 참고해보면...
Value Meaning

WTS_CONSOLE_CONNECT
0x1

A session was connected to the console terminal.

WTS_CONSOLE_DISCONNECT
0x2

A session was disconnected from the console terminal.

WTS_REMOTE_CONNECT
0x3

A session was connected to the remote terminal.

WTS_REMOTE_DISCONNECT
0x4

A session was disconnected from the remote terminal.

WTS_SESSION_LOGON
0x5

A user has logged on to the session.

WTS_SESSION_LOGOFF
0x6

A user has logged off the session.

WTS_SESSION_LOCK
0x7

A session has been locked.

WTS_SESSION_UNLOCK
0x8

A session has been unlocked.

WTS_SESSION_REMOTE_CONTROL
0x9

A session has changed its remote controlled status. To determine the status, call GetSystemMetrics and check the SM_REMOTECONTROL metric.


그러므로 위시점에서 WTS_SESSION_LOGON 일 경우에 프로그램을 기동시키면 정확하게
로그온된 시점에 프로그램이 구동하게 된다.

이것 때문에 헤맨 시간을 생각하면.. ㅇㅎㅎ ㅠㅠ~~

윈도우즈 서비스로 제작한 프로그램을 서비스에 등록할 경우..
로컬시스템 계정이나 암호를 가진 유저는 잘 등록이 되고
동작도 잘됩니다.

하지만 빈문자열로 암호를 가지지 않은 계정은 서비스가 로그온에 실패하여
서비스가 정상적으로 수행되지 못합니다.

이걸 프로그램적으로 해결하기 위해 백방으로 찾아봤지만..
해결을 못했었는데 이렇게 허무할 수가 ㅠㅠ;

http://support.microsoft.com/kb/303846/ko


오류 메시지: 계정 제한 때문에 로그온할 수 없습니다

기술 자료 ID : 303846
마지막 검토 : 2001년 11월 21일 수요일
수정 : 1.0
이 문서는 이전에 다음 ID로 출판되었음: KR303846

현상

원격 데스크톱 도구를 사용하여 Windows XP 기반 컴퓨터에 연결하려고 하면 아래의 오류 메시지가 나타날 수도 있습니다.
계정 제한 때문에 로그온할 수 없습니다.

위로 가기

원인

연결하는 데 사용한 계정에 암호가 없으면 이러한 문제가 발생할 수 있습니다. 암호가 없는 계정을 사용할 때는 원격 데스크톱 연결을 설정할 수 없습니다.

위로 가기

해결 방법

원격 데스크톱 연결을 설정할 수 있도록 이 문제를 해결하려면 해당 컴퓨터의 콘솔에서 로그온한 다음 해당 사용자 계정에 대해 암호를 설정하십시오.

위로 가기

현재 상태

이것은 의도적으로 설계된 동작입니다.

위로 가기

추가 정보

정책을 사용하여 빈 암호 제한을 해제할 수 있습니다. 이 정책을 찾아서 변경하려면 다음과 같이 하십시오.
1. 시작을 누르고, 실행을 누르고, gpedit.msc를 입력한 다음 확인을 눌러 그룹 정책 편집기를 시작합니다.
2. 컴퓨터 구성\Windows 설정\보안 설정\로컬 정책\보안 옵션\계정: 콘솔 로그온 시 로컬 계정에서 빈 암호 사용 제한을 엽니다.
3. 콘솔 로그온 시 로컬 계정에서 빈 암호 사용 제한을 두 번 누릅니다.
4. 사용 안함을 누른 다음 확인을 누릅니다.
5. 그룹 정책 편집기를 종료합니다.
참고: 기본적으로 이 정책은 사용함으로 설정되어 있습니다.

+ Recent posts