> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 타이틀에서 wd 도구 호출

> 타이틀에서 wd 도구 호출

이 섹션에서는 타이틀 코드에서 콘솔에 있는 wd 도구를 호출하기 위한 세부 정보와 샘플 코드를 제공합니다. 예를 들어 멀티플레이어 지연 문제를 디버깅하기 위해 네트워크 추적을 활성화하려면 타이틀 코드에서 wdtrace.exe를 호출할 수 있습니다.

## wd 도구 호출을 위한 샘플 타이틀 코드

이 샘플 코드 라인은 wdtrace 프로세스를 시작하는 도우미 메서드를 자세히 설명합니다. 이 예제에서 wdtrace 대신 어떤 wd 도구든 대체할 수 있습니다. 두 번째 매개 변수는 해당 도구를 실행하기 위한 인수입니다.

```c++ theme={null}
CreateAndRunRedirectedStdoutProcess(L"C:\\Windows\\System32\\wdtrace.exe", const_cast<wchar_t*>(L" start advancedmp"));
```

wdconfig.exe에 대한 CreateAndRunRedirectedStdoutProcess 메서드의 또 다른 예제는 아래에서 찾을 수 있습니다.

```c++ theme={null}
CreateAndRunRedirectedStdoutProcess(L"C:\\Windows\\System32\\wdconfig.exe", const_cast<wchar_t*>(L" query consolemode"));
```

이것은 프로세스를 생성하고 Stdout의 출력을 OutputDebugString으로 리디렉션하는 도우미 코드의 샘플입니다. 그러면 Visual Studio 또는 XbWatson에 출력이 표시됩니다. 이는 대신 파일 쓰기로 대체하여 출력을 파일에 저장할 수도 있습니다.

```c++ theme={null}
void
ReadAndHandleOutput(
    _In_ HANDLE hPipeRead)
{
    CHAR lpBuffer[256];
    DWORD nBytesRead;
    BOOL  result = TRUE;

    while (result)
    {
        ZeroMemory(lpBuffer, sizeof(lpBuffer));
        result = ReadFile(hPipeRead, lpBuffer, (sizeof(lpBuffer) - 1), &nBytesRead, NULL);
        if (!result || !nBytesRead)
        {
            if (GetLastError() == ERROR_BROKEN_PIPE)
            {
                break;
            }
            else
            {
                break;
            }
        }
        
        // Instead of outputting this via OutputDebugStringA, it could instead be written to a log file.
        
        try
        {
            OutputDebugStringA(lpBuffer);
        }
        catch (...)
        {
            return;
        }
    }
}

HRESULT
WINAPI
CreateAndRunRedirectedStdoutProcess(
    _In_ LPCWSTR mainExe,
    _In_ LPWSTR lpCommandLine)
{
    HRESULT hr = S_OK;

    HANDLE hOutputReadTmp = INVALID_HANDLE_VALUE;
    HANDLE hOutputRead = INVALID_HANDLE_VALUE;
    HANDLE hOutputWrite = INVALID_HANDLE_VALUE;
    HANDLE hErrorWrite = INVALID_HANDLE_VALUE;

    STARTUPINFO si = { 0 };
    PROCESS_INFORMATION pi = { 0 };
    si.cb = sizeof(si);

    SECURITY_ATTRIBUTES sa = { 0 };

    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;

    if (!CreatePipe(&hOutputReadTmp, &hOutputWrite, &sa, 0))
    {
        OutputDebugString(L"Failed to create pipe");
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }

    if (!DuplicateHandle(GetCurrentProcess(), hOutputWrite, GetCurrentProcess(), &hErrorWrite, 0, TRUE, DUPLICATE_SAME_ACCESS))
    {
        OutputDebugString(L"Failed to dupicate handle");
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }

    if (!DuplicateHandle(GetCurrentProcess(), hOutputReadTmp, GetCurrentProcess(), &hOutputRead, 0, FALSE /*no inheritable*/, DUPLICATE_SAME_ACCESS))
    {
        OutputDebugString(L"Failed to duplicate handle");
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }

    // All redirection handles are created, set them and create the process
    si.dwFlags = 0x00000100; // STARTF_USESTDHANDLES;
    si.hStdOutput = hOutputWrite;
    si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    si.hStdError = hErrorWrite;

    if (!CreateProcess(
        mainExe, lpCommandLine,
        nullptr, nullptr,
        true, CREATE_NO_WINDOW,
        nullptr, nullptr,
        &si, &pi))
    {
        OutputDebugString(L"Failed to create process");
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }

    // pThread is unneeded, so close it now.
    if (pi.hThread && pi.hThread != INVALID_HANDLE_VALUE)
    {
        CloseHandle(pi.hThread);
    }

Exit:

    // Close output and error handles
    if (hOutputReadTmp != INVALID_HANDLE_VALUE)
    {
        CloseHandle(hOutputReadTmp);
        hOutputReadTmp = INVALID_HANDLE_VALUE;
    }
    if (hOutputWrite != INVALID_HANDLE_VALUE)
    {
        CloseHandle(hOutputWrite);
        hOutputWrite = INVALID_HANDLE_VALUE;
    }
    if (hErrorWrite != INVALID_HANDLE_VALUE)
    {
        CloseHandle(hErrorWrite);
        hErrorWrite = INVALID_HANDLE_VALUE;
    }

    // Read output if present.  This method will block until the process
    // has exited.  Then close the handle.
    if (hOutputRead != INVALID_HANDLE_VALUE)
    {
        ReadAndHandleOutput(hOutputRead);
        CloseHandle(hOutputRead);
        hErrorWrite = INVALID_HANDLE_VALUE;
    }

    // Check the return code from the process
    if (pi.hProcess && pi.hProcess != INVALID_HANDLE_VALUE)
    {
        DWORD exitCode = WaitForSingleObject(pi.hProcess, INFINITE);

        if (exitCode != WAIT_OBJECT_0)
        {
            hr = HRESULT_FROM_WIN32(GetLastError());
        }
        else if (!GetExitCodeProcess(pi.hProcess, &exitCode))
        {
            hr = HRESULT_FROM_WIN32(GetLastError());
        }
        else
        {
            if (exitCode)
            {
                hr = E_FAIL;
            }
        }

        CloseHandle(pi.hProcess);
        pi.hProcess = INVALID_HANDLE_VALUE;
    }

    return hr;
}
```

## 참고 항목

[콘솔 명령줄 도구](/tools/tools-console/console_commandlinetools/consolecommandlinetools)

[XTF 전송 오류](/tools/tools-console/commandlinetools/xtf-transport-errors)


## Related topics

- [콘솔 기반 명령줄 도구](/ko/tools/tools-console/console_commandlinetools/consolecommandlinetools.md)
- [XBOX용 콘솔 기반 명령줄 도구](/ko/tools/tools-console/console_commandlinetools/index.md)
- [타이틀에서 평판 피드백 보내기](/ko/services/xbox-services/community/reputation/concepts/live-sending-reputation-feedback.md)
- [GDK 도구로 PC 타이틀 설치 및 실행하기](/ko/tools/tools-pc/launching-on-pc.md)
- [멀티플레이어 FAQ 및 문제 해결](/ko/services/xbox-services/multiplayer/mpsd/concepts/live-multiplayer-2015-faq.md)
