Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!

Capture DEBUGSTRING from TCC.EXE

Aug
2,799
144
Here is C# Code that will capture DEBUGSTRING output from TCC.EXE

I compiled this on my Windows 10 system with the following;

Code:
csc /nologo /platform:x64 /out:TccDebugListener.exe TccDebugListener.cs

Code:
using System;
using System.Diagnostics;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
using System.Text;

class Program
{
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr CreateEvent(IntPtr lpEventAttributes, bool bManualReset,
                                     bool bInitialState, string lpName);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool SetEvent(IntPtr hEvent);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);

    const uint WAIT_OBJECT_0 = 0;
    const uint INFINITE = 0xFFFFFFFF;

    static void Main()
    {
        Console.WriteLine("Standalone OutputDebugString listener for tcc.exe");

        // Create DebugView-compatible events
        IntPtr hDataReady = CreateEvent(IntPtr.Zero, false, false, "DBWIN_DATA_READY");
        IntPtr hBufferReady = CreateEvent(IntPtr.Zero, false, false, "DBWIN_BUFFER_READY");

        if (hDataReady == IntPtr.Zero || hBufferReady == IntPtr.Zero)
        {
            Console.WriteLine("Failed to create DBWIN events.");
            return;
        }

        using (var mmf = MemoryMappedFile.CreateOrOpen("DBWIN_BUFFER", 4096))
        using (var accessor = mmf.CreateViewAccessor())
        {
            // Signal that our buffer is ready
            SetEvent(hBufferReady);

            while (true)
            {
                // Wait for a debug string
                uint result = WaitForSingleObject(hDataReady, INFINITE);
                if (result != WAIT_OBJECT_0)
                    continue;

                int pid = accessor.ReadInt32(0);
                byte[] msgBytes = new byte[4092];
                accessor.ReadArray(4, msgBytes, 0, msgBytes.Length);

                string message = Encoding.ASCII.GetString(msgBytes).TrimEnd('\0');

                try
                {
                    Process proc = Process.GetProcessById(pid);
                    if (proc.ProcessName.Equals("tcc", StringComparison.OrdinalIgnoreCase))
                    {
                        Console.WriteLine($"[{pid}] {message}");
                    }
                }
                catch
                {
                    // Process may have exited
                }

                // Tell the system we are ready for the next message
                SetEvent(hBufferReady);
            }
        }
    }
}

The TccDebugListener.exe can be run from a PowerShell session, cmd.exe session, or tcc.exe session.

Running the following from TCC...
Code:
R:\>debugstring Test

R:\>debugstring %_isodate

R:\>

...produces the following from TccDebugListener.exe;

Code:
PS R:\> U:\TccDebugListener.exe
Standalone OutputDebugString listener for tcc.exe
[5788] [TCC] Test
[5788] [TCC] 2026-07-10

Joe
 
Back
Top