소개
Microsoft® Windows® XP는 Windows 2000 기술 기반의 새 운영 체제입니다. 빠른 사용자 전환은 Windows NT® 프로필의 데이터 구분 기술을 사용하고 사용자 계정 간의 전환을 위한 빠르고 편리한 메커니즘을 제공하는 Windows XP의 새 기능입니다.
NT 프로필을 사용한 데이터 구분
Windows XP는 개인용 시스템입니다. 예를 들면, 각 컴퓨터 사용자가 별도의 Windows 계정을 갖기 때문에 가족 구성원인 아버지, 어머니, 그리고 아들이 계정을 각각 하나씩 가지게 됩니다. 이러한 개별 Windows 계정은 대개 모든 가족 구성원이 하나의 계정을 공유했던 Windows 95 및 Windows 98에서 새롭게 발전된 개념입니다.
이러한 계정은 설치 과정 중에 만드는 것이 좋지만 나중에 제어판을 사용하여 만들 수도 있습니다. 이러한 계정은 각 사용자의 데이터가 구분되는 진정한 의미의 NT 프로필입니다. 기본적으로 이러한 계정은 암호로 보호되지 않지만 사용자는 자신의 계정에 암호를 설정할 수 있습니다.
빠른 사용자 전환 기능
Windows XP는 빠른 사용자 전환 기능을 도입하였습니다. Windows XP에서 사용자는 로그오프할 필요가 없습니다. 대신 사용자 계정은 항상 로그온되고 사용자는 열려 있는 모든 계정 간에 빠르게 전환할 수 있습니다. 예를 들어, 아버지가 회사에서 돌아와 컴퓨터를 사용한다고 가정해 보겠습니다. 아버지가 Microsoft PowerPoint®를 열어 문서 작업을 수행하던 중 아들이 다가와 컴퓨터를 써야 한다고 조릅니다. 아들은 시작 화면에서 자신의 이름을 클릭하고 게임을 시작합니다. 이 과정에서 아버지는 계속 로그온 상태이고, PowerPoint 프레젠테이션은 열려 있으며, 인터넷 연결도 계속 유지됩니다. 아버지는 원할 경우 아들을 로그오프하지 않고 자신의 열려 있는 계정으로 전환할 수 있습니다. 본질적으로 Windows XP를 사용하면 여러 사용자가 동시에 컴퓨터를 사용할 수 있는 것입니다.
Windows XP 시스템은 사용자가 로그온한 상태에서 그대로 두면 실행 중인 모든 응용 프로그램을 계속 유지하면서 시작 화면으로 돌아갑니다. 또한 로그온한 사용자 수, 읽지 않는 전자 메일의 존재 여부, 실행 중인 프로그램 수 등에 대한 정보를 제공하는 알림 메시지가 시작 화면에 나타납니다.
Windows XP Professional의 원격 데스크톱
Windows XP Professional을 사용하면 다른 시스템에서 데이터 및 응용 프로그램을 액세스할 수도 있습니다. 업무용 워크스테이션에서 Windows XP Professional을 사용하면 사용자는 원격 컴퓨터에서 자신의 테스크톱을 액세스할 수 있습니다.
예를 들어, 아버지는 사무실에서 자신의 워크스테이션을 잠금으로 설정하고 집으로 간 다음 사무실 워크스테이션에 연결할 수 있습니다. 가정용 컴퓨터는 사무실 워크스테이션에서 실행 중인 응용 프로그램을 원격으로 제어할 수 있습니다. 아버지는 다시 출근하여 데스크톱의 잠금을 해제하고 사무실에서 중단했던 작업을 집에서 계속 수행할 수 있습니다.
NT 프로필
빠른 사용자 전환 및 원격 데스크톱은 둘 다 터미널 서비스 기술을 사용하고 특별한 변경 없이 대부분의 이전 Microsoft Win32® 응용 프로그램에서 작동합니다. 지금 사용하고 있는 응용 프로그램이 Windows 2000 Logo Certified 제품이거나 Windows 2000의 Application Specification을 따르는 제품인 경우, 응용 프로그램은 Windows XP에서 아무 문제 없이 실행됩니다. 또한 Windows XP 시스템에서 응용 프로그램을 제대로 실행할 수 있게 도와주는 새 메시지를 사용할 수도 있습니다. 빠른 사용자 전환을 활용하는 새로운 방법과 함께 이 메시지는 이 문서에서 나중에 설명하도록 하겠습니다.
NT 프로필 인프라
Windows 2000은 사용자 데이터, 사용자 설정 및 컴퓨터 설정의 상태 구분을 지원하는 기본 인프라를 제공합니다. 이 인프라를 적절하게 사용하는 응용 프로그램은 최종 사용자에게 다음과 같은 이점을 제공합니다.
-
응용 프로그램 및 운영 체제 파일을 백업하지 않고 개별 문서 및 설정을 쉽게 백업할 수 있습니다.
-
여러 사용자가 단일 컴퓨터를 공유하고 각 사용자의 기본 및 일반 설정을 유지 관리할 수 있습니다.
-
여러 컴퓨터에서 작업할 수 있고 특정 컴퓨터에서 다른 컴퓨터의 문서 및 설정을 유지 관리할 수 있습니다.
모든 사용자에 대해 시작 메뉴 항목 작성
시스템에 액세스할 수 있는 모든 사용자가 응용 프로그램을 실행할 수 있게 하려면 모든 사용자 프로필에 해당 응용 프로그램의 시작 메뉴를 만듭니다. 적절한 CSIDL과 함께 SHGetFolderPath를 사용하여 자신의 요구에 맞게 응용 프로그램 데이터를 저장할 수 있습니다. 컴퓨터, 특정 비-사용자, 비-로밍 데이터에 대해서는 CSIDL_COMMON_APPDATA를 사용하십시오.
내 문서 폴더를 사용자 작성 데이터의 기본 저장소로 설정
내 문서 폴더를 기본값으로 설정하려면 매개 변수 없이 Common File Open/Save를 호출합니다. 또는 CSIDL_PERSONAL을 SHGetFolderPath()에 전달하여 내 문서 폴더를 직접 대상으로 지정합니다. 내 문서 폴더는 임시 저장 또는 응용 프로그램 상태 데이터가 아니라 사용자 작성 데이터를 위한 것입니다. 이미징 응용 프로그램의 경우에는 내 문서 대신 내 문서의 하위 항목인 CSIDL_MYPICTURES를 사용하는 것이 좋습니다.
Windows 디렉터리와 같이 사용자 프로필에 사용되지 않는 중앙 위치에서 매핑된 파일을 만들지 마십시오. 임시 파일, 메모리 매핑된 파일 및 문서는 모두 사용자 프로필 디렉터리의 해당 하위 디렉터리에 저장되어야 합니다. API SHGetFolderPathAndSubDir은 사용자를 위해 하위 디렉터리를 만들기 때문에 네임스페이스의 AppData 부분에서 더 쉽게 작업할 수 있게 해 줍니다.
SHGetFolderPath를 사용하여 파일의 해당 저장소 위치를 찾을 수 있습니다. CSIDL_COMMON_APPDATA를 응용 프로그램에 전달하면 응용 프로그램별 데이터의 일반 리포지토리로 사용되는 파일 시스템 디렉터리가 반환됩니다. CSIDL_COMMON_PROGRAMS를 전달하면 모든 사용자 시작 메뉴가 반환됩니다. 사용자는 다른 사용자의 공유 문서에 쓸 수 없으며, 읽기 기능만 가능합니다. 하지만 응용 프로그램으로 인해 CSIDL_COMMON_DOCUMENTS의 응용 프로그램별 하위 디렉터리에서 이 보안 설정이 변경될 수 있습니다. CSIDL_COMMON 파일 폴더에는 보안 문제가 수반됩니다. 제한된 사용자를 비롯하여 모든 사용자에 대해 전체 읽기/쓰기를 허용하려면 기본적으로 ACL 속성을 설정해야 합니다.
임시 파일과 같이 사용자가 바뀔 때 변경해야 하는 데이터에 대해서는 CSIDL_LOCAL_APPDATA를 사용해야 합니다.
정확한 응용 프로그램 데이터 분류 및 저장
사용자 기본 설정, 응용 프로그램 상태 및 임시 파일과 같은 응용 프로그램 데이터는 다음 분류에 따라 응용 프로그램 데이터 폴더나 레지스트리에 저장되어야 합니다.
-
사용자별 로밍 데이터
-
사용자별 비로밍 데이터
-
사용자마다 다르지 않고 비로밍인 시스템별 데이터
적절한 "액세스 거부" 메시지 사용
다음과 같이 액세스를 적절하게 거부할 수 있습니다.
-
우선 작업을 수행할 수 없도록 설정합니다.
이 방법은 제어판의 시스템 설정에서 수행할 수 있습니다. 사용자는 시스템 전체 환경 변수를 설정할 수 없지만 고유한 환경 변수를 설정할 수 있습니다. 따라서 사용자가 이 애플릿을 실행하면 시스템 전체 환경 변수 옵션은 "회색으로" 표시됩니다. 관리자가 이 애플릿을 실행하면 시스템 전체 환경 변수를 수정할 수 있습니다.
-
해당 오류 메시지를 표시합니다. 예를 들면 다음과 같습니다.
-
"이 작업을 수행하려면 관리자이어야 합니다."
-
"현재 권한으로는 이 개체 속성의 보기 기능만 사용할 수 있습니다."
-
"이 작업을 수행하려면 xyz 권한이 있어야 합니다."
-
"이 작업을 수행하려면 abc.xyz에 대한 쓰기 권한이 있어야 합니다."
-
레지스트리 사용
응용 프로그램은 읽기/쓰기 응용 프로그램 데이터 및 구성 파일 저장을 위해 레지스트리를 사용할 수도 있습니다.
HKCU 레지스트리는 작은 데이터(64KB 미만)의 저장 및 사용자별 정책 설정에 적당합니다.
기본적으로 일반 사용자가 전체 HKLM 트리에 대한 읽기 전용 권한을 가지므로 런타임 도중 HKLM에 대해 쓰기 작업을 하면 안됩니다. 또한 HKLM은 로밍을 지원하지 않습니다.
큰 파일 기반 데이터(64KB 이상)는 응용 프로그램 데이터 폴더에 두어야 합니다. 예를 들어, Internet Explorer의 임시 인터넷 캐시는 레지스트리가 아니라 사용자 프로필 내에 저장됩니다.
설치 시 응용 프로그램은 HKCU 및 HKLM에서 전체 용량이 128KB를 초과하여 저장하면 안됩니다. 단, HK 클래스 루트는 제외된다는 점에 주의하십시오.
자세한 내용은 http://msdn.microsoft.com/certification/
에서 Designed for Windows 2000 Logo를 참조하십시오.
Windows 세션 전환
세션 전환 이벤트 수신 대기
일반적으로 응용 프로그램은 세션 전환이 발생할 때 알림을 받을 필요가 없습니다. 그러나 세션 전환이 언제 발생하는지 알아야 할 경우 응용 프로그램은 세션 전환 알림을 등록할 수 있습니다. 직렬 포트나 컴퓨터의 다른 공유 리소스를 액세스하는 응용 프로그램에서는 이것을 확인해야 합니다. 알림을 등록하려면 Wtsapi32.h에서 찾을 수 있는 다음 함수를 사용합니다.
BOOL WINAPI
WTSRegisterSessionNotification(
HWND hWnd, // Window handle
DWORD dwFlags // Flags
);
등록된 HWND는 WM_WTSSESSION_CHANGE 메시지를 받습니다.
dwFlags에서 다음을 지정할 수 있습니다.
-
NOTIFY_FOR_THIS_SESSION. 해당 창이 속한 세션에 영향을 미치는 세션 변경 이벤트에 대해서만 알림을 받습니다.
-
NOTIFY_FOR_ALL_SESSIONS. 모든 세션 변경 이벤트에 대해 알림을 받습니다.
세션에서 발생하는 동작은 다음 플래그 중 하나를 포함하는 wParam 코드에서 볼 수 있습니다.
WTS_CONSOLE_CONNECT WTS_CONSOLE_DISCONNECT WTS_REMOTE_CONNECT WTS_REMOTE_DISCONNECT WTS_SESSION_LOGON WTS_SESSION_LOGOFF WTS_SESSION_LOCK WTS_SESSION_UNLOCK
lParam에는 영향을 받은 세션의 sessionId가 포함되어 있습니다.
이러한 알림이 더 이상 필요하지 않거나 종료되는 프로세스는 다음을 호출하여 알림의 등록을 취소해야 합니다.
BOOL WINAPI WTSUnRegisterSesssionNotification( HWND hWnd // window handle. );
WTSRegisterSessionNotification에 전달된 HWND 값은 개수가 계산된 참조이므로 WTSRegisterSessionNotification을 호출한 횟수만큼 WTSUnRegisterSessionNotification을 호출해야 합니다.
응용 프로그램은 WTS_CONSOLE_CONNECT, WTS_CONSOLE_DISCONNECT, WTS_REMOTE_CONNECT 및 WTS_REMOTE_DISCONNECT 메시지를 사용하여 자신의 상태를 추적하고 콘솔별 리소스를 해제 및 획득할 수 있습니다.
응용 프로그램 버전을 하나만 실행
대부분의 응용 프로그램에서는 응용 프로그램 인스턴스가 하나만 실행 중이어야 합니다. Windows XP에서는 여러 방법으로 이렇게 할 수 있습니다.
FindWindow 또는 FindWindowEx를 사용하여 응용 프로그램이 연 창을 검색합니다. 창이 이미 열려 있을 경우에는 이러한 명령을 사용하여 응용 프로그램이 열려 있는지 확인합니다.
응용 프로그램을 열 때 Mutex 또는 세마포를 만들고, 응용 프로그램 종료할 때 이를 닫습니다. 네임스페이스는 각 데스크톱에 따라 구분되므로 고유한 Mutex 또는 세마포 목록이 만들어집니다.
시스템 서비스 상호 작용
프로그램적 관점에서 볼 때 다음과 같은 몇 가지 경우를 고려해야 합니다.
-
서버 프로세스가 클라이언트 프로세스로부터 직접 요청을 받습니다.
메시지는 대개 LPC 또는 RPC를 통해 전송되며 어떤 경우든 클라이언트 토큰을 얻기 위한 API가 존재합니다. 이 경우에는 WTSQueryUserToken을 사용합니다. 클라이언트 토큰을 획득하면 서버는 advapi32!CreateProcessAsUser를 호출할 수 있으며, 결과적으로 클라이언트 사용자 토큰이 세션 태그를 갖고 있다는 가정 하에 정확한 윈도우 스테이션에서 프로세스가 수행됩니다.
-
서버 프로세스는 일부 알림 양식을 받고 현재 사용자 컨텍스트에서 사용자 인터페이스(UI)를 표시해야 합니다.
서버는 현재 사용자의 토큰을 가져야 합니다. 그런 다음 서비스는 서버 프로세스가 TS에 제공할 수 있는 주어진 세션 식별자에 대해 토큰을 서버 프로세스(TS에 대한 클라이언트 프로세스)로 복제해야 합니다. 이 경우, 서버 프로세스는 SYSTEM으로 실행 중이어야 합니다.
-
서버 프로세스는 일부 알림 양식을 받고 UI를 표시해야 하지만, 현재 사용자 컨텍스트에 있을 필요는 없습니다.
이 경우, 서버 프로세스는 기본 프로세스 토큰을 복제할 수 있고 세션 식별자를 현재 세션 식별자로 변경할 수 있습니다. 현재 세션 식별자는 WTSGetActiveConsoleSessionID를 사용하여 얻을 수 있습니다.
Windows XP Professional에서 원격 데스크톱 기능이 추가된 후에는 응용 프로그램에 필요 이상의 대역폭을 사용해서는 안됩니다. 데스크톱이 원격으로 연결된 경우 응용 프로그램은 광범위한 화면 드로잉 및 애니메이션 효과를 피해야 합니다. 사용자 데스크톱은 원격 및 콘솔 간에 동적으로 전환될 수 있습니다. 응용 프로그램은 WTS_REMOTE_CONNECT 및 WTS_REMOTE_DISCONNECT 메시지를 사용하여 원격 v/s 로컬 연결 상태와 동기화되어야 합니다. 또한 언제든지 GetSystemMetrics(SM_REMOTESESSION)를 호출하여 세션이 원격 또는 콘솔인지 여부를 확인할 수 있습니다.
세션 모니커 및 IUserNotification을 사용하여 COM 응용 프로그램을 활성 사용자 세션의 데스크톱에서 실행할 수 있습니다. 세션 모니커는 원격으로도 작동하는 IMoniker::BindToObject를 통해 사용할 수 있습니다. BindToObject의 경우, 아래에 설명된 것처럼 전체 구문을 사용해야 합니다.
HRESULT CoCreateOnConsoleWithBindToObject(REFCLSID rclsid, REFIID riid, void** ppv)
{
*ppv = NULL;
IBindCtx* pbc;
HRESULT hr = CreateBindCtx(0, &pbc);
if (SUCCEEDED(hr))
{
WCHAR sz[128], szClsid[64];
StringFromGUID2(rclsid, szClsid, ARRAYSIZE(szClsid));
LPWSTR psz = szClsid + 1; // skip "{"
while (*psz != L'}')
psz++;
*psz = NULL;
lstrcpyW(sz, L"Session:Console!clsid:");
lstrcatW(sz, &szClsid[1]);
// Parse the name and get a moniker:
ULONG ulEaten;
IMoniker* pmk;
hr = MkParseDisplayName(pbc, sz, &ulEaten, &pmk);
if (SUCCEEDED(hr))
{
IClassFactory *pcf;
hr = pmk->BindToObject(pbc, NULL, IID_PPV_ARG(IClassFactory, &pcf));
if (SUCCEEDED(hr))
{
hr = pcf->CreateInstance(NULL, riid, ppv);
pcf->Release();
}
pmk->Release();
}
pbc->Release();
}
return hr;
}
이 코드는 예제이며, 복사하여 붙여넣을 경우 컴파일되지 않는다는 것에 주의하십시오.
지문 판독기와 같은 생체 인증에 사용할 소프트웨어를 작성하면서 빠른 사용자 전환 기능을 사용하려면, fusqa@microsoft.com으로 전자 메일을 보내 특수 DLL의 사용 허가를 받으십시오.
네트워크 연결
빠른 사용자 전환을 사용하면 실행 중인 프로그램을 그대로 두고 다른 사용자의 로그인을 허용할 수 있습니다. 또한 특정 사용자에서 다른 사용자로 전환할 때 인터넷 연결을 계속 유지할 수 있습니다. 실행 중인 응용 프로그램에 따라 독립 소프트웨어 공급업체(ISV)는 연결을 종료하거나 그대로 둘 수 있습니다.
항상 활성화 상태인 연결
항상 활성화 상태를 유지하는 연결은 빠른 사용자 전환에 의해 영향을 받지 않습니다. 일반적으로 xDSL 또는 케이블 모뎀 연결이 여기에 해당하며, 무선 네트워킹 연결도 항상 활성화 상태인 연결로 볼 수 있습니다.
사용자 초기화 연결
사용자 초기화 연결로는 가상 개인 네트워킹, PPPoX 및 원격 액세스 서버(RAS) 전화 접속 연결을 들 수 있습니다. 모든 사용자 초기화 연결은 시작 화면이 표시될 때 활성화 상태를 유지합니다. 대부분의 경우, 사용자 A가 네트워크 연결을 초기화한 다음 사용자 B가 활성 세션으로 시작되면 사용자 A의 연결은 끊어집니다.
항상 활성화 상태인 사용자 초기화 연결
일부 사용자 초기화 네트워크 연결은 특정 세션에서 다른 세션으로 빠른 사용자 전환이 이루어질 때 활성 상태를 유지할 수 있습니다. 다음과 같은 경우에 네트워크 연결이 유지됩니다.
-
연결을 모든 사용자가 사용할 수 있는 경우
-
연결 자격 증명이 저장된 경우
-
Home Edition에서 새 연결 마법사로 만든 모든 연결을 암시적으로 모든 사용자가 사용할 수 있는 경우
예외
사용자가 네트워크 연결을 초기화한 다음 로그오프하는 경우, 즉 사용자 전환이 없는 경우에는 네트워크 연결을 끊어집니다.
인터넷 연결 공유(ICS)를 사용하도록 설정된 연결은 사용자가 Windows 세션을 전환하거나 모든 사용자가 시스템에서 로그오프한 경우에도 연결 상태를 유지합니다. ICS 연결은 수동으로 끊거나 제한 시간 이후 자동으로 끊을 수 있습니다.
참고
현재 RAS API는 관리자 권한으로 사용자 컨텍스트에서 호출될 때 기본적으로 모든 사용자 연결을 만듭니다.
모든 사용자는 모든 사용자/전역 연결을 종료할 수 있습니다.
모든 세션에서 활성 연결은 아이콘으로 알림 영역에 표시됩니다.
모든 사용자 연결이 아니고 전역적으로 저장된 자격 증명이 있는 모든 연결은 사용자 전환 시 끊어집니다.
사용자 인터페이스 변경
작업 그룹에 추가된 Windows XP Home Edition과 Professional의 경우, 모든 사용자/전역(all-user/global-global) 연결 옵션이 기본으로 선택됩니다.
RAS API 변경
다음 플래그가 정의되었습니다.
#define RASCF_AllUsers 0x00000001 #define RASCF_GlobalCreds 0x00000002
rasconnw 구조는 RASCONNW.dwSessionId 및 RASCONNW.dwFlags를 포함하도록 확장되었습니다.
-
RASCONNW.dwSessionId: 연결을 만든 사용자의 로그온 세션 ID입니다.
-
RASCF_AllUsers: 이 플래그는 연결에 사용되는 항목이 모든 사용자 연결인 경우에 설정됩니다.
-
RASCF_GlobalCreds: 이 플래그는 사용된 자격 증명이 RasSetCredentials(RASCM_DefaultCreds)로 설정된 자격 증명과 같은 기본 자격 증명인 경우에 설정됩니다.
또한 dnssuffix의 설정을 프로그램적으로 용이하게 하기 위해 szDnsSuffix 필드가 RASENTRY 구조에 추가되었습니다.
RASCONNW
{
DWORD dwSize;
HRASCONN hrasconn;
WCHAR szEntryName[ RAS_MaxEntryName + 1 ];
#if (WINVER >= 0x400)
WCHAR szDeviceType[ RAS_MaxDeviceType + 1 ];
WCHAR szDeviceName[ RAS_MaxDeviceName + 1 ];
#endif
#if (WINVER >= 0x401)
WCHAR szPhonebook [ MAX_PATH ];
DWORD dwSubEntry;
#endif
#if (WINVER >= 0x500)
GUID guidEntry;
#endif
#if (WINVER >= 0x501)
DWORD dwSessionId;
DWORD dwFlags;
#endif
};
이 코드는 예제이며, 복사하여 붙여넣을 경우 컴파일되지 않는다는 것에 주의하십시오.
전자 메일 알림
빠른 사용자 전환을 사용할 경우, 로그온한 사용자의 읽지 않은 전자 메일 수를 시작 로그온 화면에 표시할 수 있습니다. 시작 화면의 사용자 이름 아래에 읽지 않은 메일 수를 나타내는 하이퍼링크가 나타납니다. 이 하이퍼링크를 클릭하면 메일을 받은 계정을 볼 수 있습니다. 예를 들어, Bob이라는 사용자의 읽지 않은 전자 메일 수가 세 개라고 가정해 보겠습니다. 이 경우, 하이퍼링크를 클릭하면 Bob@MSN.com(2) 및 Bob@hotmail.com(1)이 표시됩니다. 이러한 작업을 위한 API인 SHGetUnreadMailCount 및 SHSetUnreadMailCount는 shellapi.h에 있습니다. 읽지 않은 전자 메일이 설정되면 날짜 스탬프도 함께 표시되며, 읽지 않은 전자 메일 항목이 2주를 경과하면 시작 화면은 해당 항목을 무시합니다.
터미널 서비스
일반 터미널 서비스 연결이 끊기면 RAS 및 FUS 전화 접속 아이콘이 자동으로 없어집니다.
OOBE(Out Of Box Experience) 도중에 사용자 계정 작성
단일 Windows 사용자 계정에서 여러 개의 인터넷 서비스 공급자(ISP) 계정을 만들면 안됩니다. 모든 Windows XP 사용자는 자신의 NT 프로필에서 고유한 ISP 계정을 가져야 데이터 구분, 개인 정보 보호 및 보안이 쉬워집니다. ISP 클라이언트 소프트웨어 또는 프로필을 가진 다른 모든 응용 프로그램은 자격 증명을 해당 사용자의 계정에 저장해야 합니다. 계정과 연관된 ISP 자격 증명 집합이 하나만 있을 경우, 사용자가 소프트웨어를 실행하면 응용 프로그램은 사용자를 확인할 필요가 없습니다. 마찬가지로 Windows에 의해 이미 확인 및 인증되었으므로 사용자에게 다시 확인 작업을 수행하라고 요청할 필요가 없습니다.
Windows XP를 사용하면 ISV는 OOBE(Out Of Box Experience) 도중에 별도의 사용자 계정을 만들 수 있습니다. 그러나 사용자 계정 작성 및 삭제는 관리할 사용자에게 맡기는 것이 좋습니다. 여러 응용 프로그램이 각각 사용자 계정을 개별적으로 만들 경우, 과도한 사용자 계정으로 인해 혼돈이 생길 수 있기 때문입니다. 사용자 계정을 반드시 만들어야 할 경우에는 계정을 만들기 전에 사용자가 그 사실을 알고 있는지 확인합니다. 그런 다음 아래에 설명된 것처럼 계정을 만듭니다.
Window의 NT 프로필을 만들기 전에 ISV는 응용 프로그램에 필요한 프로필을 만드는 설치 응용 프로그램을 실행할 수 있습니다. 예를 들어, 이 설치 응용 프로그램은 Bob@MSN.com을 만들 수 있습니다. 이 설치 응용 프로그램은 응용 프로그램 프로필 하나를 Windows 계정 하나와 연관시킬 수 있습니다. Windows XP OOBE 화면에서는 계정 이름을 입력하는 메시지가 나타납니다. 각 사용자의 편집 상자 옆에는 각 계정과 연관된 ISP 계정을 나타내는 편집 불가능한 정적 텍스트가 있습니다. 다음 예제에서 첫 번째 사용자는 편집 불가능한 정적 텍스트로 Bob@MSN.com을 가집니다. OOBE는 첫 번째 사용자의 프로필 이름을 Profilename=<string>에 기록하므로 설치 응용 프로그램은 레지스트리의 특정 키에서 응용 프로그램 프로필 하나를 Windows 사용자 계정 하나와 연관시킬 수 있습니다. 또한 ISP 계정 하나가 Windows 계정 하나와 연관되도록 OOBE 키 값을 업그레이드 전에 설정할 수 있습니다. 이렇게 하면 Windows Millennium와 같은 NT 프로필 기반이 아닌 운영 체제에서 업그레이드할 수 있습니다.
OOBE에서 ISP를 등록하는 도중에 ISP 응용 프로그램은 기본값이 ISP 이름(예: MSN)인 ISPAccount=<string>이라는 새 키를 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Setup\OOBE에 기록합니다. 새 키에서 ISP 응용 프로그램은 기본값이 사용자의 ISP 계정(예: Bob@MSN.com)인 ISPUserName=<string>을 기록합니다. 또한 ISP가 ISPUserFriendlyName="<friendly name>" 값을 추가할 경우 OOBE는 작성할 첫 번째 프로필의 기본값으로 이 이름을 제안합니다.
OOBE에서 Windows 계정을 만드는 동안 OOBE는 ISPUserName에서 읽어 계정 작성 편집 상자 옆에 있는 사용자 인터페이스에 편집 불가능한 텍스트 값을 씁니다. 예를 들어, 첫 번째 사용자는 편집 상자 옆에 편집 불가능한 정적 텍스트로 Bob@MSN.com을 가집니다. 그런 다음 사용자는 Windows 계정 이름에 사용할 이름을 선택할 수 있습니다.
OOBE는 첫 번째 계정 작성 편집 상자에서 읽은 Windows 계정 이름을 Profilename=<string>에 씁니다. 예를 들어, 첫 번째 사용자의 계정 이름은 Bob Smith가 될 수 있습니다. 이 사용자가 로그온하면 ISP 응용 프로그램은 실행되고 위 키를 검색합니다. 현재 Windows 사용자가 "Profilename"과 일치하면 ISP 응용 프로그램은 ISPUserName과 Profilename을 연관시킵니다.
사용자 프로필 작성, 열거 및 로드를 위한 API는 MSDN 온라인의 Platform SDK에 있는 "Whistler Beta 1 Edition"에 모두 설명되어 있습니다.
다음 예제 코드는 계정을 사용자 계정으로 만듭니다. 사용자가 관리자가 되기를 원할 경우에는 "사용자(Users)" 대신 "관리자(Administrators)"를 지정하여 NetLocalGroupAddMembers를 다시 사용합니다. 아래의 도메인 필드는 시스템 이름을 포함할 수 있지만, 여기서는 ""로 두어도 충분합니다.
STDMETHODIMP CreateUserAccount(BSTR bstrLoginName)
{
HRESULT hr;
hr = E_FAIL;
if ( bstrLoginName && *bstrLoginName )
{
NET_API_STATUS nasRet;
USER_INFO_1 usri1 = {0};
usri1.usri1_name = bstrLoginName;
usri1.usri1_password = TEXT("");
usri1.usri1_flags = UF_NORMAL_ACCOUNT |
UF_SCRIPT | UF_PASSWD_NOTREQD | UF_DONT_EXPIRE_PASSWD;
usri1.usri1_priv = USER_PRIV_USER;
nasRet = NetUserAdd(NULL, // local computer
1, // structure level
(LPBYTE)&usri1, // user infomarmation
NULL); // don't care
if ( nasRet == NERR_Success )
{
TCHAR szDomainAndName[256];
LOCALGROUP_MEMBERS_INFO_3 lgrmi3;
PLOCALGROUP_INFO_0 plgi0;
wnsprintf(szDomainAndName,
ARRAYSIZE(szDomainAndName),
TEXT("%s\\%s"),
_szDomain, /// this would be the machine name
bstrLoginName);
lgrmi3.lgrmi3_domainandname = szDomainAndName;
// by default newly created accounts will be user accounts
nasRet = NetLocalGroupAddMembers(
NULL,
TEXT("Users"),
3,
(LPBYTE)&lgrmi3,
1);
}
hr = HRESULT_FROM_WIN32(nasRet);
}
else
{
hr = E_INVALIDARG;
}
return hr;
}
이 코드는 예제이며, 복사하여 붙여넣을 경우 컴파일되지 않는다는 것에 주의하십시오.
이 코드는 계정을 만들지만 사용자가 처음 로그온할 때까지 프로필은 만들어지지 않습니다. LogonUser를 호출하여 프로필 작성을 강제로 할 수 있지만 또는 프로필 작성을 직접 할 수 있지만 성능이 현저하게 저하됩니다.
사용자 열거
dwPreferredSize = (sizeof(NET_DISPLAY_USER) + (3 * UNLEN) * s_iMaximumUserCount); pNDU = NULL; lError = NetQueryDisplayInformation(NULL, // NULL means LocalMachine 1, // query User information 0, // starting with the first user s_iMaximumUserCount, // return a max of 100 users dwPreferredSize, // preferred buffer size &dwEntriesRead, reinterpret_cast<void**>(&pNDU));
필수 호출 코드
(NET_API_STATUS)NetApiBufferFree(pNDU);
다른 사용자 레지스트리에 대해 읽기/쓰기 작업을 하려면 RegLoadKey 및 RegUnloadKey를 사용하여 하이브를 로드합니다. 작업이 끝나면 이 키를 언로드해야 한다는 것에 주의하십시오.



