Re: [DELPHI]Вызов bat-файла
![](/images/graemlins/confused.gif)
видимо да...а как *.exe....help-a на execute хрен выдает(
В дельфе есть много функций для запуска внешних прог. Например, WinExec или ShellExecute.
![](/images/graemlins/cool.gif)
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, но я так никогда не делал.
данная функция использовалась в 16разрядных прогах, а в 32хразрядных не рекомендуется.
Не, ну ты реально мне глаза на мир открыл!
![](/images/graemlins/grin.gif)
![](/images/graemlins/grin.gif)
![](/images/graemlins/grin.gif)
Между прочим, это в хелпе написано.
Вот именно поэтому я и посоветовал, чтобы чел сам в хелпе всё и нашёл. Это, знаешь ли, полезнее, чем когда тебе всё разжуют.
CreateProcess
А вот этого точно не надо советовать. Человеку надо просто батничек запустить, а не париться с кучей ненужных ему параметров, вроде приоритета и т.д.
ShellExecute - вот то, что ему требуется.
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 такого не получится.
Не, ну ты реально мне глаза на мир открыл!зачем тогда советовать заведомо нехороший вариант?
Ты в дельфи строки складывать как будешь, concat'ом или вручную?
спасибо разобрался)
Ты в дельфи строки складывать как будешь, concat'ом или вручную?в большинстве случаев пишу не задумываясь str1+str2, но если строк надо сложить много и надо, чтобы это быстрее работало, начинаю думать над тем, как правильнее это сделать.
не понимаю, к чему это?
Если надо выполнить какое-либо действие над каким-то файлом/папкой средствами оболочки, используется ShellExecute, а если надо запустить приложение, то для этого существует CreateProcess. И это правильно. На машине может быть битая запись в реестре, отвечающая за действия с bat/cmd файлами, но CreateProcess всё-равно должен работать. ShellExecute же в таких случаях не будет работать корректно.
Когда мне впервые надо было воспользоваться CreateProcess, я просто взял рабочий исходник и выдрал от туда всё, что мне нужно... Несколько позже почитал внимательно в мсдн про эту функцию. Имхо, это не так плохо, когда некоторый кусок кода используется без его понимания, но с пониманием действия, которое он производит. Понимание может прийти позже. Это я к тому, что ShellExecute при кажущейся большей простоте по сравнению с CreateProcess всё-же не столь очевидна: я написал правильный вызов не с первой попытки, даже прочитав описание в мсдн.
И это правильно. На машине может быть битая запись в реестре, отвечающая за действия с bat/cmd файлами, но CreateProcess всё-равно должен работать. ShellExecute же в таких случаях не будет работать корректно.А ещё на машине может не быть строк, так что давай на всякий случай реализуй её как массив char-ов, мало ли что.
А ещё на машине может не быть строк, так что давай на всякий случай реализуй её как массив char-ов, мало ли что.бред.
Не тупи, поддержка строк осуществляется модулем system в дельфи, который всегда подключен. После того, как программа скомпилена, никакой поддержки строк на машине, на которой прога будет запускаться не требуется. Если правильно компилилось, то прога даже на голой 98й винде запустится (естественно, если прога юзает BDE, то он должен быть).
Что же касается реестра - в нём может быть что угодно.
Не тупи, строк может не быть на машине, на которой осуществляется сборка
обоснуй примером
строк может не быть на машине, на которой осуществляется сборкатоесть, это как, простите?
поддержка строк уже есть в экзешнике. Или ты предлагаешь взять дельфишную прогу и откомпилять её компилятором, который строки не поддерживает? Я тебя возможно разочарую, но компиляторы паскаля не поддерживающие строк канули в небытие задолго до того, как появилась самая первая версияю Дельфи.
Что-то мне непонятны твои доводы, приведи конкретный пример.
Или ты предлагаешь взять дельфишную прогу и откомпилять её компилятором, который строки не поддерживает?Да.
По сути это то же самое, что и брать компьютер, на котором не заработает ShellExecute.
Почему ты останавливаешься только на использовании CreateProcess вместо ShellExecute, почему бы, для большей универсальности, не переписать все строки вручную, как массивы символов - и все строковые функции тоже?
Да.Еще раз повторяю то, что я уже писал: если в реестре ошибка в разделе batfile, то твой батник не запустится так, как нужно в случае ShellExecute. Именно про такую возможность я говорю, в таком случае можно считать, что функция ShellExecute не будет работать корректно. Если ты посмотришь соответствующий раздел и воспользуешься информацией по строению соответствующих разделов реестра, ты поймешь, что в норме данная функция просто вызовет CreateProcess, у которого первый параметр будет nil, а во втором - имя bat-файла, а после него - параметры через пробел. Т.е., если использовать CreateProcess, произойдет тоже самое, но а)без лишнего лазанья по реестру, б)без вероятности ошибки в случае неправильной записи в реестре.
По сути это то же самое, что и брать компьютер, на котором не заработает ShellExecute.
Почему ты останавливаешься только на использовании CreateProcess вместо ShellExecute, почему бы, для большей универсальности, не переписать все строки вручную, как массивы символов - и все строковые функции тоже?
Я надеюсь достаточно понятно объяснил свою мысль, которую ты похоже неправильно проинтерпретировал?
То есть, я так понимаю, ошибка может возникнуть пр использовании ShellExecute("myfile" но не возникнет при использовании ShellExecute("myfile.bat")? Или что? Выражайся, пожалуйста, яснее, из твоих постов так и не понять, в чём проблема.
Если обработчиком события "Open" для файлов "*.bat" будет "noetpad %1", то ShellExecute запустит блокнот, а CreateProccess - запустит bat-файл
ты хоть раз видел, чтобы я указал в примерах file вместо file.bat ?
ну так пусть запустит cmd file.bat, а не file.bat.
ситуация совершенно аналогичная.
Поясни
![](/images/graemlins/wink.gif)
cmd может и не бытьплюс еще и это... bat файлы могут исполняться посредством интерпретатора command.com
Я имел в виду то, что при запуске exeшника или com-файла, программиста, использующего ShellExecute может постигнуть абсолютно та же участь, что и запускающего таким образом bat файл, я про битый реестр.
Бывает когда жалуются на то, что программы не запускаются... Так вот, на самом деле они запускаются, просто раздел exefile малость подпорчен. Вроде есть даже вирус, портящий соответствующий раздел.
Еще раз повторюсь. Если надо запустить программу/батник, то следует пользоваться средствами для запуска програм/батников, а если надо открыть или выполнить какое-то shell-зависимое действие над каким-нибудь файлом, имеет смысл пользоваться АПИ функцией, которая для этого предназначена.
У тебя все сложно. Правильный подход - это простой подход. ShellExecute делает то, что нужно. У полупроцента неудачников, которые зачем-то сломали себе реестр, способ не работает. Что является личными проблемами этих неудачников, а не программистов. Не стоит перекладывать проблему с больной головы на здоровую.
Я отнюдь не сторонник поиска самых простых решений применительно е Дельфи, если, конечно, это не является оптимальным вариантом. Уж слишком часто использование простого решения заставляет для расширения возможностей перелопатить кучу кода в будущем.
Ты хочешь сказать, что CreateProcess - это сложный подход, потому что для него надо ввести пару переменных и указать немного больше параметров? Не смеши
Сложнее, чем нужно, если надо запустить bat файл без дополнительных условий.
Я отнюдь не сторонник поиска самых простых решений применительно е Дельфи, если, конечно, это не является оптимальным вариантом. Уж слишком часто использование простого решения заставляет для расширения возможностей перелопатить кучу кода в будущем.
Здесь правильным подходом будет создание метода ExecuteBatFile(path : String в котором написать простое решение с ShellExecute. Если ситуация потребует более сложного решения, достаточно будет заменить код только в этом методе. Ни о каком перелопачивании кучи кода в будущем речи и не идет.
так ведь bat-файл не является приложением, он является как раз файлом.
как этот код, согласуется с таким замечанием из 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.
В языках высокого уровня имеет смысл всегда использовать настолько высокоуровневые функции, насколько это возможно.
ShellExecute и CreateProccess две обычные WinAPI-функции и уровень у них у обеих одинаково низкий. к дельфи отношения не имеющие
первая - ищет в реестре нужную команду ("open", "edit", "bla-bla-bla") и делает действия, прописанные в реестре.
вторая - запускает исполняемый файл.
мы увидем тоже самое, что указано для exefile: "%1" %*
Что означает, что ShellExecute, при выполнении "открытия" bat-файлов (как, кстати, и cmd-файлов) вызывает CreateProcess именно таким образом, каким я указал, поскольку формат вызова приложения везде один и тот-же... Еще советую взглянуть на содержимое переменной окружения PATHEXT
так ведь bat-файл не является приложением, он является как раз файлом.как я уже сказал, данные реестра это не подтверждают. Почти все остальные типы файлов (кроме .com, .exe, .cmd и .bat) запускаются через какое-либо сторонее приложение. При чем этим сторонним приложением может быть и тот-же bat-файл.
"%1" %*Однако, при удалении cmd.exe все эти bat-файлы не запускаются - " не найден файл".
Что вполне логично - .exe и .com исполняет ядро, а для .bat и .cmd нужен командный интерпретатор.
И у меня огромное подозрение, что в случае ситуации "змея кусает себя за хвост" для не .exe и не .com файлов - запускается cmd.exe с параметром из реестра.
т.е. ты активно завязываешься на недокументированные фичи, которые на тех операционках, которые не встречал, могут быть реализованы со всем по другом?.
попробуй запустить 16-битное приложение, предварительно удалив ntvdm.exe
б) 16-битные приложения не обязаны загружаться в ВиндузНТ. Разработчики лишь обещали постараться, чтобы как можно большая часть этих приложений работала, но вовсе не гарантировали (и, напротив, отрицали) такую возможность.
грубо говоря, 16-битные дос-приложения, как и bat-пакеты, не являются исполняемыми файлами в виндах. Так что ничего удивительного, что удаление одного не самого системного файла способно поломать процесс запуска: нет никакой принципиальной разницы между doc-документами, bat-документами, txt-документами и MZ-exe-документами.
Определика тогда обратное: что _является_ исполняемым файлом в виндах. Только сразу имей в виду, что managed екзешки/дллки тоже в том же самом PE лежат.
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 не даёт эффекта.
Если же делать любым из предлагаемых мною методов, то всё работает (можете попробовать на различных версиях винды).
Только объясните мне, почему если делать по документации, то не работает?
Я предпочитаю, конечно, документированные методы, но если точно по документации не получается, приходится делать то, что говорит опыт.
"Родными" исполняемыми файлами в НТ являются только те файлы, которые требуют для запуска подсистемы окружения Виндуз (csrss) и Позикс (psxss). Собственно, VDM является одним из компонентов системы виндуз, но если ты хочешь к этому придраться, то получится, что твой пример с 16-приложениями некорректен: выходит, ты собираешься покоцать систему.
![](/images/graemlins/crazy.gif)
грубо говоря, 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.
реально не пашети правильно, т.к. это соответствует cmd.exe /?
а при чем здесь вопросительный знак?
cmd.exe /?выдаёт хелп по юзанию cmd.exe =)
так в MZ или в PE?Чо? Если ты не знал, у любого PE в начале есть кусок MZ, который выводит в консоль сообщение "вам нужен виндовс", что в принципе позволяет считать произвольный PE экзешник MZ экзешником =).
Так вот, я хочу, чтобы ты попытался чётко и внятно сформулировать, что же такое "родной исполняемый файл" и как его отличить от "неродного".
Подозреваю, что если ты достаточно сильно задумаешься, то придёшь к выводу, что определение "родной исполняемый файл" некорректно/бессмысленно.
MZ-файлы используют команды дос. насколько я помню (хотя не могу в этом поклясться все они реализованы вызовами прерываний где-то порядка 20-х
PE-файлы, по идее, должны юзать команды виндуз. То есть вызывать виндузовые функции.
Я сомневаюсь, что могу четко провести разграничение этих файлов с технической точки зрения, но с практической демаркация очевидна: MS обещает поддерживать один тип файлов и не обещает поддерживать другой.
не у любого. можно сделать PE без stub
а при чем здесь вопросительный знак?к тому, что в хелпе написано, что запускать батники надо такой командой:
cmd /c batch.bat
или
cmd /k batch.bat
я думал, /c и /k - это для запуска команд.. типа, copy запустить можно только через "cmd /c copy", а исполняемые файлы - безо всякой /c
батник - такая-же команда, поэтому запускать её можно безо всяких cmd, а дальше уж винда разберётся.
Оставить комментарий
kokon77
Как вызвать из программы *.bat?