다음을 통해 공유


원격 컴퓨터 액세스

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);
}