Форум программистов, компьютерный форум, киберфорум
Delphi: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/4: Рейтинг темы: голосов - 4, средняя оценка - 5.00
4 / 4 / 0
Регистрация: 09.12.2022
Сообщений: 297

Захват консоли в строку

15.02.2024, 12:45. Показов 1340. Ответов 15
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте, уважаемые профессионалы!
Пытаюсь захватить вывод консольного приложения в строку. Для этого использую найденную на просторах форумов функцию:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
function runcmd(aString: WideString): string;
const
  CReadBuffer = 2400;
var
  saSecurity: TSecurityAttributes;
  hRead: THandle;
  hWrite: THandle;
  suiStartup: TStartupInfo;
  piProcess: TProcessInformation;
  pBuffer: array [0 .. CReadBuffer] of AnsiChar;
  dRead: DWord;
  dRunning: DWord;
begin
  Result := '';
 
  saSecurity.nLength := SizeOf(TSecurityAttributes);
  saSecurity.bInheritHandle := True;
  saSecurity.lpSecurityDescriptor := nil;
 
  if CreatePipe(hRead, hWrite, @saSecurity, 0) then
  begin
    try
      FillChar(suiStartup, SizeOf(TStartupInfo), #0);
      suiStartup.cb := SizeOf(TStartupInfo);
      suiStartup.hStdInput := hRead;
      suiStartup.hStdOutput := hWrite;
      suiStartup.hStdError := hWrite;
      suiStartup.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
      suiStartup.wShowWindow := SW_HIDE;
 
      if CreateProcessW(PChar(astring), nil, @saSecurity, @saSecurity, True,
        CREATE_NEW_PROCESS_GROUP or NORMAL_PRIORITY_CLASS, nil, nil,
        suiStartup, piProcess) then
      begin
        CloseHandle(hWrite);
        try
          repeat
            dRunning := WaitForSingleObject(piProcess.hProcess, 100);
 
            repeat
              dRead := 0;
              if ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil) then
              begin
                pBuffer[dRead] := #0;
                //OemToAnsi(pBuffer, pBuffer);
                Result := Result + String(pBuffer);
              end else
              result:='error '+floattostr(getlasterror());
            until (dRead < CReadBuffer);
          until (dRunning <> WAIT_TIMEOUT);
        finally
          CloseHandle(piProcess.hProcess);
          CloseHandle(piProcess.hThread);
        end;
      end else
        raise Exception.Create('Can not CreateProcess ' + QuotedStr(aString));
    finally
      CloseHandle(hRead);
    end;
  end else
    raise Exception.Create('Can not CreatePipe ' + QuotedStr(aString));
end;
Вместо искомой строки, сгенерированной запускаемым приложением, возвращается код ошибки 109. По факту, процесс запускается, но ReadFile ничего не возвращает в переменную dRead. Что бы это могло быть?
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
15.02.2024, 12:45
Ответы с готовыми решениями:

Вывести строку символов по указанным координатам в консоли, очертить строку на экране одинарной рамкой
Вывести строку символов по указанным координатам, очертить строку на экране одинарной рамкой. Windows XP x32, TASM.

1. Ввести с консоли строку. Найти количество в букв в верхнем и нижнем регистрах. Сформировать новую строку, содержащую
1. Ввести с консоли строку. Найти количество в букв в верхнем и нижнем регистрах. Сформировать новую строку, содержащую только строчные...

Ввести с консоли строку. Найти количество в букв в верхнем и нижнем регистрах. Сформировать новую строку, содержащую тол
Ввести с консоли строку. Найти количество в букв в верхнем и нижнем регистрах. Сформировать новую строку, содержащую только строчные буквы...

15
Модератор
 Аватар для D1973
9903 / 6441 / 2454
Регистрация: 21.01.2014
Сообщений: 27,341
Записей в блоге: 3
15.02.2024, 13:11
Ошибка 109 на более человеческом языке звучит как ERROR_BROKEN_PIPE. Возможно, маловат таймаут в функции WaitForSingleObject...
А вообще... чему у Вас равны значения параметров hRead, hWrite в момент вызова функции CreatePipe?
0
4 / 4 / 0
Регистрация: 09.12.2022
Сообщений: 297
15.02.2024, 15:09  [ТС]
Цитата Сообщение от D1973 Посмотреть сообщение
А вообще... чему у Вас равны значения параметров hRead, hWrite в момент вызова функции CreatePipe?
Всё время разные. В среднем 576, 580.

Добавлено через 7 минут
Цитата Сообщение от D1973 Посмотреть сообщение
Возможно, маловат таймаут в функции WaitForSingleObject...
Увеличил до 10 секунд, всё равно та же ошибка. Да и время ожидания практически мгновенно... Не похоже
0
Модератор
 Аватар для D1973
9903 / 6441 / 2454
Регистрация: 21.01.2014
Сообщений: 27,341
Записей в блоге: 3
15.02.2024, 18:46
Цитата Сообщение от t232006 Посмотреть сообщение
Всё время разные
а откуда они берутся-то? Вот о чем я Вас спрашиваю
0
4 / 4 / 0
Регистрация: 09.12.2022
Сообщений: 297
15.02.2024, 19:22  [ТС]
Как я понял из документации к функции CreatePipe, они генерируются системой для чтения/записи из/в буфер.
0
пофигист широкого профиля
4769 / 3204 / 862
Регистрация: 15.07.2013
Сообщений: 18,608
18.02.2024, 21:40
Цитата Сообщение от t232006 Посмотреть сообщение
until (dRead < CReadBuffer);
Вот это условие мне не нравится.

Добавлено через 1 час 4 минуты
Цитата Сообщение от t232006 Посмотреть сообщение
CREATE_NEW_PROCESS_GROUP
И еще. Этот флаг использован осознанно или только потому что он был использован в том примере с помойки?

И зачем эта пляска с вызовом WaitForSingleObject в цикле?
0
4187 / 1835 / 220
Регистрация: 06.10.2010
Сообщений: 4,123
19.02.2024, 12:35
Лучший ответ Сообщение было отмечено t232006 как решение

Решение

Попробуй этот код.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{$APPTYPE CONSOLE}
uses
  Windows;
 
const
  CReadBuffer = 2400;
 
var
 saSecurity: TSecurityAttributes=(nLength:SizeOf(TSecurityAttributes);bInheritHandle:True);
 suiStartup: TStartupInfo=(cb: SizeOf(TStartupInfo);dwFlags:STARTF_USESTDHANDLES+STARTF_USESHOWWINDOW;wShowWindow:SW_HIDE);
 piProcess:  TProcessInformation;
 pBuffer:    array [0 .. CReadBuffer] of AnsiChar;
 dRead:      DWord;
 
begin
  if CreatePipe(suiStartup.hStdInput, suiStartup.hStdOutput, @saSecurity, CReadBuffer) then
  begin
    suiStartup.hStdError:=suiStartup.hStdOutput;
    if CreateProcessW('B:\1.exe',0,@saSecurity,0,True,0,0,0,suiStartup,piProcess) then
    begin
      dRead:=0;
      ReadFile(suiStartup.hStdInput, pBuffer, CReadBuffer, dRead, 0);
      pBuffer[dRead]:=#0;
      TerminateProcess(piProcess.hProcess,0);
    end;
    CloseHandle(suiStartup.hStdInput);
    CloseHandle(suiStartup.hStdOutput);
  end;
  writeln(pBuffer);
  readln;
end.
1
4 / 4 / 0
Регистрация: 09.12.2022
Сообщений: 297
19.02.2024, 12:53  [ТС]
Цитата Сообщение от northener Посмотреть сообщение
Вот это условие мне не нравится.
все равно dRead = 0, а так быть не должно. Так что не в цикле дело
Цитата Сообщение от northener Посмотреть сообщение
И еще. Этот флаг использован осознанно или только потому что он был использован в том примере с помойки?
да, вы правы, этот флаг здесь лишний, но он не мешается (он игнорируется ОС).
Цитата Сообщение от northener Посмотреть сообщение
И зачем эта пляска с вызовом WaitForSingleObject в цикле?
при невозможности соединения с сервером (моя программа должна соединяться с GoogleDrive и получать список файлов по маске) консоль должна закрыться. А WaitForSingleObject - чтобы не продолжать выполнение программы, пока этот список не будет получен.
0
4 / 4 / 0
Регистрация: 09.12.2022
Сообщений: 297
24.02.2024, 17:59  [ТС]
murderer, Ваш код работает, но только есть 2 обстоятельства:
1)если запускать следующую последовательность в отладчике, то всё нормально
Code
1
2
3
4
5
6
begin
      dRead:=0;
      ReadFile(suiStartup.hStdInput, pBuffer, CReadBuffer, dRead, 0);
      pBuffer[dRead]:=#0;
      TerminateProcess(piProcess.hProcess,0);
    end;
, но если в режиме транслятора, тогда возвращается только первая строчка.
2) правильно ли я понимаю, что
Code
1
2
3
4
var
 saSecurity: TSecurityAttributes=(nLength:SizeOf(TSecurityAttributes);bInheritHandle:True);
 suiStartup: TStartupInfo=(cb: SizeOf(TStartupInfo);dwFlags:STARTF_USESTDHANDLES+STARTF_USESHOWWINDOW;wShowWindow:SW_HIDE);
 piProcess:  TProcessInformation;
могут быть только глобальными?
0
пофигист широкого профиля
4769 / 3204 / 862
Регистрация: 15.07.2013
Сообщений: 18,608
26.02.2024, 02:30
Цитата Сообщение от t232006 Посмотреть сообщение
1)если запускать следующую последовательность в отладчике, то всё нормально
Цитата Сообщение от t232006 Посмотреть сообщение
но если в режиме транслятора, тогда возвращается только первая строчка.
И это вполне нормально. В режиме отладчика всё делается медленно. И вполне возможно программа успевает получить всю информацию за один вызов функции ReadFile.
Не знаю что вы называете "режимом транслятора", ибо в программировании трансляторов как отдельных сущностей нет уже тыщу лет.
Но обратите внимание что в первом вашем коде есть цикл
Цитата Сообщение от t232006 Посмотреть сообщение
repeat
dRead := 0;
if ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil) then
begin
pBuffer[dRead] := #0;
//OemToAnsi(pBuffer, pBuffer);
Result := Result + String(pBuffer);
end else
result:='error '+floattostr(getlasterror());
until (dRead < CReadBuffer);
Этот цикл там не сдуру вставлен в код!
Условие в until там кривое. Но цикл нужен!

Добавлено через 15 минут
Цитата Сообщение от murderer Посмотреть сообщение
TerminateProcess(piProcess.hProcess,0);
А это вообще серпом по фабержам. Где вы нарыли такой кривой код?
0
4 / 4 / 0
Регистрация: 09.12.2022
Сообщений: 297
03.03.2024, 23:46  [ТС]
Цитата Сообщение от northener Посмотреть сообщение
Не знаю что вы называете "режимом транслятора",
Хотел сказать, "в режиме компилятора". Извиняюсь.
0
Модератор
4115 / 2347 / 807
Регистрация: 15.11.2015
Сообщений: 9,328
04.03.2024, 12:04
Цитата Сообщение от t232006 Посмотреть сообщение
Хотел сказать, "в режиме компилятора".
Что это за режим? Знаю режим дебага.
0
пофигист широкого профиля
4769 / 3204 / 862
Регистрация: 15.07.2013
Сообщений: 18,608
05.03.2024, 02:29
Цитата Сообщение от t232006 Посмотреть сообщение
Хотел сказать, "в режиме компилятора". Извиняюсь.
Цитата Сообщение от AzAtom Посмотреть сообщение
Что это за режим? Знаю режим дебага.
Вангую что "режим отладчика" - это запуск с использованием точек останова. А "режим компилятора" - это тот же запуск, но без точек останова.
1
4 / 4 / 0
Регистрация: 09.12.2022
Сообщений: 297
05.03.2024, 15:45  [ТС]
Цитата Сообщение от AzAtom Посмотреть сообщение
Что это за режим? Знаю режим дебага.
Режим компилятора согласно определению - это вид транслятора, преобразующий исходный код с какого-либо языка программирования на машинный язык. А интерпретатор - это процесс чтения и выполнения исходного кода. Другими словами под транслятором я понимаю простое исполнение кода (F9 или ctrl+Shift+F9 или Ctrl+F9), а интерпретатор - это режим отладчика, то есть выполнение построчно.
0
Модератор
4115 / 2347 / 807
Регистрация: 15.11.2015
Сообщений: 9,328
05.03.2024, 20:37
t232006, понятно, что вы понимаете как-то необычно. Delphi всегда компилирует программу в машинные коды. При запуске по F9 по умолчанию происходит запуск программы в режиме отладки. То есть, программа работает как обычно, сама по себе, но к ней подключается дебагер и тогда возможно пошаговое исполнение. Но программа при этом всё равно скомпилированная и выполняются машинные коды.
0
пофигист широкого профиля
4769 / 3204 / 862
Регистрация: 15.07.2013
Сообщений: 18,608
06.03.2024, 01:13
Цитата Сообщение от t232006 Посмотреть сообщение
А интерпретатор - это процесс чтения и выполнения исходного кода. Другими словами под транслятором я понимаю простое исполнение кода (F9 или ctrl+Shift+F9 или Ctrl+F9), а интерпретатор - это режим отладчика, то есть выполнение построчно.
Ни в Паскале, ни в Дельфи интерпретаторов никогда не было.
Трансляторы может и были когда-то на заре Паскаля. Не знаю.
Но уж начиная с Турбо Паскаля был только компилятор. Это уж если вы хотите "согласно определению".
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
06.03.2024, 01:13
Помогаю со студенческими работами здесь

Ввести n строк с консоли, найти самую короткую строку. Вывести эту строку, её длину и количество гласных букв в ней
1.Ввести n строк с консоли, найти самую короткую строку. Вывести эту строку, её длину и количество гласных букв в ней. Помогите плиз

Ввести n строк с консоли, найти самую короткую строку. Вывести эту строку, её длину и количество гласных букв в ней
Помогите сделать пж.

Циклы: вывести в первую строчку консоли строку из 10 заданных букв и во вторую строчку консоли из 5 таких букв
Задана буква. Вывести в первую строчку консоли строку из 10 таких букв и во вторую строчку консоли из 5 таких букв.

Cчитать строку из консоли
Как считать строку из консоли?

Изменить строку в консоли
У меня такой вопрос. Как можно изменить одну или несколько строк в консоли? То есть если есть, допустим 10 строк, то как изменить скажем,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru