Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2012.02.05;
Скачать: CL | DM;

Вниз

Вывод в командную строку (cmd.exe)   Найти похожие ветки 

 
Faceless ©   (2011-10-27 13:09) [0]

Через командную строку запускаю приложение с определенными параметрами, приложение в зависимости от параметров выполняет некую операцию. Необходимо возвращать в комадную строку результат выполнения операции. Примера, как это делается не на нашел.


 
RWolf ©   (2011-10-27 13:12) [1]

Exit(КодВозврата);


 
RWolf ©   (2011-10-27 13:13) [2]

перепутал с Си; в паскале это Halt(retcode);


 
Ega23 ©   (2011-10-27 13:15) [3]


>  в паскале это Halt(retcode);

ExitCode := ...


 
Faceless ©   (2011-10-27 13:19) [4]

Имеется ввиду, как из MyApp.exe передать, например, строку с сообщением в командную строку.


 
Ega23 ©   (2011-10-27 13:20) [5]

writeln


 
Anatoly Podgoretsky ©   (2011-10-27 13:22) [6]

Не понятно что ты спрашиваешь, поскольку по умолчанию CMD выводит в командную строку.


 
Faceless ©   (2011-10-27 13:36) [7]

Пользователь запускает командную строку Windows (cmd.exe). Вводит MyApp.exe BackUp -StoreName="MyStore". Запускается приложение MyApp.exe (не консольное приложение). При запуске (FormCreate) необходимо проверить существование магазина "MyStore" в базе данных. Если не существует, в командной строке должно отобразиться сообщение, что-то вроде: "Операция не может быть выполнена. Магазин с именем "MyStore" не существует.".


 
Anatoly Podgoretsky ©   (2011-10-27 13:37) [8]

Выводи текст в stdout


 
Faceless ©   (2011-10-27 13:38) [9]

Как, например, по нажатию кнопки в приложении, вывести строку в командную строку Windows (cmd.exe).


 
И. Павел ©   (2011-10-27 13:40) [10]

> [7] Faceless ©   (27.10.11 13:36)

Создайте батник (тем более что ваш вызов exe будет для пользователя запутанный и не помешает сделать его более дружественным) и анализируйте код завершения программы.

MyApp.exe BackUp -StoreName="MyStore".
if errorlevel 1 (
  echo Нет такого магазина
)


 
Ega23 ©   (2011-10-27 13:47) [11]


> Anatoly Podgoretsky ©   (27.10.11 13:37) [8]
>
> Выводи текст в stdout


Разве у оконного приложения есть stdout?


 
Плохиш ©   (2011-10-27 13:53) [12]


> Faceless ©   (27.10.11 13:36) [7]

Неконсольные программы выводят свои сообщения с помощью messagebox и не надо фигнëй страдать.


 
Jeer ©   (2011-10-27 14:07) [13]


> и не надо фигнëй страдать.


Это уже не фигня, а болезнь в крайне запущенной стадии.


 
Faceless ©   (2011-10-27 14:20) [14]


> Неконсольные программы выводят свои сообщения с помощью
> messagebox и не надо фигнëй страдать.


человек хочет, чтобы была возможность выполнять административные сервисы приложения через командную строку (импорт / экспорт товаров в магизин, импорт / экспорт классификатора товаров, создание резервной копии магазина и проч.) и возвращать результат выполнения в командную строку. До меня в приложении уже была реализована вся логика по разбору параметров командной строки и запуску сервисов приложения, но все сообщения выводились через MessageBox"а. Нужно сделать так, чтобы все сообщения перенаправлять в командную строку.


 
Ega23 ©   (2011-10-27 14:23) [15]

Вот тут Розыч говорит, что можно pipe создать и через него "общаться".
Но, ИМХО, либо GUI, либо CMD.
А что мешает товарищу 2 разных приложения поставлять?


 
DiamondShark ©   (2011-10-27 14:29) [16]


> До меня в приложении уже была реализована вся логика по
> разбору параметров командной строки и запуску сервисов приложения,
>  но все сообщения выводились через MessageBox"а. Нужно сделать
> так, чтобы все сообщения перенаправлять в командную строку.

Ну так и замени MessageBox на WriteLn.


 
DiamondShark ©   (2011-10-27 14:35) [17]


> Ega23 ©   (27.10.11 14:23) [15]
> Вот тут Розыч говорит, что можно pipe создать и через него "общаться".

Передай Розычу, чтоб тему читал, а не буковки узнавал.


> Но, ИМХО, либо GUI, либо CMD.

Они не взаимоисключающие.

Собираешь приложение с ключом $APPTYPE CONSOLE.
Анализируешь параметры запуска. Если решаешь работать в пакетном режиме, пишешь всё в консоль. Если решаешь работать в граф. интерфейсе, отсоединяешься от консоли и работаешь как оконное приложение.
Утилит, которые так себя ведут, полным-полно.


 
Anatoly Podgoretsky ©   (2011-10-27 14:43) [18]


> Вот тут Розыч говорит, что можно pipe создать и через него
> "общаться".

Мало ли что он говорит, когда автор молчит.


 
Anatoly Podgoretsky ©   (2011-10-27 14:46) [19]


> Ega23 ©   (27.10.11 13:47) [11]

А разве есть достоверная информация, что у автора консольное или GUI приложение, но кроме того stdin, stdout это все чем располагает консольное приложение. А он что то говорит про вывод в косоль.


 
Ega23 ©   (2011-10-27 15:13) [20]


> А разве есть достоверная информация, что у автора консольное
> или GUI приложение


Ну если FormCreate, то явно не консоль.


 
Inovet ©   (2011-10-27 15:17) [21]

> [20] Ega23 ©   (27.10.11 15:13)
> Ну если FormCreate, то явно не консоль.

Никио не запрещает в консольном создать форму.


 
Anatoly Podgoretsky ©   (2011-10-27 15:19) [22]

> Ega23  (27.10.2011 15:13:20)  [20]

Все это должен очень точно сообщить автор


 
han_malign   (2011-10-27 15:28) [23]


> stdin, stdout это все чем располагает консольное приложение

- если бы, IMAGE_OPTIONAL_HEADER.Subsystem=WINDOWS_CUI  - определяет бытие...
(а еще stderr)

> отсоединяешься от консоли

- угу, единственный вариант - CreateProcess(...DETACHED_PROCESS...)


 
Faceless ©   (2011-10-27 15:51) [24]


> А разве есть достоверная информация, что у автора консольное
> или GUI приложение


GUI

Нашел рабочий пример чтение / запии через pipes. Только в нем процесс cmd.exe создается CreateProcess, выполняется запись / чтение и процесс завершается, а мне нужно присоединиться к уже запущеному, передать сообщение и не закрывать. как это сделать пока не понятно.


unit uChildProc;

interface

uses
Windows, SysUtils;

resourcestring
//resourcestring sSetStdHandleMsg = "Ошибка при перенаправлении стандартного ввода."#13#13"%s;
 sCreatePipeMsg = "Ошибка при создании "трубы" (Pipe)."#13#13"CreatePipe(FChildStdoutRd, FChildStdoutWr, saAttr, 0)";
 sDuplicateHandleMsg = "Ошибка при создании копии хэндла."#13#13"DuplicateHandle(GetCurrentProcess(), FChildStdoutRd, GetCurrentProcess(), @FChildStdoutRdDup, 0, False, DUPLICATE_SAME_ACCESS)";
 sCreateChildProcessMsg = "Ошибка при создании дочернего процесса."#13#13"CreateChildProcess(ExeName, CommadLine, FChildStdoutWr)";

type

 ESetStdHandleErr = class(Exception);
 ECreatePipeErr = class(Exception);
 EDuplicateHandleErr = class(Exception);
 ECreateChildProcessErr = class(Exception);

{ TChildProc }
{Класс дочернего процесса. Позволяет создать дочерний процесс и работать с его stdIn и stdOut}
 TChildProc = class(TObject)
   FChildStdoutRd: THandle;
   FChildStdoutWr: THandle;
   FChildStdinRd: THandle;
   FChildStdinWr: THandle;
 private
   function CreateChildProcess(ExeName, CommadLine: String; StdIn: THandle; StdOut: THandle): Boolean;
 public
   constructor Create(ExeName, CommadLine: String);
   destructor Destroy; override;
   function ReadStrFromChild(Timeout: Integer=1000): String;
   function WriteStrToChild(Data: String): Boolean;
 end;

implementation

{ TChildProc }

constructor TChildProc.Create(ExeName, CommadLine: String);
Var
 StdoutRdTmp, StdinWrTmp: THandle; //Временные хэндлы.
 saAttr: TSecurityAttributes;
begin
 ZeroMemory(@saAttr, SizeOf(TSecurityAttributes));
 saAttr.nLength := SizeOf(TSecurityAttributes);
 saAttr.bInheritHandle := True;
 saAttr.lpSecurityDescriptor := Nil;
 If not CreatePipe(StdoutRdTmp, FChildStdoutWr, @saAttr, 0) Then  //Создаем "читальный" Pipe
   raise ECreatePipeErr.CreateRes(@sCreatePipeMsg)
 Else
   If not CreatePipe(FChildStdinRd, StdinWrTmp, @saAttr, 0) Then  //Создаем "писальный" Pipe
     raise ECreatePipeErr.CreateRes(@sCreatePipeMsg)
   Else
     begin
       //Делаем НЕ наследуемые дубликаты хэндлов тех концов Pipe"ов, которые передаются в запускаемый процесс...
     If not DuplicateHandle(GetCurrentProcess(), StdoutRdTmp, GetCurrentProcess(), @FChildStdoutRd, 0, False, DUPLICATE_SAME_ACCESS) Then
         raise EDuplicateHandleErr.CreateRes(@sDuplicateHandleMsg)
       Else
       If not DuplicateHandle(GetCurrentProcess(), StdinWrTmp, GetCurrentProcess(), @FChildStdinWr, 0, False, DUPLICATE_SAME_ACCESS) Then
           raise EDuplicateHandleErr.CreateRes(@sDuplicateHandleMsg)
         Else
           begin
             CloseHandle(StdoutRdTmp);//Закроем наследуемый вариант "Читального" хэндла
             CloseHandle(StdinWrTmp); //Закроем наследуемый вариант "Писального" хэндла
             //Собственно создание дочернего процесса и присоединение его StdIn/Out"a к нашим Pipe"ам
            If not CreateChildProcess(ExeName, CommadLine, FChildStdinRd, FChildStdoutWr) Then
               raise ECreateChildProcessErr.CreateRes(@sCreateChildProcessMsg)
           end;
     end;
end;

function TChildProc.CreateChildProcess(ExeName, CommadLine: String; StdIn,
 StdOut: THandle): Boolean;
Var
 piProcInfo: TProcessInformation;
 siStartInfo: TStartupInfo;
begin
// Set up members of STARTUPINFO structure.
 ZeroMemory(@siStartInfo, SizeOf(siStartInfo));
 siStartInfo.cb := SizeOf(siStartInfo);
 siStartInfo.hStdInput := StdIn;
 siStartInfo.hStdOutput := StdOut;
siStartInfo.dwFlags := STARTF_USESTDHANDLES;
  Result := CreateProcess(Nil,
     PChar(ExeName + " " + CommadLine),       // command line
     Nil,          // process security attributes
     Nil,          // primary thread security attributes
     TRUE,         // handles are inherited
     0,            // creation flags
     Nil,          // use parent"s environment
     Nil,          // use parent"s current directory
     siStartInfo,  // STARTUPINFO pointer
     piProcInfo);  // receives PROCESS_INFORMATION
end;

destructor TChildProc.Destroy;
begin
//Закрываем хэндлы пайпов
 CloseHandle(FChildStdoutRd);
 CloseHandle(FChildStdoutWr);
 CloseHandle(FChildStdinRd);
 CloseHandle(FChildStdinWr);
end;

function TChildProc.ReadStrFromChild(Timeout: Integer): String;
Const
 SleepDevider = 10; //Делим весь таймаут на "кусочки" по (Timeout / SleepDevider) мс
Var
i: Integer;
dwRead, BufSize, DataSize: DWORD;
 Res: Boolean;
 SleepTime: Integer;
begin
Try
   SleepTime := Timeout div SleepDevider;
   Repeat
     For i := 0 to SleepDevider - 1 do  //Ждем данные
      begin
        Res := PeekNamedPipe(FChildStdoutRd, nil, 0, nil, @DataSize, nil);
         Res := Res and (DataSize > 0);
         If Res Then
           Break;
         Sleep(SleepTime);
       end;
     If Res Then  //Если есть данные
       begin
         BufSize := Length(Result);
         SetLength(Result, BufSize + DataSize);
       Res := ReadFile(FChildStdoutRd, Result[BufSize + 1], DataSize, dwRead, Nil);
       end;
   Until not Res;
 Except
  Result := "Read Err!";
 End;
end;

function TChildProc.WriteStrToChild(Data: String): Boolean;
Var
dwWritten, BufSize: DWORD;
 chBuf: PChar;
begin
//Обратите внимание на #13#10!!! Без них - будет работать с ошибками. Многие (но не все!) процессы ждут этих символов для обработки ввода
//Это пара символов (конец строки и перевод каретки - CR/LF)
//Вообще-то можно обойтись только LF(#10) или вообще ничем (для некоторых юниксоидных творений), но это самый надежный вариант.
//Но помните! Программы бывают разные поэтому в некоторых случаях может потребоваться поиграться с символами завершения ввода.
 chBuf := PChar(Data + #13#10);
 BufSize := Length(chBuf);
 Result := WriteFile(FChildStdinWr, chBuf^, BufSize, dwWritten, Nil);
 Result := Result and (BufSize = dwWritten);
end;

end.
 


procedure TForm1.Button1Click(Sender: TObject);
Var
 i: Integer;
begin
 With TChildProc.Create(Edit1.Text, "") do
   Try
     For i:=0 to Memo2.Lines.Count-1 do
       WriteStrToChild(Memo2.Lines[i]);
     Memo1.Lines.Add(ReadStrFromChild(500));
   Finally
     Free;
   End;
end;


 
Anatoly Podgoretsky ©   (2011-10-27 15:53) [25]


>
> > Anatoly Podgoretsky ©   (27.10.11 13:37) [8]
> >
> > Выводи текст в stdout
>
>
> Разве у оконного приложения есть stdout?

Посмотри CreateProcess и найдешь если захочешь.


 
DiamondShark ©   (2011-10-27 16:44) [26]


> han_malign   (27.10.11 15:28) [23]


> > отсоединяешься от консоли
>  - угу, единственный вариант - CreateProcess(...DETACHED_PROCESS...)

Есть FreeConsole функция.


 
han_malign   (2011-10-27 17:24) [27]


> Есть FreeConsole функция.

- к сожалению консоль родительского процесса после этого не разблокирется...



Страницы: 1 вся ветка

Текущий архив: 2012.02.05;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.007 c
15-1319009052
Handle
2011-10-19 11:24
2012.02.05
перевести фразу


2-1319447555
Laguna
2011-10-24 13:12
2012.02.05
Ввод в TЕdit руками или сканером штрихкода.


15-1318859876
lextasy
2011-10-17 17:57
2012.02.05
Посоветуйте учебник по Delphi для школьника


2-1319653394
Дмитрий
2011-10-26 22:23
2012.02.05
Проблемы c Firebird


15-1318797003
Юрий
2011-10-17 00:30
2012.02.05
С днем рождения ! 17 октября 2011 понедельник