> ## 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"));
```

以下是針對 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;
}
```

## 另請參閱

[主機命令列工具](/zh-TW/tools/tools-console/console_commandlinetools/consolecommandlinetools)

[XTF 傳輸錯誤](/zh-TW/tools/tools-console/commandlinetools/xtf-transport-errors)


## Related topics

- [主機型命令列工具](/zh-TW/tools/tools-console/console_commandlinetools/consolecommandlinetools.md)
- [適用於 XBOX 的主機型命令列工具](/zh-TW/tools/tools-console/console_commandlinetools/index.md)
- [WdLaunchMode](/zh-TW/reference/remoting/enums/wdlaunchmode.md)
- [從遊戲傳送信譽意見反應](/zh-TW/services/xbox-services/community/reputation/concepts/live-sending-reputation-feedback.md)
- [全域儲存空間工具 (GlobalStorage.exe)](/zh-TW/tools/tools-services/live-global-storage-tool.md)
