Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2012.02.05;
Скачать: [xml.tar.bz2];

Вниз

Вывод в командную строку (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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.54 MB
Время: 0.004 c
15-1318710605
Юрий
2011-10-16 00:30
2012.02.05
С днем рождения ! 16 октября 2011 воскресенье


15-1319112823
Sergey Masloff
2011-10-20 16:13
2012.02.05
midaslib в новых версиях Delphi


2-1319627705
dev888
2011-10-26 15:15
2012.02.05
помогите определиться с форматом функции


2-1319714974
Очень Злой
2011-10-27 15:29
2012.02.05
Можно ли описать запись неизвестного заранее размера


2-1319633128
Sanprof
2011-10-26 16:45
2012.02.05
Значение Series зная XPos (TChart)





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский