> ## 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.

# Calling wd tools from your title

> Calling wd tools from your title

This section will provide details and sample code for calling wd tools that live on the console in your title code. An example would be to call wdtrace.exe in title code to enable network tracing to debug multiplayer latency issues.

## Sample title code for calling wd tools

This line of sample code details the helper method which starts the wdtrace process. Any wd tool can be substituted for wdtrace in this example. The second parameter is the arguments for launching that tool.

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

Another example of the CreateAndRunRedirectedStdoutProcess method can be found below for wdconfig.exe

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

This is a sample of helper code that creates the process and re-directs the output from Stdout to OutputDebugString. This would then enable output to show up in Visual Studio or XbWatson. This could be replaced with a file write to store the output in a file instead.

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

## See also

[Console Command-line tools](/tools/tools-console/console_commandlinetools/consolecommandlinetools)

[XTF transport errors](/tools/tools-console/commandlinetools/xtf-transport-errors)


## Related topics

- [Console-based command-line tools](/tools/tools-console/console_commandlinetools/consolecommandlinetools.md)
- [Console-based command-line tools for XBOX](/tools/tools-console/console_commandlinetools/index.md)
- [Install and launch your PC title with GDK tools](/tools/tools-pc/launching-on-pc.md)
- [Best practices for calling XBOX services](/services/xbox-services/develop/best-practices/live-best-practices-calling-xbl.md)
- [Game Saves tools](/build/core-features/common/game-save/game-saves-tools.md)
