Всем привет! Задание: Оба приложения через фиксированные промежутки времени передают друг другу строку текста, включающую дескриптор приложения и текущее время. Требование к заданию: 1) Используя средства языка Object Pascal, разработать в соответствии с индивидуальным заданием приложения ПI и П2 (П2 - «дочернее»). 2) Для организации автоматической записи/чтения данных используйте стан-дартный системный компонент-таймер TTimer с интервалом «срабатывания» не бо¬лее 2-4 с. 3) Обратите внимание, текст сообщения об ошибке, возникающей при работе с каналом можно получить с помощью вызова SysErTorMessage(GetLastError).
Немного теории по заданию:
Для создания анонимных каналов (далее просто «каналы») в ОС Windows ис¬пользуется функция CreatePipe. Она возвращает два дескриптора, имеющие права GENERIC_READ (OENERIC_WRJTE) и SYNCHRONIZE на доступ к «входу» и «выходу» канала. Для записи и чтения данных необходимо использовать соответственно функции WriteFile и ReadFile. Как только канал перестаёт быть необходимым, его необходимо уничтожить с помощью функции CIoseHandle. Типичное использование анонимного канала состоит в создании канала пере¬дачи данных между родительским и дочерним процессом. В руководстве [1] для этого рекомендуется выполнять переназначение стандартного ввода и вывода в дочер¬нем процессе. Рассмотрим общую схему такого переназначения: 1) Получить дескриптор стандартного входного/выходного потока с помощью функции OctSldHandle и сохранить его для дальнейшего использования. 2) Создать канал, вызвав функцию CreatePipe. 3) Вызвать функцию SetStdHandle, чтобы переназначить стандартные потоки чте-ния и записи. 4) Создать дочерний процесс с помощью функции CrcaieProcess. При этом необхо¬димо указать, что дочерний процесс должен наследовать дескрипторы процесса, в том числе потоки ввода/вывода. Рассмотрим программный фрагмент, реализующий данную схему (с двухсто¬ронним доступом к каналу):
var 01d_Input, 01d_Output: THandle; hReadPipe, hWritePipe: Cardinal; //Дескрипторы канала: «выход», «вход» PipeAttributes: TSecurityAttributes; si: TStartupInfo; pi: TProcessInformation; // Код, выполняемый при инициализации головной программы // - Шаг 1 01d_Input :- GetStdHandle(STD_INPUT_HANDLE); 01d_Output :- GetStdHandle(STO_OUTPUT_HANDLE) ; // - Шаг 2 PipeAttributes.nLength :- SizeOf(TSecurityAttributes); PipeAttributes.IpSecurityDescriptor :- Hil; PipeAttributes.blnheritHandle := True; // Разрешение «наследовать» // дескрипторы канала // Создание канала размером 100 байт if Not CreatePipe(hReadPipe,hWritePipe,ePipeAttributes,100) then „ // Обработка ситуации, когда канал не был создан // - Шаг 3 SetStdHandle(STD_INPUT_HANDLE, hReadPipe); SetStdHandle(STD_OUTPUT_HANDLE, hWritePipe); // - Шаг 4 si.cb:-si2eof(TStartupInfo); sl.lpReserved :- Nil; si.lpDesktop :- Hil; si.lpTitle :- Mil; si.dwFlags :- 0; si.cbReserved2 :- 0; si.lpReserved2 :=■ Nil; // - Шаг 5 if Hot CreateProcess('ChildTask.exe',Nil,Nil,Nil, True, 0,Nil,Nil, si,pi) than // Обработка ситуации, когда дочерний процесс не был создан SetStdHandle(STD_INPOT_HANDLE, 01d_Input) ; SetStdHandle (STD__OUTPUT_HANDLE, OldJDutput) ; // Код, выполняемый при инициализации дочерней программы hReadPipe :- GetStdHandle(STD_INPUT_HANDLE) ; hWritePipe :- GetStdHandle(STD_OUTPUT_HANDLE); // Код, выполняемый при записи данных в канал var nNumberOfBytesToWrite, NumberOfBytesWritten: Cardinal; Buffer: array(0..5O) of char; begin Screen.Cursor :- crHourGlass; try StrLCopy(Buffer,pChar(Editl.Text),50); // Записываем не более 50 байт nNumberOfBytesToWrite :- Length(Edit 1.Text)+1; if Not WriteFile(hWritePipe,Buffer,nNumberOfBytesToWrite, NumberOfBytesWritten,Nil) than _. // Обработка ситуации, когда // запись в канал оказывается невозможной. finally Screen-Cursor := crDefault; and; end; // Код, выполняемый при чтении данных из канала var Buffer: array[0..10] of char; nNumberOfBytesToRead, NumberOfBytesRead: Cardinal; begin Screen.Cursor :- crHourGlass; try nNumberOfBytesToRead :- 10; // Считываем no 10 байт if ReadFile(hReadPipe,Buffer,nNumberOfBytesToRead, NumberOfBytesRead,Nil) then Memol.Lines.Add(String(Buffet)) else „ // Обработка ситуации, когда чтение // из канала оказывается невозможным. finally Screen.Cursor := crDefault; end; end; // Код, выполняемый при завершении головной программы CIoseHandle(hReadPipe); CIoseHandle(hWritePipe); // Уничтожение канала
Нашел задание--Приложение П1 непрерывно через фиксированные промежутки времени выводит пользовательский текст в канал. Приложение П2 записывает данные из канала в файл-протокол.(все требованию такие же). Как можно переделать вот этот код под своё задание?
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin CloseHandle(hReadPipe); CloseHandle(hWritePipe); end;
procedure TForm1.Timer1Timer(Sender: TObject); var nNumberOfBytesToWrite, NumberOfBytesWritten: Cardinal; Buffer: array[0..50] of char; begin Screen.Cursor := crHourGlass; try StrLCopy(Buffer,pChar(Memo1.Lines.Text),50); nNumberOfBytesToWrite := Length(Memo1.Lines.Text)+1; if Not WriteFile(hWritePipe,Buffer,nNumberOfBytesToWrite, NumberOfBytesWritten,Nil) then ShowMessage('Невозможна запись в канал!');
procedure TForm1.Timer1Timer(Sender: TObject); var Buffer: array[0..30] of char; nNumberOfBytesToRead, NumberOfBytesRead: Cardinal; begin Screen.Cursor := crHourGlass; try nNumberOfBytesToRead := 30; // Считываем по 10 байт if ReadFile(hReadPipe,Buffer,nNumberOfBytesToRead, NumberOfBytesRead,Nil) then begin Memo1.Lines.Add(String(Buffer)); Memo1.Lines.SaveToFile('Read.txt'); WFile(String(Buffer),'Read1.txt'); end else Memo1.Lines.Add('Невозможно чтение!'); finally Screen.Cursor := crDefault; end; end;
procedure WFile (str,patch: string); var f: TextFile; begin AssignFile(f,patch); if FileExists(patch) then begin append(f); writeln(f,str); end else begin rewrite(f); writeln(f,str); end; close(f); end;