Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Запуск bin файла с параметрами


Автор: Ergoz 9.7.2009, 01:13
Приветствую пользователей винграда. Возникла проблема, и вопрос.
Требуется запустить bin файл (на пример ergoz.bin) который в принципе является ехешником, но быть бином ему необходимо. И есть батник, в котором прописана команда:
Код

start bin32/ergoz.bin -ip:127.0.0.1 -ng


Как можно заметить при запуске есть дополнительные параметры запуска, а именно:
Цитата

-ip:127.0.0.1

 и 
Цитата

-ng


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

Автор: Ergoz 11.7.2009, 10:47
не ужто никто не знает? очень прошу, помогите

Автор: Keeper89 11.7.2009, 13:55
Для запуска все-таки придется хотя бы временно изменить расширение на исполняемое. А параметры в ShellExecute передаются, читайте спецификацию функции.

Автор: kami 11.7.2009, 18:51
Цитата(Keeper89 @  11.7.2009,  13:55 Найти цитируемый пост)
Для запуска все-таки придется хотя бы временно изменить расширение на исполняемое.

Вовсе не обязательно.

Пример: скомпилировать проект, изменить расширение с exe на bin. После этого скомпилировать еще раз, запустить экзешник и нажать на кнопочку. Будет счастье в виде 2-х процессов с одинаковым именем и расширениями exe и bin.
Код

procedure TfrmMain.Button1Click(Sender: TObject);
var
  pi:TProcessInformation;
  si:TStartupInfo;
begin
  FillChar(si, SizeOf(TStartupInfo), 0);
  si.cb:=SizeOf(TStartupInfo);
  CreateProcess(
    nil, // в принципе, можно указать имя запускаемого файла и здесь, но тогда могут начаться проблемы с
         // передачей командной строки
    PChar(ChangeFileExt(ParamStr(0), '.bin')+' 12345'), // поэтому указываем всё в lpCommandLine
    nil,
    nil,
    False,
    CREATE_DEFAULT_ERROR_MODE,
    nil,
    nil,
    si,
    pi);
end;


P.S. вообще-то нужна еще обработка того, запустился процесс или нет... но лень smile

Добавлено через 1 минуту и 22 секунды
Цитата(Ergoz @  9.7.2009,  01:13 Найти цитируемый пост)
Я смотрел функции ShellExecute и прочие

ShellExecute не запустит, afaik, bin-файл. Выдаст стандартный запрос "а чем бы открыть этот тип файлов?"

Автор: Keeper89 11.7.2009, 19:05
kami, шикарно, про такой запуск (неисполняемых файлов как процесса) не знал - спасибо smile

Автор: Ergoz 13.7.2009, 14:34
Цитата(kami @ 11.7.2009,  18:51)
Цитата(Keeper89 @  11.7.2009,  13:55 Найти цитируемый пост)
Для запуска все-таки придется хотя бы временно изменить расширение на исполняемое.

Вовсе не обязательно.

Пример: скомпилировать проект, изменить расширение с exe на bin. После этого скомпилировать еще раз, запустить экзешник и нажать на кнопочку. Будет счастье в виде 2-х процессов с одинаковым именем и расширениями exe и bin.
Код

procedure TfrmMain.Button1Click(Sender: TObject);
var
  pi:TProcessInformation;
  si:TStartupInfo;
begin
  FillChar(si, SizeOf(TStartupInfo), 0);
  si.cb:=SizeOf(TStartupInfo);
  CreateProcess(
    nil, // в принципе, можно указать имя запускаемого файла и здесь, но тогда могут начаться проблемы с
         // передачей командной строки
    PChar(ChangeFileExt(ParamStr(0), '.bin')+' 12345'), // поэтому указываем всё в lpCommandLine
    nil,
    nil,
    False,
    CREATE_DEFAULT_ERROR_MODE,
    nil,
    nil,
    si,
    pi);
end;


P.S. вообще-то нужна еще обработка того, запустился процесс или нет... но лень smile

Добавлено @ 18:53
Цитата(Ergoz @  9.7.2009,  01:13 Найти цитируемый пост)
Я смотрел функции ShellExecute и прочие

ShellExecute не запустит, afaik, bin-файл. Выдаст стандартный запрос "а чем бы открыть этот тип файлов?"

я наверное совсем туп, но никак не получается реализовать именно запуск. Можно конечно сделать так (набросок):

Код

procedure TForm1.sButton1Click(Sender: TObject);
var
fileName : string;
myFile   : TextFile;
  begin
  fileName := 'start.bat';
  FileSetAttr(fileName, faSysFile or faHidden);
  AssignFile(myFile, fileName);
  ReWrite(myFile);
  WriteLn(myFile, '@echo off');
  WriteLn(myFile, 'bin32\ergoz.bin -ip:93.81.252.28 -ng');
  WriteLn(myFile, 'exit');
  CloseFile(myFile);
  ShellExecuteA( nil ,'open','start.bat', nil, nil, SW_SHOW);
  DeleteFile('start.bat');
end;


но к сожалению это не совсем то что мне нужно, а нужно именно напрямую без левого файла. То что приведено kami я честно пытался под себя сделать но вообще не получилось. 

Ту kami, если не трудно, можешь показать конкретный пример запуска с вышеуказанными параметрами вышеуказанного файла в папке.

Заранее спасибо!

Автор: CodeMonkey 13.7.2009, 15:45
2 kami - кавычки забыл. И первый параметр не можно, а сильно желательно указывать ;)

Автор: kami 13.7.2009, 17:11
Цитата(CodeMonkey @  13.7.2009,  15:45 Найти цитируемый пост)
2 kami - кавычки забыл

Точно smile
Цитата(CodeMonkey @  13.7.2009,  15:45 Найти цитируемый пост)
. И первый параметр не можно, а сильно желательно указывать

когда я его указывал, Delphi-приложение отказывалось понимать параметры командной строки. (код тот же, только в CreateProcess указывались отдельно файл приложения и параметр соответственно).
 smile хотя... может, дело в кавычках, действительно... позже проверю, если не забуду.

Цитата(Ergoz @  13.7.2009,  14:34 Найти цитируемый пост)
можешь показать конкретный пример запуска с вышеуказанными параметрами вышеуказанного файла в папке.

Не буду. Поменять 1 строку в приведенном мной коде... для этого не нужно два верхних образования. Без обид..
Цитата(Ergoz @  13.7.2009,  14:34 Найти цитируемый пост)
никак не получается реализовать именно запуск.

Код в студию. Будем посмотреть, что там не получается.

Добавлено через 5 минут и 1 секунду
Цитата(Ergoz @  13.7.2009,  14:34 Найти цитируемый пост)
пример запуска с вышеуказанными параметрами вышеуказанного файла в папке.

{$IFDEF offtopic}
"в соответствии с вышеизложенным ранее поименованным должностным лицам исполнить нижеуказанное"
smile  smile 
{$ENDIF}

Автор: CodeMonkey 13.7.2009, 17:36
Цитата(kami @  13.7.2009,  17:11 Найти цитируемый пост)
когда я его указывал, Delphi-приложение отказывалось понимать параметры командной строки

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

Логика такая: командная строчка (второй параметр) передаётся программе "как есть". Программа может парсить командную строчку, как ей будет угодно. Соответственно, если в командной строке вы не укажете саму программу, а только её параметры, то сама программа в них запутается: она примет первый параметр за своё имя (нет, ParamStr(0) в Delphi вызывает GetModuleFileName, но другие могут), а второй параметр (если он есть) - за первый.
Имя же программы для запуска загрузчиком ОС берётся из первого параметра, если он задан. Или пытается извлечься из второго, если нет.

Вот это "пытается извлечься" и есть причина, почему всегда рекомендуется указывать первый параметр:

CreateProcess(PChar(Application), PChar('"' + Application + '" ' + Params), ...)

Так ошибок не будет никогда. А если вы его не укажете - у вашей программы могут быть серьёзные проблемы с безопасностью. Особенно, если вы не используете кавычки.

Автор: kami 13.7.2009, 17:42
CodeMonkey, понял. Не знал о дублировании параметров, возьму на заметку. Спасибо smile 

Автор: Ergoz 13.7.2009, 21:56
Хорошо, на примере кода покажу чего я не совсем понял. Я не спорю что вообще нужно образование чтоб поправить 1 строчку, просто я когда попробовал исправить её у меня не происходило вообще ничего. Итак, вот первая версия кода которую я пробовал:

Код

procedure TfrmMain.Button1Click(Sender: TObject);
var
  pi:TProcessInformation;
  si:TStartupInfo;
begin
  FillChar(si, SizeOf(TStartupInfo), 0);
  si.cb:=SizeOf(TStartupInfo);
  CreateProcess(
    nil, // в принципе, можно указать имя запускаемого файла и здесь, но тогда могут начаться проблемы с
         // передачей командной строки
    PChar(ChangeFileExt(ParamStr(0), 'ergoz.bin')+' -ip:127.0.0.1'), // поэтому указываем всё в lpCommandLine
    nil,
    nil,
    False,
    CREATE_DEFAULT_ERROR_MODE,
    nil,
    nil,
    si,
    pi);
end;

на такой код программа по нажатию кнопки никак не реагировала,  и не производила никаких действий.

Вот на такой код:
Код

procedure TForm1.sButton1Click(Sender: TObject);
var
  pi:TProcessInformation;
  si:TStartupInfo;
begin
  FillChar(si, SizeOf(TStartupInfo), 0);
  si.cb:=SizeOf(TStartupInfo);
  CreateProcess('ergoz.bin',PChar('"' + 'aion.bin' + '" ' + '-ip:127.0.0.1'),nil,nil,False,CREATE_DEFAULT_ERROR_MODE,nil,nil,si,pi);
  end;

и на такой:
Код

procedure TfrmMain.Button1Click(Sender: TObject);
var
  pi:TProcessInformation;
  si:TStartupInfo;
begin
  FillChar(si, SizeOf(TStartupInfo), 0);
  si.cb:=SizeOf(TStartupInfo);
  CreateProcess( 'ergoz.bin', PChar(ChangeFileExt(ParamStr(0), 'ergoz.bin')+' -ip:127.0.0.1'), nil,nil,False,CREATE_DEFAULT_ERROR_MODE,nil,nil,si, pi);
end;

программа запускается (как я понимаю благодаря появлению 1 параметра с адресом запускаемой программы), но она запускается не совсем правильно, и никак не пойму в чём дело. Суть в том что если через батник запускаю такого вида:
Код

@echo off
ergoz.bin -ip:127.0.0.1 -ng
exit

то приложение, как и должно, запускается не в полном экране и без ошибок каких либо. Но если запускаю вручную в командной строке так:
Код

C:\main\game>ergoz.bin -ip:127.0.0.1

то запускается в полном экране, игнорируя все начальные конфиги программы которую запускаю, + ошибка загрузки шрифтов, т.е. неправильно (из моей программы с такими же проблемами запускается). Я никак не могу ещё понять почему так, даже когда вручную в цмд пишу запуск. бьюсь уже над этой проблемой несколько часов и никак не соображу в чём дело...

Автор: Ergoz 13.7.2009, 22:32
странно, но если в командной строке набрать 
C:\main>game\ergoz.bin -ip:127.0.0.1
то всё нормально. видимо стоит там проверка на то, откуда запускается требуемый бин, фиг знает. Но суть в том что всё заработало. спасибо всем огромное за помощь, именно эта конструкция пашет без проблем:
Код

var
  pi:TProcessInformation;
  si:TStartupInfo;
begin
  FillChar(si, SizeOf(TStartupInfo), 0);
  si.cb:=SizeOf(TStartupInfo);
  CreateProcess('bin32\aion.bin',PChar('"' + 'main\ergoz.bin' + '" ' + '-ip:127.0.0.1'),nil,nil,False,CREATE_DEFAULT_ERROR_MODE,nil,nil,si,pi);

  end;


ещё раз огромное спасибо!!!


п.с. так и не понял зачем тут нужна была эта вещь ChangeFileExt(ParamStr(0), '.bin'), т.к. без неё всё норм запустилось smile но всё равно огромное спасибо!!

Автор: kami 13.7.2009, 22:40
Цитата(Ergoz @  13.7.2009,  22:32 Найти цитируемый пост)
так и не понял зачем тут нужна была эта вещь ChangeFileExt(ParamStr(0), '.bin'), т.к. без неё всё норм запустилось

Нажать F1 на ChangeFileExt религия не позволяет? smile
Я же приводил пример для того же приложения, у которого в качестве расширения был указан не exe а bin

Автор: CodeMonkey 14.7.2009, 09:11
Код
  if not CreateProcess(...) then
    RaiseLastOSError;
 
должно помочь в поиске причины "не хачу".

Добавлено через 5 минут и 10 секунд
Ergoz: с логикой у вас серьёзные проблемы. Попробуйте объяснить самому себе: 
Цитата
CreateProcess('bin32\aion.bin',PChar('"' + 'main\ergoz.bin' ....

Автор: Ergoz 14.7.2009, 17:15
Цитата

CreateProcess('bin32\aion.bin',PChar('"' + 'main\ergoz.bin' ....


да не, там то всё норм)) это я когда тут на форуме выкладывал использовал вторую версию своей проги и решил поправить под остальную часть, и забыл первую часть исправить. Я просто делал несколько видов ланчеров для игры АЙОН. И у одного запуск у меня через мейн (у меня там специальный клиент) а второй через бин )) поэтому тут косяк только на форуме))

Автор: CodeMonkey 4.8.2009, 13:36
Вот, кстати, http://bugtraq.ru/rsn/archive/2005/11/18.html.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)