|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Программа консольного ввода/вывода
Помогите пожалуйста переделать код под Delphi XE3, проект взят отсюда http://www.delphisources.ru/forum/sh...ad.php?p=79065. Написан видимо в D7.
Программа представляет собой оболочку cmd. В Edit вводишь команду, в Memo получаешь ответ. Код:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TReadThread = class(TThread) private buf: array [0..255] of AnsiChar; dummy: Cardinal; procedure UpdateForm; protected procedure Execute; override; public constructor Create; destructor Destroy; override; end; TFormMain = class(TForm) MemoConsole: TMemo; EditText: TEdit; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure EditTextKeyPress(Sender: TObject; var Key: Char); private hPipeInputRead: THandle; hPipeInputWrite: THandle; hPipeOutputRead: THandle; hPipeOutputWrite: THandle; hProcess: THandle; readthread: TReadThread; public end; var FormMain: TFormMain; implementation {$R *.dfm} procedure TFormMain.FormCreate(Sender: TObject); var securityattributes: TSecurityAttributes; startupinfo: TStartupInfo; processinformation: TProcessInformation; begin securityattributes.nLength:=SizeOf(TSecurityAttributes); securityattributes.lpSecurityDescriptor:=nil; securityattributes.bInheritHandle:=True; CreatePipe(hPipeInputRead, hPipeInputWrite, @securityattributes, 0); CreatePipe(hPipeOutputRead, hPipeOutputWrite, @securityattributes, 0); ZeroMemory(@startupinfo, SizeOf(TStartupInfo)); ZeroMemory(@processinformation, SizeOf(TProcessInformation)); startupinfo.cb:=SizeOf(TStartupInfo); startupinfo.dwFlags:=STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; startupinfo.wShowWindow:=SW_HIDE; startupinfo.hStdInput:=hPipeInputRead; startupinfo.hStdOutput:=hPipeOutputWrite; startupinfo.hStdError:=hPipeOutputWrite; CreateProcess(nil, PChar('cmd'), nil, nil, True, CREATE_NEW_CONSOLE, nil, nil, startupinfo, processinformation); hProcess:=processinformation.hProcess; readthread:=TReadThread.Create; end; procedure TFormMain.FormDestroy(Sender: TObject); begin TerminateProcess(hProcess, 255); WaitForSingleObject(hProcess, INFINITE); CloseHandle(hProcess); readthread.Terminate; CloseHandle(hPipeInputWrite); CloseHandle(hPipeInputRead); CloseHandle(hPipeOutputWrite); CloseHandle(hPipeOutputRead); readthread.WaitFor; readthread.Free; end; procedure TFormMain.EditTextKeyPress(Sender: TObject; var Key: Char); var buf: array [0..255] of AnsiChar; dummy: Cardinal; begin if Key=#13 then begin MemoConsole.Clear; StrPCopy(buf, EditText.Text+#13#10); WriteFile(hPipeInputWrite, buf, Length(EditText.Text)+2, dummy, nil); EditText.Clear; end; end; { TReadThread } constructor TReadThread.Create; begin inherited Create(False); FreeOnTerminate:=False; end; destructor TReadThread.Destroy; begin inherited Destroy; end; procedure TReadThread.Execute; begin while not Terminated do if ReadFile(FormMain.hPipeOutputRead, buf, Length(buf), dummy, nil) then Synchronize(UpdateForm); end; procedure TReadThread.UpdateForm; begin OemToAnsiBuff(buf, buf, dummy); FormMain.MemoConsole.Text:=FormMain.MemoConsole.Text+Copy(buf, 1, dummy); end; end. Сам переделал пару мест, поменял of Char, на of AnsiChar (стр.12, 85). Ошибки в коде исчезли, но теперь при компиляции вылазит это: Так как с delphi знаком всего пару недель ), на этом встал в тупик. Последний раз редактировалось zxen, 13.02.2013 в 15:50. |
#2
|
||||
|
||||
Если уж переводить на AnsiChar, то нужно и структуры менять. К примеру, TStartupInfo меняется на TStartupInfoA.
Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. |
#3
|
|||
|
|||
Нарыл и приспособил немножко другой код.. Есть небольшая проблемка, когда программа запускает например пинг. ехе, во время обработки пргрпмму невозжожно закрыть крестиком, вставил паузу (стр. 116) программа не виснет , но крестик все равно не нажимается. И как можно закрывать порограммы, запущенные CreateProcess'om.. тасккил по имени как то тупо.. И еще, как бы сделать так, чтоб текст вывода консоли добавлялся к уже существующему в мемо, а не стирался с каждым новым выводом. Memo1.Text:= Memo1.Text + DosToWin(getcmdval) не работает, выполняется первая команда, дальше вообще ничего в мемо не пишется.
Код:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Winapi.ShellAPI; type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; Edit1: TEdit; Button2: TButton; Button3: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Edit1KeyPress(Sender: TObject; var Key: Char); private function GetDosOutput(const CommandLine:string): string; public end; var Form1: TForm1; implementation {$R *.dfm} var stopfunc: Integer; function DosToWin(ASource: AnsiString): AnsiString; var Ch: PAnsiChar; begin Ch := AnsiStrAlloc(Length(ASource) + 1); OemToAnsi(PAnsiChar(ASource), Ch); Result := StrPas(Ch); StrDispose(Ch); end; function TForm1.GetDosOutput(const CommandLine:string): string; var SA: TSecurityAttributes; SI: TStartupInfoA; PI: TProcessInformation; StdOutPipeRead, StdOutPipeWrite: THandle; WasOK: Boolean; Buffer: array[0..255] of AnsiChar; BytesRead: Cardinal; WorkDir, Line: String; i:Integer; begin stopfunc:=0; Application.ProcessMessages; with SA do begin nLength := SizeOf(SA); bInheritHandle := True; lpSecurityDescriptor := nil; end; CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0 ); try with SI do begin FillChar(SI, SizeOf(SI), 0); cb := SizeOf(SI); dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; wShowWindow := SW_HIDE; hStdInput := GetStdHandle(STD_INPUT_HANDLE); hStdOutput := StdOutPipeWrite; hStdError := StdOutPipeWrite; end; WorkDir := ExtractFilePath(CommandLine); WasOK:=CreateProcessa(nil, PAnsiChar(AnsiString(CommandLine)), nil, nil, True, 0, nil, PAnsiChar('C:\WINDOWS\system32\'), SI, PI); //WasOK := CreateProcess(nil, PChar('C:\WINDOWS\system32\cmd.exe'), nil, nil, True, 0, nil, PChar(WorkDir), SI, PI); CloseHandle(StdOutPipeWrite); if not WasOK then raise Exception.Create('Could not execute command line!') else try Line := ''; repeat WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil); if BytesRead > 0 then begin Buffer[BytesRead] := #0; Line := Line + Buffer; if (Copy(Form1.Edit1.text,1,4) = 'ping') then begin Form1.Memo1.text := DosToWin(Line); // конвертим вывод в мемо, с ОЕМ в Анси Memo1.Perform(EM_LINESCROLL,0,Memo1.Lines.Count-1); // автопрокрутка мемо вниз ////////////////////////// пауза, чтоб не висло окно при пинге и множественных выводов консоли i := 0; while i<100 do begin sleep(12); Application.ProcessMessages; inc(i); end; //// убиваем процессы if stopfunc = 1 then begin CloseHandle(PI.hThread); CloseHandle(PI.hProcess); shellexecute(0,'Open',Pchar('taskkill'),'/im cmd.exe /f',0,SW_HIDE); shellexecute(0,'Open',Pchar('taskkill'),'/im ping.exe /f',0,SW_HIDE); Exit; end; end; end; until not WasOK or (BytesRead = 0); WaitForSingleObject(PI.hProcess, INFINITE); finally CloseHandle(PI.hThread); CloseHandle(PI.hProcess); end; finally result:=Line; CloseHandle(StdOutPipeRead); end; end; //// выполняем команду CMD procedure TForm1.Button1Click(Sender: TObject); var cmdinput, getcmdval, memotxt: string; begin Edit1.Text:= Trim(Edit1.Text); // удаляем пробелы в начале и в конце в строке ввода cmdinput:= 'cmd.exe /c ' + Edit1.Text; // текст посылаемый в функцию memotxt:= Memo1.Text; getcmdval:= GetDosOutput(cmdinput); Memo1.Text:= DosToWin(getcmdval); end; /// останавливаем выполнение CMD procedure TForm1.Button2Click(Sender: TObject); begin stopfunc:=1; end; end. Последний раз редактировалось zxen, 24.02.2013 в 11:14. |