none
Получение текста из консольного окна / C# .NET RRS feed

  • Вопрос

  • Здравствуйте.
    Помогите программно получить весь текст из консоли сервера Counter Strike 1.6. Сказали, что нужно найти дескриптор окно консоли и применить GetWindowText. Но я не знаю как.
    30 марта 2014 г. 3:30

Ответы

  • Если речь идёт об обычном консольном окне Windows, то GetWindowText вернёт только его заголовок.

    static class ConsoleWindowHelper
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int GetWindowText(IntPtr hWnd, [Out] StringBuilder windowName, Int32 maxLength);
    
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int GetWindowTextLength(IntPtr hWnd);
    
        public static string GetText(string processName)
        {
            Process consoleProcess = Process.GetProcessesByName(processName).FirstOrDefault();
            if (consoleProcess == null)
            {
                throw new Exception("Cannot find process with name " + processName);
            }
    
            using (consoleProcess)
            {
                IntPtr handle = consoleProcess.MainWindowHandle;
    
                int length = GetWindowTextLength(handle);
                if (length < 1)
                {
                    int errorCode = Marshal.GetLastWin32Error();
                    throw new Win32Exception(errorCode, "Fail to get text length");
                }
    
                StringBuilder text = new StringBuilder(length + 1);
                GetWindowText(handle, text, text.Capacity);
                return text.ToString();
            }
        }
    }


    Если есть возможность запустить консоль программно, то можно перенаправить стандартный поток вывода, но тогда придётся запустить её без shell оболочки.

    using (Process p = new Process())
    {
        p.StartInfo.FileName = @"С:\CS\ConsoleApplication.exe";
        p.StartInfo.WorkingDirectory = @"С:\CS";
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.UseShellExecute = false;
                    
        // подписываемся на событие записи в консоль
        // полученный текст просто пишем в консоль уже нашего приложения
        p.OutputDataReceived += (o, e) => Console.WriteLine(e.Data);
    
        p.Start();
        p.BeginOutputReadLine();
    
        p.WaitForExit();
        p.CancelOutputRead();
    }

    или же вместо

    p.OutputDataReceived += (o, e) => Console.WriteLine(e.Data);
    p.BeginOutputReadLine();
    читать из StandartOutput напрямую
    StreamReader reader = p.StandardOutput;
    while (!reader.EndOfStream)
    {
        Console.WriteLine(reader.ReadLine());
    }



    • Изменено Sing1e 30 марта 2014 г. 13:03 ошибка при копировании
    • Помечено в качестве ответа PaMuC 30 марта 2014 г. 16:47
    30 марта 2014 г. 10:35

Все ответы

  • Если речь идёт об обычном консольном окне Windows, то GetWindowText вернёт только его заголовок.

    static class ConsoleWindowHelper
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int GetWindowText(IntPtr hWnd, [Out] StringBuilder windowName, Int32 maxLength);
    
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int GetWindowTextLength(IntPtr hWnd);
    
        public static string GetText(string processName)
        {
            Process consoleProcess = Process.GetProcessesByName(processName).FirstOrDefault();
            if (consoleProcess == null)
            {
                throw new Exception("Cannot find process with name " + processName);
            }
    
            using (consoleProcess)
            {
                IntPtr handle = consoleProcess.MainWindowHandle;
    
                int length = GetWindowTextLength(handle);
                if (length < 1)
                {
                    int errorCode = Marshal.GetLastWin32Error();
                    throw new Win32Exception(errorCode, "Fail to get text length");
                }
    
                StringBuilder text = new StringBuilder(length + 1);
                GetWindowText(handle, text, text.Capacity);
                return text.ToString();
            }
        }
    }


    Если есть возможность запустить консоль программно, то можно перенаправить стандартный поток вывода, но тогда придётся запустить её без shell оболочки.

    using (Process p = new Process())
    {
        p.StartInfo.FileName = @"С:\CS\ConsoleApplication.exe";
        p.StartInfo.WorkingDirectory = @"С:\CS";
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.UseShellExecute = false;
                    
        // подписываемся на событие записи в консоль
        // полученный текст просто пишем в консоль уже нашего приложения
        p.OutputDataReceived += (o, e) => Console.WriteLine(e.Data);
    
        p.Start();
        p.BeginOutputReadLine();
    
        p.WaitForExit();
        p.CancelOutputRead();
    }

    или же вместо

    p.OutputDataReceived += (o, e) => Console.WriteLine(e.Data);
    p.BeginOutputReadLine();
    читать из StandartOutput напрямую
    StreamReader reader = p.StandardOutput;
    while (!reader.EndOfStream)
    {
        Console.WriteLine(reader.ReadLine());
    }



    • Изменено Sing1e 30 марта 2014 г. 13:03 ошибка при копировании
    • Помечено в качестве ответа PaMuC 30 марта 2014 г. 16:47
    30 марта 2014 г. 10:35
  • Средствами .net вряд ли это возможно. Посмотрите вот эту статью из WinAPI.

    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    30 марта 2014 г. 15:16
  • не понимаю причем тут вообще WinApi когда идет речь о приложении не причастного к операционной системе. Консоль игры этой (Counter Strike) никакого отношения к системе не имеет, эта консоль даже не должна интерпретироваться как "консоль", может это просто некий textbox (предположение). а что бы получить от него что нибудь, надо запатчить или взломать саму библиотеку игры, какой нибудь game.dll который написан скорей всего на c или c++, что сразу требует от вас знания этого языка и приемов


    if (Thread.Was == HelpFul) Mark.As(HelpFul); else if (Thread.Was == Answered) Mark.As(Answered); else Provide(More.Details);

    30 марта 2014 г. 17:22