Re: [DELPHI]Вызов bat-файла

kokon77

Как вызвать из программы *.bat?

Flack_bfsp

Так же, как и *.exe?

kokon77

видимо да...а как *.exe....help-a на execute хрен выдает(

Flack_bfsp

В дельфе есть много функций для запуска внешних прог. Например, WinExec или ShellExecute.

yolki

Настоящие закоренелые апишники используют CreateProcess

Andbar

WinExec
не надо советовать это! данная функция использовалась в 16разрядных прогах, а в 32хразрядных не рекомендуется. Между прочим, это в хелпе написано.
Запускать можно через CreateProcess следующими двуми способами:

var
PMSI: TStartupInfo;
PMPI: TProcessInformation;
.....
fillchar(PMSI,sizeof(PMSI0);
PMSI.cb:=sizeof(PMSI);
if CreateProcess(
nil,//или 'C:\WINNT\system32\cmd.exe'
'path\to\file.bat parameters',//или '/C path\to\file.bat parameters'
nil,nil,false,NORMAL_PRIORITY_CLASS,nil,'starting\directory',PMSI,PMPI)=false
then messagebox(0,'error','',0);

Можно через ShellExecute, но я так никогда не делал.

Flack_bfsp

данная функция использовалась в 16разрядных прогах, а в 32хразрядных не рекомендуется.

Не, ну ты реально мне глаза на мир открыл!
Между прочим, это в хелпе написано.

Вот именно поэтому я и посоветовал, чтобы чел сам в хелпе всё и нашёл. Это, знаешь ли, полезнее, чем когда тебе всё разжуют.
CreateProcess

А вот этого точно не надо советовать. Человеку надо просто батничек запустить, а не париться с кучей ненужных ему параметров, вроде приоритета и т.д.
ShellExecute - вот то, что ему требуется.

Andbar

ShellExecute - вот то, что ему требуется.
Может я не прав, однако ShellExecute запускает CreateProcess, это во-первых. Во-вторых, CreateProcess существует для запуска приложений, а ShellExecute - для выполнения действий над файлами (в т.ч. - open). При чем, последняя - несколько более "тяжелая" функция. Если делать так, чтобы было красиво и быстро - лучше CreateProcess использовать. Если же делать так, чтобы меньше заморачиваться - пожалуйста, можно использовать такой код:
ShellExecute(
Handle,//или 0
'open',//или nil
'path\to\file.bat',
'parameters',
'path\to\starting\dir',
SW_SHOWNORMAL);

Имхо, у каждой из функций свои преимущества и недостатки.
например, с CreateProcess можно замутить следующую вещь: перехватить вывод и отправить его в Memo. С ShellExecute такого не получится.
Не, ну ты реально мне глаза на мир открыл!
зачем тогда советовать заведомо нехороший вариант?

kruzer25

Насколько я понял из твоего поста - ShellExecute - обёртка над CreateProcess, но выполняющая какие-то конкретные действия.
Ты в дельфи строки складывать как будешь, concat'ом или вручную?

kokon77

спасибо разобрался)

Andbar

Ты в дельфи строки складывать как будешь, concat'ом или вручную?
в большинстве случаев пишу не задумываясь str1+str2, но если строк надо сложить много и надо, чтобы это быстрее работало, начинаю думать над тем, как правильнее это сделать.
не понимаю, к чему это?
Если надо выполнить какое-либо действие над каким-то файлом/папкой средствами оболочки, используется ShellExecute, а если надо запустить приложение, то для этого существует CreateProcess. И это правильно. На машине может быть битая запись в реестре, отвечающая за действия с bat/cmd файлами, но CreateProcess всё-равно должен работать. ShellExecute же в таких случаях не будет работать корректно.
Когда мне впервые надо было воспользоваться CreateProcess, я просто взял рабочий исходник и выдрал от туда всё, что мне нужно... Несколько позже почитал внимательно в мсдн про эту функцию. Имхо, это не так плохо, когда некоторый кусок кода используется без его понимания, но с пониманием действия, которое он производит. Понимание может прийти позже. Это я к тому, что ShellExecute при кажущейся большей простоте по сравнению с CreateProcess всё-же не столь очевидна: я написал правильный вызов не с первой попытки, даже прочитав описание в мсдн.

kruzer25

И это правильно. На машине может быть битая запись в реестре, отвечающая за действия с bat/cmd файлами, но CreateProcess всё-равно должен работать. ShellExecute же в таких случаях не будет работать корректно.
А ещё на машине может не быть строк, так что давай на всякий случай реализуй её как массив char-ов, мало ли что.

Andbar

А ещё на машине может не быть строк, так что давай на всякий случай реализуй её как массив char-ов, мало ли что.
бред.
Не тупи, поддержка строк осуществляется модулем system в дельфи, который всегда подключен. После того, как программа скомпилена, никакой поддержки строк на машине, на которой прога будет запускаться не требуется. Если правильно компилилось, то прога даже на голой 98й винде запустится (естественно, если прога юзает BDE, то он должен быть).
Что же касается реестра - в нём может быть что угодно.

kruzer25

Не тупи, строк может не быть на машине, на которой осуществляется сборка

yolki

обоснуй примером

Andbar

строк может не быть на машине, на которой осуществляется сборка
тоесть, это как, простите?
поддержка строк уже есть в экзешнике. Или ты предлагаешь взять дельфишную прогу и откомпилять её компилятором, который строки не поддерживает? Я тебя возможно разочарую, но компиляторы паскаля не поддерживающие строк канули в небытие задолго до того, как появилась самая первая версияю Дельфи.
Что-то мне непонятны твои доводы, приведи конкретный пример.

kruzer25

Или ты предлагаешь взять дельфишную прогу и откомпилять её компилятором, который строки не поддерживает?
Да.
По сути это то же самое, что и брать компьютер, на котором не заработает ShellExecute.
Почему ты останавливаешься только на использовании CreateProcess вместо ShellExecute, почему бы, для большей универсальности, не переписать все строки вручную, как массивы символов - и все строковые функции тоже?

Andbar

Да.
По сути это то же самое, что и брать компьютер, на котором не заработает ShellExecute.
Почему ты останавливаешься только на использовании CreateProcess вместо ShellExecute, почему бы, для большей универсальности, не переписать все строки вручную, как массивы символов - и все строковые функции тоже?
Еще раз повторяю то, что я уже писал: если в реестре ошибка в разделе batfile, то твой батник не запустится так, как нужно в случае ShellExecute. Именно про такую возможность я говорю, в таком случае можно считать, что функция ShellExecute не будет работать корректно. Если ты посмотришь соответствующий раздел и воспользуешься информацией по строению соответствующих разделов реестра, ты поймешь, что в норме данная функция просто вызовет CreateProcess, у которого первый параметр будет nil, а во втором - имя bat-файла, а после него - параметры через пробел. Т.е., если использовать CreateProcess, произойдет тоже самое, но а)без лишнего лазанья по реестру, б)без вероятности ошибки в случае неправильной записи в реестре.
Я надеюсь достаточно понятно объяснил свою мысль, которую ты похоже неправильно проинтерпретировал?

kruzer25

То есть, я так понимаю, ошибка может возникнуть пр использовании ShellExecute("myfile" но не возникнет при использовании ShellExecute("myfile.bat")? Или что? Выражайся, пожалуйста, яснее, из твоих постов так и не понять, в чём проблема.

yolki

Если обработчиком события "Open" для файлов "*.bat" будет "noetpad %1", то ShellExecute запустит блокнот, а CreateProccess - запустит bat-файл

Andbar

ты хоть раз видел, чтобы я указал в примерах file вместо file.bat ?

kruzer25

ну так пусть запустит cmd file.bat, а не file.bat.

Andbar

ситуация совершенно аналогичная.

kruzer25

Поясни

yolki

cmd может и не быть

Andbar

cmd может и не быть
плюс еще и это... bat файлы могут исполняться посредством интерпретатора command.com
Я имел в виду то, что при запуске exeшника или com-файла, программиста, использующего ShellExecute может постигнуть абсолютно та же участь, что и запускающего таким образом bat файл, я про битый реестр.
Бывает когда жалуются на то, что программы не запускаются... Так вот, на самом деле они запускаются, просто раздел exefile малость подпорчен. Вроде есть даже вирус, портящий соответствующий раздел.
Еще раз повторюсь. Если надо запустить программу/батник, то следует пользоваться средствами для запуска програм/батников, а если надо открыть или выполнить какое-то shell-зависимое действие над каким-нибудь файлом, имеет смысл пользоваться АПИ функцией, которая для этого предназначена.

Helga87

У тебя все сложно. Правильный подход - это простой подход. ShellExecute делает то, что нужно. У полупроцента неудачников, которые зачем-то сломали себе реестр, способ не работает. Что является личными проблемами этих неудачников, а не программистов. Не стоит перекладывать проблему с больной головы на здоровую.

Andbar

Ты хочешь сказать, что CreateProcess - это сложный подход, потому что для него надо ввести пару переменных и указать немного больше параметров? Не смеши.
Я отнюдь не сторонник поиска самых простых решений применительно е Дельфи, если, конечно, это не является оптимальным вариантом. Уж слишком часто использование простого решения заставляет для расширения возможностей перелопатить кучу кода в будущем.

Helga87

Ты хочешь сказать, что CreateProcess - это сложный подход, потому что для него надо ввести пару переменных и указать немного больше параметров? Не смеши

Сложнее, чем нужно, если надо запустить bat файл без дополнительных условий.
Я отнюдь не сторонник поиска самых простых решений применительно е Дельфи, если, конечно, это не является оптимальным вариантом. Уж слишком часто использование простого решения заставляет для расширения возможностей перелопатить кучу кода в будущем.

Здесь правильным подходом будет создание метода ExecuteBatFile(path : String в котором написать простое решение с ShellExecute. Если ситуация потребует более сложного решения, достаточно будет заменить код только в этом методе. Ни о каком перелопачивании кучи кода в будущем речи и не идет.

Dasar

> Во-вторых, CreateProcess существует для запуска приложений, а ShellExecute - для выполнения действий над файлами (в т.ч. - open).
так ведь bat-файл не является приложением, он является как раз файлом.

Dasar

> CreateProcess(nil,//или 'C:\WINNT\system32\cmd.exe''path\to\file.bat parameters',//или '/C path\to\file.bat parameters'
как этот код, согласуется с таким замечанием из msdn?
т.е. откуда делается вывод, что если мы cmd не указываем, то это будет работать (будет запускаться bat-файл)?
To run a batch file, you must start the command interpreter; set lpApplicationName to cmd.exe and set lpCommandLine to the name of the batch file.

kruzer25

Именно я хочу сказать, что CreateProcess для этого не подходит.
В языках высокого уровня имеет смысл всегда использовать настолько высокоуровневые функции, насколько это возможно.

yolki

ты совершенно неправильно всё понял.
ShellExecute и CreateProccess две обычные WinAPI-функции и уровень у них у обеих одинаково низкий. к дельфи отношения не имеющие
первая - ищет в реестре нужную команду ("open", "edit", "bla-bla-bla") и делает действия, прописанные в реестре.
вторая - запускает исполняемый файл.

Andbar

во-первых, опыт... Во-вторых, если заглянуть в реестр, а именно в ветку HKEY_CLASSES_ROOT\batfile\shell\open\command
мы увидем тоже самое, что указано для exefile: "%1" %*
Что означает, что ShellExecute, при выполнении "открытия" bat-файлов (как, кстати, и cmd-файлов) вызывает CreateProcess именно таким образом, каким я указал, поскольку формат вызова приложения везде один и тот-же... Еще советую взглянуть на содержимое переменной окружения PATHEXT
так ведь bat-файл не является приложением, он является как раз файлом.
как я уже сказал, данные реестра это не подтверждают. Почти все остальные типы файлов (кроме .com, .exe, .cmd и .bat) запускаются через какое-либо сторонее приложение. При чем этим сторонним приложением может быть и тот-же bat-файл.

kruzer25

Радистам на заметку: у меня в HKEY_CLASSES_ROOT\batfile\shell\open\command тоже стоит
"%1" %*
Однако, при удалении cmd.exe все эти bat-файлы не запускаются - " не найден файл".
Что вполне логично - .exe и .com исполняет ядро, а для .bat и .cmd нужен командный интерпретатор.
И у меня огромное подозрение, что в случае ситуации "змея кусает себя за хвост" для не .exe и не .com файлов - запускается cmd.exe с параметром из реестра.

Dasar

> во-первых, опыт... Во-вторых, если заглянуть в реестр
т.е. ты активно завязываешься на недокументированные фичи, которые на тех операционках, которые не встречал, могут быть реализованы со всем по другом?.

Andbar

попробуй запустить 16-битное приложение, предварительно удалив ntvdm.exe

maggi14

а) ты не видишь разницы между командным шеллом и подсистемой окружения?
б) 16-битные приложения не обязаны загружаться в ВиндузНТ. Разработчики лишь обещали постараться, чтобы как можно большая часть этих приложений работала, но вовсе не гарантировали (и, напротив, отрицали) такую возможность.

maggi14

грубо говоря, 16-битные дос-приложения, как и bat-пакеты, не являются исполняемыми файлами в виндах. Так что ничего удивительного, что удаление одного не самого системного файла способно поломать процесс запуска: нет никакой принципиальной разницы между doc-документами, bat-документами, txt-документами и MZ-exe-документами.

bleyman

Определика тогда обратное: что _является_ исполняемым файлом в виндах. Только сразу имей в виду, что managed екзешки/дллки тоже в том же самом PE лежат.

Andbar

To run a batch file, you must start the command interpreter; set lpApplicationName to cmd.exe and set lpCommandLine to the name of the batch file.
классная инструкция:
procedure TForm1.Button1Click(Sender: TObject);
var
PMSI: TStartupInfo;
PMPI: TProcessInformation;
begin
fillchar(PMSI,sizeof(PMSI0);
PMSI.cb:=sizeof(PMSI);
if CreateProcess('cmd.exe','e:\tmp\1.cmd',nil,nil,false,NORMAL_PRIORITY_CLASS,nil,nil,PMSI,PMPI)=false
then messagebox(0,'error','',0);
end;
выдаёт ошибку. Заметь, по инструкции...
Если написать C:\WINNT\system32\cmd.exe, то запустится консолька с приглашением (!)
Замена cmd.exe на command.com не даёт эффекта.
Если же делать любым из предлагаемых мною методов, то всё работает (можете попробовать на различных версиях винды).
Только объясните мне, почему если делать по документации, то не работает?
Я предпочитаю, конечно, документированные методы, но если точно по документации не получается, приходится делать то, что говорит опыт.

maggi14

так в MZ или в PE?
"Родными" исполняемыми файлами в НТ являются только те файлы, которые требуют для запуска подсистемы окружения Виндуз (csrss) и Позикс (psxss). Собственно, VDM является одним из компонентов системы виндуз, но если ты хочешь к этому придраться, то получится, что твой пример с 16-приложениями некорректен: выходит, ты собираешься покоцать систему.

maggi14

реально не пашет

Andbar

грубо говоря, 16-битные дос-приложения, как и bat-пакеты, не являются исполняемыми файлами в виндах.
тем не менее,

lpApplicationName
[in] Pointer to a null-terminated string that specifies the module to execute. The specified module can be a Windows-based application. It can be some other type of module (for example, MS-DOS or OS/2) if the appropriate subsystem is available on the local computer.

Andbar

реально не пашет
и правильно, т.к. это соответствует cmd.exe /?

maggi14

а при чем здесь вопросительный знак?

Andbar

при том, что команда
cmd.exe /?
выдаёт хелп по юзанию cmd.exe =)

bleyman

так в MZ или в PE?
Чо? Если ты не знал, у любого PE в начале есть кусок MZ, который выводит в консоль сообщение "вам нужен виндовс", что в принципе позволяет считать произвольный PE экзешник MZ экзешником =).
Так вот, я хочу, чтобы ты попытался чётко и внятно сформулировать, что же такое "родной исполняемый файл" и как его отличить от "неродного".
Подозреваю, что если ты достаточно сильно задумаешься, то придёшь к выводу, что определение "родной исполняемый файл" некорректно/бессмысленно.

maggi14

знал. Но это не единственное отличие.
MZ-файлы используют команды дос. насколько я помню (хотя не могу в этом поклясться все они реализованы вызовами прерываний где-то порядка 20-х
PE-файлы, по идее, должны юзать команды виндуз. То есть вызывать виндузовые функции.
Я сомневаюсь, что могу четко провести разграничение этих файлов с технической точки зрения, но с практической демаркация очевидна: MS обещает поддерживать один тип файлов и не обещает поддерживать другой.

yolki

не у любого. можно сделать PE без stub

gopnik1994

а при чем здесь вопросительный знак?
к тому, что в хелпе написано, что запускать батники надо такой командой:
cmd /c batch.bat
или
cmd /k batch.bat

maggi14

я думал, /c и /k - это для запуска команд.. типа, copy запустить можно только через "cmd /c copy", а исполняемые файлы - безо всякой /c

Andbar

батник - такая-же команда, поэтому запускать её можно безо всяких cmd, а дальше уж винда разберётся.
Оставить комментарий
Имя или ник:
Комментарий: