Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
yemets63
Member

Откуда: Самара
Сообщений: 1277
Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт

      Stream := TMemoryStream.Create;
      try
        if Windows.ReadFile(PipeRead, Buffer, 16382, NumberOfBytesRead, nil) then
        begin
          Stream.Write(PipeRead, NumberOfBytesRead);
          Stream.Position := 0;
          AErrors.LoadFromStream(Stream,TEncoding.GetEncoding(GetOEMCP));
        end;
      finally
        Stream.Free;
        CloseHandle(PipeRead);
      end;


если в Буфер что то приходит, и размер NumberOfBytesRead не равен 0, GetLastError = 0
если в Буфере пусто, и размер NumberOfBytesRead = 0, GetLastError = 109 - Канал закрыт

сам PipeRead имеет только номер процесса

как проверить перед выполнением Windows.ReadFile(PipeRead, Buffer, 16382, NumberOfBytesRead, nil) если результата не будет, то не выполнять вышеприведенный код

очень не красиво в finally end ставить SetLastError(0)
14 фев 20, 15:09    [22080105]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 49375

yemets63
Stream.Write(PipeRead, NumberOfBytesRead);

Это что за бред?

Posted via ActualForum NNTP Server 1.5

14 фев 20, 15:21    [22080111]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11498
yemets63
очень не красиво в finally end ставить SetLastError(0)
А зачем его ставить? Это раз. А второе зачем проверять GetLastError, если функция вернула True?
14 фев 20, 18:30    [22080286]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
makhaon
Member

Откуда: A galaxy far far away
Сообщений: 3523
yemets63,

ты же как-то трубу у себя открываешь? тут же самого главного - кода открытия - нет, но зачем то есть код чтения, к тому же неверный. вот на открытии и проверяй. открылась труба - значит ок. нет - значит трубы нет.
14 фев 20, 18:49    [22080308]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
Мимопроходящий
Member

Откуда: бурятский тундрюк, эсквайр
Сообщений: 31041

14.02.2020 18:49, makhaon пишет:
> открылась труба - значит ок. нет - значит трубы нет.

при открытии да, но канал может сдохнуть и в процессе чтения.
результат нужно проверять всегда.

Posted via ActualForum NNTP Server 1.5

14 фев 20, 18:52    [22080310]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11498
Мимопроходящий
результат нужно проверять всегда.
Но не GetLastError
14 фев 20, 19:18    [22080329]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
yemets63
Member

Откуда: Самара
Сообщений: 1277
_Vasilisk_,

код достаточно стаднтартный, запись текста из консоли, взят из Интернета еще за долго до меня.
я пробежался и особо ни чего не придумал, разве только заменить чтение Pipe в поток через функцию.

и так по тексту

сначала
CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0);
CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0);

потом процесс

if CreateProcess( nil, CommandMem, nil, nil, True, CreationFlags, nil, nil, StartupInfo, ProcessInfo) then
begin


GetExitCodeProcess(ProcessInfo.hProcess, AProcessExitCode);
если процесс пошел,
while AProcessExitCode = STILL_ACTIVE do
begin

далее получение текста из консоли
Stream := TMemoryStream.Create;
try
while true do
begin
succeed := ReadFile(PipeOutputRead, Buffer, BufferSizeText, NumberOfBytesRead, nil);
if not succeed then break;
Stream.Write(Buffer, NumberOfBytesRead);
end;
Stream.Position := 0;
AOutput.LoadFromStream(Stream,TEncoding.GetEncoding(GetOEMCP));
finally
Stream.Free;
end;
Result := True;
end:

end else
begin
Result := False;
end;

в конце закрытие и выдача результатов

ALastOSError := GetLastError;
GetExitCodeProcess(ProcessInfo.hProcess, AProcessExitCode);
CloseHandle(ProcessInfo.hProcess);

Result false или true если файл выполнился то true
если файл выполнился то - GetExitCodeProcess(ProcessInfo.hProcess, AProcessExitCode) = 0
а вот GetLastError равен 0, пока не начинаю закрывать каналы, и притом возврат код сообщения, например 109 - канал закрыт. следующий шаг после 109 будет логично 87, так как параметры уже получиться нельзя, но это уже не интересно, так как результат из pipe получен AOutput и / или AError


проблема с тестировщиками, им не нравится,
мы протестировали, результат при наличии файлов и правильных команд даже с перенаправлением всегда есть.
17 фев 20, 12:49    [22081235]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 49375

yemets63
код достаточно стаднтартный, запись текста из консоли, взят из Интернета еще за долго до меня.

Код достаточно бредовый, сразу видно что из интернета. Пора отказаться от отмазки "задолго
до меня" и таки переписать его правильно.

Posted via ActualForum NNTP Server 1.5

17 фев 20, 13:40    [22081313]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
yemets63
Member

Откуда: Самара
Сообщений: 1277
Dimitry Sibiryakov,

ни фига не отмазка, код с 2014-го лежит, приписка автора есть, который когда то был до нас

но по сути, я сделал почти тоже самое, до его кода, есть какие то свежие решения?
17 фев 20, 13:54    [22081321]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 49375

yemets63
есть какие то свежие решения?

В данном случае нужны не "свежие", а правильные решения. Как минимум - избавиться от
Stream и начать ловить завершение приложения именно по закрытию трубки, а не GetExitCode.

Posted via ActualForum NNTP Server 1.5

17 фев 20, 13:57    [22081327]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
Мимопроходящий
Member

Откуда: бурятский тундрюк, эсквайр
Сообщений: 31041

17.02.2020 13:57, Dimitry Sibiryakov пишет:
> начать ловить завершение приложения именно по закрытию трубки, а не GetExitCode.

не-а.
каноны велят отделять мух от котлет.
закрытие трубы всё таки не всегда тождественно завершению приложения.

Posted via ActualForum NNTP Server 1.5

17 фев 20, 14:13    [22081347]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 49375

Мимопроходящий
закрытие трубы всё таки не всегда тождественно завершению приложения.

"Чо?"
Кто ж её закроет-то? И самый главный вопрос: а что делать с приложением, которое её таки
закрыло?

Posted via ActualForum NNTP Server 1.5

17 фев 20, 14:20    [22081360]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
Мимопроходящий
Member

Откуда: бурятский тундрюк, эсквайр
Сообщений: 31041

при обломе трубы жди СиглОбжект.
если WAIT_OBJECT_0, получай ЭкзитПроцессКоде
если WAIT_FAILED, получай ЛастЕгор

"А кулаками махать любой дурак умеет." (С)

Posted via ActualForum NNTP Server 1.5

17 фев 20, 14:25    [22081372]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
makhaon
Member

Откуда: A galaxy far far away
Сообщений: 3523
yemets63,

готовая реализация не подойдет? в жедаях например:
https://github.com/project-jedi/jcl/blob/3a1b1681dfc2e461c02e44255a60b582a6e44b35/jcl/source/windows/JclMiscel.pas#L66
17 фев 20, 14:31    [22081383]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
Мимопроходящий
Member

Откуда: бурятский тундрюк, эсквайр
Сообщений: 31041

17.02.2020 14:31, makhaon пишет:
> готовая реализация не подойдет? в жедаях например:

мощно!
function WinExec32AndRedirectOutput(const Cmd: string; var Output: string; RawOutput: Boolean): Cardinal;
begin
  Result := Execute(Cmd, Output, RawOutput);
end;

дайте две!

Posted via ActualForum NNTP Server 1.5

17 фев 20, 14:40    [22081393]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
yemets63
Member

Откуда: Самара
Сообщений: 1277
джеди не пойдет,

WinExec32AndRedirectOutput - нет, ... "Герои не ищут легких путей",

хочу правильных решений и чем больше, тем лучше,
и так что сделать со Stream?
17 фев 20, 18:35    [22081626]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
Мимопроходящий
Member

Откуда: бурятский тундрюк, эсквайр
Сообщений: 31041

стрим в данном случае нахрен не нужен.

Posted via ActualForum NNTP Server 1.5

17 фев 20, 18:46    [22081635]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
Zelius
Member

Откуда: Россия, Москва
Сообщений: 1411
yemets63,

может подойдет
  function TryReadFromPipe( aPipe: THandle; out aBytes: TBytes): Boolean;
  var
    TotalBytesAvailable: DWORD;
    dwRead: Cardinal;
  begin
    SetLength( aBytes, 0);
    Result := False;
    Win32Check( PeekNamedPipe( aPipe, nil, 0, nil, @TotalBytesAvailable, nil));
    if TotalBytesAvailable <> 0 then
    begin
      SetLength( aBytes, TotalBytesAvailable);
      Win32Check( ReadFile( aPipe, Pointer(aBytes)^, TotalBytesAvailable, dwRead, nil));
      Result := True;
    end;
  end;


взято здесь Перенаправление вывода в файл
17 фев 20, 18:57    [22081646]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 49375

Zelius
может подойдет

Очередной нагугленный код, который решает не совсем ту задачу, которая стоит. Вот так сон
разума и рождает чудовищ.

Posted via ActualForum NNTP Server 1.5

17 фев 20, 19:09    [22081652]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
makhaon
Member

Откуда: A galaxy far far away
Сообщений: 3523
Мимопроходящий,

что не так?

yemets63,

ну ок, делай свой очередной велосипед. Безумству храбрых поем мы славу!
18 фев 20, 07:18    [22081803]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
yemets63
Member

Откуда: Самара
Сообщений: 1277
makhaon


ну ок, делай свой очередной велосипед. Безумству храбрых поем мы славу!


полностью согласен, но политика местной партии напрягает, и вынуждает начать все с квадратных колес, были решения проще и все рабочие. но примерно раз в год когото прёт, и приходится придумывать велосипеды, которые ездят боком
18 фев 20, 10:02    [22081894]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 5713
Dimitry Sibiryakov

Мимопроходящий
закрытие трубы всё таки не всегда тождественно завершению приложения.

"Чо?"
Кто ж её закроет-то? И самый главный вопрос: а что делать с приложением, которое её таки
закрыло?
её вызывающий должен закрывать, но никак не вызываемый
если по правильному, то вызываемому приложению даётся только дубликат хэндла - хоть зазакрывайся

другое дело, что обычно чтение делают в другом потоке в бокирующем режиме и закрывают Pipe когда убеждаются, что вызываемое приложение завершено, естественно вывалится ошибка на чтении
18 фев 20, 10:33    [22081932]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
yemets63
Member

Откуда: Самара
Сообщений: 1277
расскидал стандартный текст из интернета, о чем речь шла сначала по своему, протестировал сам, сделал кучу прерываний, убивал потоки и разрушал файлы, реакция есть.
до сих пор не понятно, почему когда нет ошибки и буфер пуст показывает что канал закрыт, номер 109, в итоге я его тупо ставлю в 0.
ошибки при процессах если не создавать нет.

короче отдал на тестирование, через пару дней будет ответ.
18 фев 20, 11:47    [22082021]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
Zelius
Member

Откуда: Россия, Москва
Сообщений: 1411
yemets63,

MSDN
If an anonymous pipe is being used and the write handle has been closed, when ReadFile attempts to read using the pipe's corresponding read handle, the function returns FALSE and GetLastError returns ERROR_BROKEN_PIPE.
18 фев 20, 11:52    [22082027]     Ответить | Цитировать Сообщить модератору
 Re: Нужно получить значение из канала PIPE, но когда оно пустое, пишет ошибку Канал закрыт  [new]
makhaon
Member

Откуда: A galaxy far far away
Сообщений: 3523
yemets63,

то есть даже посмотреть в жедаях как сделано не вариант, ну ок, тогда продолжай кактус грызть

вот ссылка прямо на сам код, а то вместе с Мимипроходящим так мимо и пройдете

https://github.com/project-jedi/jcl/blob/bde454905aac7f961350e5c36af5ad0a4713963b/jcl/source/common/JclSysUtils.pas#L2993

Сообщение было отредактировано: 18 фев 20, 12:02
18 фев 20, 11:53    [22082029]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Delphi Ответить