> ## 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 进程的辅助方法。在此示例中,可以用任何 wd 工具替换 wdtrace。第二个参数是启动该工具的参数。

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

以下是 CreateAndRunRedirectedStdoutProcess 方法用于 wdconfig.exe 的另一个示例。

```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)
