Форум: "Начинающим";
Текущий архив: 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