debugging 显示外部进程调试输出

vd2z7a6w  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(132)

我正在开发一个视频游戏的声音编辑器。
这个应用程序有一个选项来测试游戏中的声音,为了做到这一点,我使用Process.Start和一些特殊的参数来打开game.exe。
游戏使用OutputDebugStringA()来打印调试消息。其想法是在此窗体中使用一个多行文本框来显示游戏进程的调试消息。
我一直在做一些研究,我知道从sysinternals的DebugView的存在,但不是有用的这种情况下,我也发现DbMon.NET的代码项目,但由于某种原因导致游戏运行非常缓慢(与DebugView不发生).
有什么建议吗?

emeijp43

emeijp431#

尝试这样做,您可以在将进程ID打印到文本框之前,在do while循环中指定它。

public partial class Form1 : Form
{
    private readonly IntPtr _bufferReadyEvent;
    private readonly IntPtr _dataReadyEvent;
    private readonly IntPtr _mapping;
    private readonly IntPtr _file;
    private const int WaitTimeout = 500;
    private const uint WAIT_OBJECT_0 = 0;
    private readonly Thread _reader;

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

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern IntPtr CreateFileMapping(IntPtr hFile, IntPtr lpFileMappingAttributes, FileMapProtection flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName);

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

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern uint WaitForSingleObject(IntPtr handle, uint milliseconds);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, FileMapAccess dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);

    [Flags]
    private enum FileMapAccess
    {
        FileMapRead = 0x0004,
    }

    [Flags]
    private enum FileMapProtection
    {
        PageReadWrite = 0x04,
    }

    public Form1()
    {
        InitializeComponent();

        _bufferReadyEvent = CreateEvent(IntPtr.Zero, false, false, "DBWIN_BUFFER_READY");
        if (_bufferReadyEvent == IntPtr.Zero)
            Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());

        _dataReadyEvent = CreateEvent(IntPtr.Zero, false, false, "DBWIN_DATA_READY");
        if (_dataReadyEvent == IntPtr.Zero)
            Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());

        _mapping = CreateFileMapping(new IntPtr(-1), IntPtr.Zero, FileMapProtection.PageReadWrite, 0, 4096, "DBWIN_BUFFER");
        if (_mapping == IntPtr.Zero)
            Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());

        _file = MapViewOfFile(_mapping, FileMapAccess.FileMapRead, 0, 0, 1024);
        if (_file == IntPtr.Zero)
            Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());

        _reader = new Thread(Read)
        {
            IsBackground = true
        };
        _reader.Start();
    }

    private void Read()
    {
        try
        {
            do
            {
                SetEvent(_bufferReadyEvent);

                uint wait = WaitForSingleObject(_dataReadyEvent, WaitTimeout);
                if (wait == WAIT_OBJECT_0) // we don't care about other return values
                {
                    int pid = Marshal.ReadInt32(_file);
                    string text = Marshal.PtrToStringAnsi(new IntPtr(_file.ToInt32() + Marshal.SizeOf(typeof(int)))).TrimEnd(null);
                    if (string.IsNullOrEmpty(text))
                    {
                        continue;
                    }
                    Textbox_DebugConsole.Invoke((MethodInvoker)delegate
                    {
                        Textbox_DebugConsole.AppendText(string.Format("{0} - {1}", pid, text + Environment.NewLine));
                    });
                }
            }
            while (true);
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}

相关问题