다음을 통해 공유


원격 컴퓨터 액세스

Windows 이벤트 로그 API를 사용하여 로컬 컴퓨터 또는 원격 컴퓨터의 데이터에 액세스할 수 있습니다. 원격 컴퓨터의 데이터에 액세스하려면 EvtOpenSession 함수를 호출하여 원격 세션 컨텍스트를 만들어야 합니다. 이 함수를 호출할 때 연결하려는 원격 컴퓨터의 이름, 연결을 만드는 데 사용할 사용자 자격 증명 및 사용자를 인증하는 데 사용할 인증 유형을 지정합니다. 현재 사용자를 지정하려면 도메인, 사용자 및 암호 멤버를 NULL로 설정합니다.

Windows 이벤트 로그 API를 호출할 때 EvtOpenSession 함수가 반환하는 원격 세션 컨텍스트에 핸들을 전달합니다. 로컬 컴퓨터의 데이터에 액세스하려면 NULL 을 전달하여 기본 세션을 지정합니다. 원격 컴퓨터의 데이터에 액세스하려면 원격 컴퓨터에서 "원격 이벤트 로그 관리" Windows 방화벽 예외를 사용하도록 설정해야 합니다. 그렇지 않으면 세션 핸들을 사용하려고 하면 RPC_S_SERVER_UNAVAILABLE 호출에 오류가 발생합니다. 연결하는 컴퓨터에서 Windows Vista 이상을 실행해야 합니다.

다음 예제에서는 원격 컴퓨터에 연결하는 방법을 보여줍니다.

#include <windows.h>
#include <stdio.h>
#include <winevt.h>

#pragma comment(lib, "wevtapi.lib")

EVT_HANDLE ConnectToRemote(LPWSTR lpwszRemote);
void EnumProviders(EVT_HANDLE hRemote);

void main(void)
{
    EVT_HANDLE hRemote = NULL;
    LPWSTR pwsComputerName = L"<name of the remote computer goes here>";
    

    // Enumerate the registered providers on the local computer.
    wprintf(L"Registered providers on the local computer\n\n");
    EnumProviders(hRemote);

    hRemote = ConnectToRemote(pwsComputerName);
    if (NULL == hRemote)
    {
        wprintf(L"Failed to connect to remote computer. Error code is %d.\n", GetLastError());
        goto cleanup;
    }

    // Enumerate the registered providers on the remote computer.
    // To access a remote computer, the remote computer must enable 
    // Remote Event Log Management as an exception in the firewall;
    // otherwise, the remote call fails with RPC_S_SERVER_UNAVAILABLE.
    wprintf(L"\n\nRegistered providers on the remote computer\n\n");
    EnumProviders(hRemote);

cleanup:

    if (hRemote)
        EvtClose(hRemote);
}

// Create a session context for the remote computer. Set the 
// Domain, User, and Password member to NULL to specify
// the current user.
EVT_HANDLE ConnectToRemote(LPWSTR lpwszRemote)
{
    EVT_HANDLE hRemote = NULL;
    EVT_RPC_LOGIN Credentials;

    RtlZeroMemory(&Credentials, sizeof(EVT_RPC_LOGIN));
    Credentials.Server = lpwszRemote;
    Credentials.Domain = NULL; 
    Credentials.User = NULL; 
    Credentials.Password = NULL; 
    Credentials.Flags = EvtRpcLoginAuthNegotiate; 

    // This call creates a remote session context; it does not actually
    // create a connection to the remote computer. The connection to
    // the remote computer happens when you use the context.
    hRemote = EvtOpenSession(EvtRpcLogin, &Credentials, 0, 0);

    SecureZeroMemory(&Credentials, sizeof(EVT_RPC_LOGIN));

    return hRemote;
}

// Enumerate the registered providers on the computer.
void EnumProviders(EVT_HANDLE hRemote)
{
    EVT_HANDLE hPublishers = NULL;
    WCHAR wszPublisherName[255 + 1];
    DWORD dwBufferUsed = 0;
    DWORD status = ERROR_SUCCESS;

    hPublishers = EvtOpenPublisherEnum(hRemote, 0);
    if (NULL == hPublishers)
    {
        wprintf(L"EvtOpenPublisherEnum failed with %d\n", GetLastError());
        goto cleanup;
    }

    while (true)
    {
        if (EvtNextPublisherId(hPublishers, sizeof(wszPublisherName)/sizeof(WCHAR), wszPublisherName, &dwBufferUsed))
        {
            wprintf(L"%s\n", wszPublisherName);
        }
        else
        {
            status = GetLastError();
            if (ERROR_NO_MORE_ITEMS == status)
            {
                break;
            }
            else
            {
                wprintf(L"EvtNextPublisherId failed with 0x%ud\n", GetLastError());
            }
        }
    }

cleanup:

    if (hPublishers)
        EvtClose(hPublishers);
}