'CoInitialize'에 해당되는 글 1

  1. 2008.12.01 WMI를 이용하여 PC 제조번호 가져오기 2

WMI는 은근히 재미있는 주제입니다. COM을 사용하는 방법과 WMI에 접근하는 방법을 같이 공부할 수 있거든요.
또한, AD를 사용한다면, 에이전트 없이 원격 클라이언트의 정보를 상당량 수집할 수 있구요.

WMI에 대한 자세한 설명은 MSDN을 참조해주시구요, 전체적인 과정을 살펴보면 대략 다음과 같습니다.

1. CoInitialize로 COM을 초기화한다.
2. CoInitializeSecurity로 보안 레벨을 설정한다.
3. CoCreateInstance로 WMI 의 COM Object 를 생성한다.
4. ConnectServer로 "root\\cimv2" 네임스페이스로 접속한다.
5. ExecQuery 로 WQL 구문을 실행한다.
6. 실행결과 Enumerator 를 분석하고, 제조번호를 파싱한다.

그리하여, 전체 코드는 다음과 같이 되겠습니다.


001.#include "stdafx.h"
002. 
003.int _tmain(int argc, _TCHAR* argv[])
004.{
005.    int nRet = 0;
006.    HRESULT hr = S_OK;
007.    TCHAR tszMsg[1024] = {0, };
008. 
009.    try
010.    {
011.        if (_tsetlocale(LC_ALL, _T("")) == NULL)
012.            throw _T("_tsetlocale");
013. 
014.        hr = CoInitializeEx(0, COINIT_MULTITHREADED);
015.        if (FAILED(hr))
016.            throw _T("CoInitialize");
017. 
018.        hr = CoInitializeSecurity(NULL, -1, NULL, NULL,
019.            RPC_C_AUTHN_LEVEL_DEFAULT,
020.            RPC_C_IMP_LEVEL_IMPERSONATE,
021.            NULL, EOAC_NONE, NULL);
022.        if (FAILED(hr))
023.            throw _T("CoInitializeSecurity");
024. 
025.        CComPtr<IWbemLocator> wbemLocater = NULL;
026.        hr = CoCreateInstance(
027.                CLSID_WbemAdministrativeLocator,
028.            NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator,
029.            (LPVOID*)&wbemLocater);
030.        if (FAILED(hr))
031.            throw _T("CoCreateInstance");
032. 
033.        CComPtr<IWbemServices> wbemServices = NULL;
034.        hr = wbemLocater->ConnectServer(L"root\\cimv2",
035.            NULL, NULL, NULL,
036.            WBEM_FLAG_CONNECT_USE_MAX_WAIT,
037.            NULL, NULL, &wbemServices);
038.        if (FAILED(hr))
039.            throw _T("ConnectServer");
040. 
041.        CComPtr<IEnumWbemClassObject> wbemEnumerator = NULL;
042.        hr = wbemServices->ExecQuery(L"WQL",
043.            L"SELECT * FROM Win32_ComputerSystemProduct",
044.            WBEM_FLAG_FORWARD_ONLY, NULL, &wbemEnumerator);
045.        if (FAILED(hr))
046.            throw _T("ExecQuery");
047. 
048.        ULONG uReturned;
049.        while (wbemEnumerator)
050.        {
051.            CComPtr<IWbemClassObject> wbemObject = NULL;
052.            hr = wbemEnumerator->Next(
053.                WBEM_INFINITE, 1, &wbemObject, &uReturned);
054.            if (FAILED(hr))
055.                throw _T("Next");
056. 
057.            if (uReturned == 0)
058.                break;
059. 
060.            _variant_t vtProp;
061.            hr = wbemObject->Get(L"IdentifyingNumber",
062.                0, &vtProp, 0 ,0);
063.            if (FAILED(hr))
064.                throw _T("Get");
065. 
066.            wprintf(_T("%s\n"), (LPCTSTR)vtProp.bstrVal);
067.        }
068.    }
069.    catch (LPTSTR tszErr)
070.    {
071.        DWORD dwErr = GetLastError();
072.        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0,
073.            hr, 0, tszMsg, sizeof(tszMsg), NULL);
074.        if (*tszMsg == 0)
075.        {
076.            BSTR bstrErr;
077.            IErrorInfo* pErrInfo;
078.            GetErrorInfo(0, &pErrInfo);
079.            pErrInfo->GetDescription(&bstrErr);
080.            if (*bstrErr == 0)
081.            {
082.                if (*tszMsg == 0)
083.                {
084.                    FormatMessage(
085.                        FORMAT_MESSAGE_FROM_SYSTEM,
086.                        0, dwErr, 0,
087.                        tszMsg, sizeof(tszMsg), NULL);
088.                }
089.            }
090.        }
091.        _tprintf(_T("Error: [%s] %s\n"), tszErr, tszMsg);
092.        nRet = 1;
093.    }
094.    catch (...)
095.    {
096.        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0,
097.            GetLastError(), 0,
098.            tszMsg, sizeof(tszMsg), NULL);
099.        _tprintf(_T("Error: [UnExpected], %s\n"), tszMsg);
100.        nRet = 1;
101.    }
102. 
103.    CoUninitialize();
104. 
105.    return nRet;
106.}