Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Вопросы по Delphi

Автор: RoLerBooK
Дата сообщения: 17.04.2006 19:51
У меня есть вопрос.
Я в программировании не силен, поэтому возник такой вопрос.

Каким образом можно вызвать программу (которая поддерживает консоль,т.е. принимает команды вместе с вызовом ее с командной строки) с передачей ей параметров и получить ответ от нее?
Видимость вызываемой проги зависит от параметров или можно в вызове установить?

Хотелось бы пример такого увидеть.
Спасибо за внимание.
Автор: EZH
Дата сообщения: 17.04.2006 20:40
RoLerBooK

Цитата:

uses ShellApi;
...
ShellExecute(Handle,'open', 'c:\windows\notepad.exe','c:\SomeText.txt', nil, SW_SHOWNORMAL);
Автор: RoLerBooK
Дата сообщения: 17.04.2006 21:11
EZH
Спасибо за ответ, как я понял параметры передаются на месте 'c:\SomeText.txt' - ?
Мне например надо вызвать application.exe, которое вызывается следующим образом:
application.exe -r fileother.exe

Это надо сделать так?

ShellExecute(Handle,'open', 'application.exe','-r fileother.exe', nil, SW_SHOWNORMAL);

И потом в какой параметр ответ передается?
Автор: EZH
Дата сообщения: 17.04.2006 21:52
RoLerBooK
А что за ответ то? Что это вообще - ответ?

Если ты вызываешь DOS прогу, то они обычно возвращают код возврата (ERRORLEVEL), но на сколько я знаю тебе до него будет не достучаться из Delphi. Как вариант можешь наваять .bat и в нем запускать свою прогу, и в bat же и проверять ERRORLEVEL. Ну а bat вызывать из Delphi.

Если вызываемая DOS-прога написана тобой, то можно попробовать заставить её возвращать значения через переменные окружения, к которым ты в Delphi будешь иметь доступ. Или заставить это делать тот же батник.

Если под ответом проги ты понимаешь какой-то вывод текста на консоль, то можно просто его перенаправить с консоли в текстовый файл, и уже из Delphi разбирать этот текстовик.

Если же ты запускаешь Win-приложение - то тут вооще куча вариантов, надо понять что и как возвращается, что тебе нужно...
Автор: RoLerBooK
Дата сообщения: 17.04.2006 22:01
EZH
Нет прога Windows, просто работает с командной строки (вроде консолью называют, если неправильно поправьте).

Ну как она может запускать как с командной строки? меня первым делом интересует как запускать. С теми например. параметрами как я указал.

А ответ. например - код ошибки или все хорошо
Автор: SERGE_BLIZNUK
Дата сообщения: 18.04.2006 06:05
RoLerBooK
посмотрите пример запуска arj.exe для запаковки (пример консольной программы)
_http://rapidshare.de/files/18285255/TestArj.dpr.html
Как получить код ошибки - я постараюсь сегодня посмотреть.
Автор: ArtemiyUO
Дата сообщения: 18.04.2006 07:11
Если программа выводит результат своей работы в консоль то можно сделать так.
Запустить програму с параметром "progname.exe >> log.txt
после завершения работы программы в файле log.txt будет все что она вывела в консоль. Потом можно из дельфей анализировать данный файл.
Автор: RostY
Дата сообщения: 18.04.2006 08:12
RoLerBooK
uses ...ShellApi,WinProcs,WinTypes

procedure TForm1.Button1Click(Sender: TObject);
Var
s:integer;
prog: array [0..255]of char;
param: array [0..255]of char;
wrkdir: array [0..255]of char;
FProcessHnd: THandle;
FTimer:TTimer;
ExitCode:DWord;
ShellInfo:TShellExecuteInfo;
FHInstance:THandle;

begin
StrPCopy(prog,Edit1.Text);
StrPCopy(param,Edit2.Text);
StrPCopy(wrkdir,Edit4.Text);

FillChar(ShellInfo,SizeOf(TShellExecuteInfo),0);
ShellInfo.cbSize:=SizeOf(TShellExecuteInfo);
ShellInfo.fMask:=SEE_MASK_NOCLOSEPROCESS;
ShellInfo.Wnd:=HWnd_Desktop;
ShellInfo.lpFile:=prog;
ShellInfo.lpParameters:=param;
ShellInfo.lpDirectory:=wrkdir;
ShellInfo.nShow:=SW_SHOWNORMAL;

if ShellExecuteEx(@ShellInfo) then
begin
Edit3.Text:='Working';
FHInstance:=ShellInfo.hInstApp;
FProcessHnd:=ShellInfo.hProcess;
repeat
Application.ProcessMessages;
GetExitCodeProcess(FProcessHnd,ExitCode);
until (ExitCode<>still_Active);

Edit3.Text:='Terminated:'+IntToStr(ExitCode);
end;
end;

ExitCode возвращает ERRORLEVEL

Добавлено:
еще можеш использовать компонент TRZLauncher из пакета Raize
Автор: vserd
Дата сообщения: 18.04.2006 09:52
RoLerBooK
Это называется перенаправлением вывода (еще бывает перенаправление ввода).
Примеры есть в MSDN, Королевстве Delphi, Delphi World и еще на множестве сайтов.

Вот пример с Delphi World.
[more]
Delphi World - это проект, являющийся сборником статей и малодокументированных

Получить выходные данные DOS приложения
------------------------------------

Оформил: {DeeCo}
Автор: {http://www.swissdelphicenter.ch/}

Код:
{----------------------------CreateDOSProcessRedirected---------------------------
Description : executes a (DOS!) app defined in the CommandLine parameter redirected
to take input from InputFile and give output to OutputFile
Result : True on success
Parameters :
CommandLine : the command line for the app, including its full path
InputFile : the ascii file where from the app takes input
OutputFile : the ascii file to which the app's output is redirected
ErrMsg : additional error message string. Can be empty
Error checking : YES
Target : Delphi 2, 3, 4
Author : Theodoros Bebekis, email bebekis@otenet.gr
Notes :
Example call : CreateDOSProcessRedirected('C:\MyDOSApp.exe',
'C:\InputPut.txt',
'C:\OutPut.txt',
'Please, record this message')
-----------------------------------------------------------------------------------}

function CreateDOSProcessRedirected(const CommandLine, InputFile, OutputFile,
ErrMsg: string): Boolean;
const
ROUTINE_ID = '[function: CreateDOSProcessRedirected ]';
var
OldCursor: TCursor;
pCommandLine: array[0..MAX_PATH] of Char;
pInputFile, pOutPutFile: array[0..MAX_PATH] of Char;
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
SecAtrrs: TSecurityAttributes;
hAppProcess, hAppThread, hInputFile, hOutputFile: THandle;
begin
Result := False;

{ check for InputFile existence }
if not FileExists(InputFile) then
raise Exception.CreateFmt(ROUTINE_ID + #10 + #10 +
'Input file * %s *' + #10 +
'does not exist' + #10 + #10 +
ErrMsg, [InputFile]);

{ save the cursor }
OldCursor := Screen.Cursor;
Screen.Cursor := crHourglass;

{ copy the parameter Pascal strings to null terminated strings }
StrPCopy(pCommandLine, CommandLine);
StrPCopy(pInputFile, InputFile);
StrPCopy(pOutPutFile, OutputFile);

try

{ prepare SecAtrrs structure for the CreateFile calls
This SecAttrs structure is needed in this case because
we want the returned handle can be inherited by child process
This is true when running under WinNT.
As for Win95 the documentation is quite ambiguous }
FillChar(SecAtrrs, SizeOf(SecAtrrs), #0);
SecAtrrs.nLength := SizeOf(SecAtrrs);
SecAtrrs.lpSecurityDescriptor := nil;
SecAtrrs.bInheritHandle := True;

{ create the appropriate handle for the input file }
hInputFile := CreateFile(pInputFile,
{ pointer to name of the file }
GENERIC_READ or GENERIC_WRITE,
{ access (read-write) mode }
FILE_SHARE_READ or FILE_SHARE_WRITE,
{ share mode } @SecAtrrs, { pointer to security attributes }
OPEN_ALWAYS, { how to create }
FILE_ATTRIBUTE_TEMPORARY, { file attributes }
0); { handle to file with attributes to copy }


{ is hInputFile a valid handle? }
if hInputFile = INVALID_HANDLE_VALUE then
raise Exception.CreateFmt(ROUTINE_ID + #10 + #10 +
'WinApi function CreateFile returned an invalid handle value' +
#10 +
'for the input file * %s *' + #10 + #10 +
ErrMsg, [InputFile]);

{ create the appropriate handle for the output file }
hOutputFile := CreateFile(pOutPutFile,
{ pointer to name of the file }
GENERIC_READ or GENERIC_WRITE,
{ access (read-write) mode }
FILE_SHARE_READ or FILE_SHARE_WRITE,
{ share mode } @SecAtrrs, { pointer to security attributes }
CREATE_ALWAYS, { how to create }
FILE_ATTRIBUTE_TEMPORARY, { file attributes }
0); { handle to file with attributes to copy }

{ is hOutputFile a valid handle? }
if hOutputFile = INVALID_HANDLE_VALUE then
raise Exception.CreateFmt(ROUTINE_ID + #10 + #10 +
'WinApi function CreateFile returned an invalid handle value' +
#10 +
'for the output file * %s *' + #10 + #10 +
ErrMsg, [OutputFile]);

{ prepare StartupInfo structure }
FillChar(StartupInfo, SizeOf(StartupInfo), #0);
StartupInfo.cb := SizeOf(StartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
StartupInfo.wShowWindow := SW_HIDE;
StartupInfo.hStdOutput := hOutputFile;
StartupInfo.hStdInput := hInputFile;

{ create the app }
Result := CreateProcess(nil, { pointer to name of executable module }
pCommandLine,
{ pointer to command line string }
nil, { pointer to process security attributes }
nil, { pointer to thread security attributes }
True, { handle inheritance flag }
CREATE_NEW_CONSOLE or
REALTIME_PRIORITY_CLASS, { creation flags }
nil, { pointer to new environment block }
nil, { pointer to current directory name }
StartupInfo, { pointer to STARTUPINFO }
ProcessInfo); { pointer to PROCESS_INF }

{ wait for the app to finish its job and take the handles to free them later }
if Result then
begin
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
hAppProcess := ProcessInfo.hProcess;
hAppThread := ProcessInfo.hThread;
end
else
raise Exception.Create(ROUTINE_ID + #10 + #10 +
'Function failure' + #10 + #10 +
ErrMsg);

finally
{ close the handles
Kernel objects, like the process and the files we created in this case,
are maintained by a usage count.
So, for cleaning up purposes we have to close the handles
to inform the system that we don't need the objects anymore }
if hOutputFile <> 0 then CloseHandle(hOutputFile);
if hInputFile <> 0 then CloseHandle(hInputFile);
if hAppThread <> 0 then CloseHandle(hAppThread);
if hAppProcess <> 0 then CloseHandle(hAppProcess);
{ restore the old cursor }
Screen.Cursor := OldCursor;
end;
end;
Проект {Delphi World} © Выпуск 2002 - 2004
Автор проекта: {___Nikolay}
Автор: RoLerBooK
Дата сообщения: 18.04.2006 17:10
Спасибо всем кто ответил. Еще ничего не пробовал, пока остались вопросы.

SERGE_BLIZNUK
Вариант интересный. приблизительно мне это и надо. просто вызываемый процесс, не должен быть виден кроме самой программы, которая его вызвала. И в программе возможны не только работа с одним файдом. Но я думаю можно попробовать поиграться с о строками.

ArtemiyUO
Выводит в log инфу о файле и кое какие данные. Но что то много.

RostY
Я как понял, это кусок прогаммы какой-то. которая ему передает некоторые параметры. Не расшифруешь какие? И ShellExecuteEx лучше cmd? Будет работать с консолью?


vserd
Ну в первом месте работает же с DOS программой, а у меня Win приложение - консоль.

А во второй написано на С, по этому мне еще сложнее разобраться.

Ответ который выдает консоль, меня сейчас пока меньше всего интересует.

Интересно, а существует вариант при котором, этот файл я могу встроить в свое приложение (у меня нет исходника, есть сама прога) и как то работать с ней, с учетом, что встраиваемая прога - Win консоль, а встраивать нужно в Delphi программу?

P.S. Хотя наверно врядли найдется простое решение.


Автор: XPEHOMETP
Дата сообщения: 18.04.2006 17:46
Есть разные компонетны (например, ActiveX), которые позволяют взять в оборот консольную прогу: считывать вывод из консольного окна, имитировать ввод в консоль с клавиатуры и делать другие трюки. Конкретно: AppBinder:

www.doneex.com

C Delphi дружит.
Автор: RoLerBooK
Дата сообщения: 18.04.2006 18:07
XPEHOMETP
А на другом компьютере его инсталлировать обязательно? Если да, то это не подходит.

Добавлено:
В общем если можно, то скиньте исходники для Delphi какого нибудь GUI приложения написанного для управления консольным приложением.
Автор: vserd
Дата сообщения: 18.04.2006 18:38
RoLerBooK

Цитата:
vserd
Ну в первом месте работает же с DOS программой, а у меня Win приложение - консоль.

Я дал тебе ответ. DOS или консоль это не имеет никакого значения. Этот способ перехватывает StdOut и передает тебе.
Тема избитая и разжованная, у меня пересказывать желания нет. Так что вчитывайтся
http://www.delphikingdom.com/asp/nets.asp?ItemID=220.
http://www.delphikingdom.com/asp/itemq.asp?Mode=1&ItemID=448


Цитата:
Интересно, а существует вариант при котором, этот файл я могу встроить в свое приложение (у меня нет исходника, есть сама прога) и как то работать с ней, с учетом, что встраиваемая прога - Win консоль, а встраивать нужно в Delphi программу?

Можешь. Ответ есть в FAQ.

Добавлено:

Цитата:
В общем если можно, то скиньте исходники для Delphi какого нибудь GUI приложения написанного для управления консольным приложением

В общем поиск рулит.
http://www.yandex.ru/yandsearch?text=%F3%EF%F0%E0%E2%EB%E5%ED%E8%E5+%EA%EE%ED%F1%EE%EB%FC%ED%FB%EC+%EF%F0%E8%EB%EE%E6%E5%ED%E8%E5%EC&stype=www
Автор: RoLerBooK
Дата сообщения: 18.04.2006 18:57
vserd

Цитата:
Можешь. Ответ есть в FAQ.

В каком FAQ? (Это по поводу встраивания консольной программы в мою - имею только exe файл)
Или тоже поиск рулит? Сорри за то что видать достал.
Но раз ты нашел, не подскажешь ссылку?
Автор: ArtemiyUO
Дата сообщения: 19.04.2006 06:01
УРРААААААААААААААААААААА
Вышел АПДЕЙТ2
ftp://ftpd.borland.com/download/bds/bds_2006/english/arch/bds2006_en_arch_upd2.zip
Автор: RostY
Дата сообщения: 19.04.2006 08:19
RoLerBooK
Могу скинуть ГУИ-пример на мейл (напиши в ПМ).
тот кусок программы: на форме 4 едита и батон
Едит1 - название программы: rar.exe, например
Едит2 - параметры (типа -a aaa.rar *.*)
Eдит4 - рабочий каталог

в Едит3 показывается слово "working...", пока программа работает, а когда отработает - код завершения (ERRORLEVEL).

Остальное
Автор: vserd
Дата сообщения: 19.04.2006 11:25
RoLerBooK
http://www.yandex.ru/yandsearch?text=delphi%20faq
Автор: XPEHOMETP
Дата сообщения: 19.04.2006 11:38
RoLerBooK

Любые ActiveX компоненты должны регистрироваться на том компе, где они будут работать, в качестве СОМ-сервера. То есть это не полная инсталляция (с вводом регистрационного номера и проч.), а регистрация с помощью Regsvr32.exe. Она абсолютно обязательна, иначе компонент не будет работать. Вообще есть варианты компонентов такого типа, которые подключаются как DLL, их регистрировать не надо. Есть даже бесплатные или почти бесплатные (типа показывают строчку, что это trial version и урезают функции, но пользоваться можно неограниченно, если не в коммерческих целях). Если интересно, могу посмотреть, что-то у меня было такое скачано.
Автор: YFred
Дата сообщения: 19.04.2006 12:22
Подскажите пожалуйста, как или с помощью какова компанента можно упрорядочить массив записей, типа

Код:
TRecGPK=Record
N: integer;
Name: string;
end;
Автор: valerka78
Дата сообщения: 19.04.2006 12:32
YFred
А это имх тебе в ветку по Паскалю надо было постить
Если память не изменяет то
TRecGPR.Name[N] то что тебе нужно.
Поправьте, если ошибся
Автор: YFred
Дата сообщения: 19.04.2006 12:37
valerka78

Цитата:
TRecGPR.Name[N] то что тебе нужно.
- и чо это
Автор: RomanTim
Дата сообщения: 19.04.2006 13:42
YFred
Есть множество алгоритмов сортировки, я думаю не проблема найти и готовые реализации на паскале.
Если же так хочется компонент, то можешь загнать массив в TList - у него есть метод Sort
Автор: mimir
Дата сообщения: 19.04.2006 13:48
YFred
Я использую просто TStrings.
ls.AddObjects('...', Pointer(1));
ls.AddObjects('...', Pointer(2));
ls.Sort();
Автор: valerka78
Дата сообщения: 19.04.2006 13:48
YFred
Да, действительно фигня какая-то
Я просто не совсем понимаю что значит упорядочить, можешь уточнить?

Добавлено:
А это, после 100 страниц не делят ветку?

Страницы: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768

Предыдущая тема: Вероятность одинакового CRC32


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.