Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 19.09.2018, 11:14   #1
Timofey_p
Пользователь
 
Регистрация: 27.11.2016
Сообщений: 10
По умолчанию Ошибка при запуске внешней программы

Добрый день, форумчане!

Не могу понять в чём дело. Сам я любитель в программировании Delphi, на профи не претендую.
Сделал копию функции для отладки (вообще взял с просторов интернета).
Код:
function ExecAndWait1(ACmd: string; WaitTimeOut: cardinal = INFINITE): Cardinal;
var
  si: STARTUPINFO;
  pi: PROCESS_INFORMATION;
  res: BOOL;
  r: cardinal;
  p1: String;
begin
  with si do
  begin
    cb := sizeof(si);
    lpReserved := nil;
    lpDesktop := nil;
    //lpTitle := PChar('External program "' + ACmd + '"');
    dwFlags := 0;
    cbReserved2 := 0;
    lpReserved2 := nil;
  end;

//-------------------
  // 2 строки с запуском RAR (меняю местами или комментирую для тестов)
  p1 := '"C:\Program Files\WinRAR\Rar.exe" A D:\qqq.rar D:\net\*.* -agYYYY-MM-DD -r -m5 -ed -esh -inul';
  p1 := GetCurrentDir + '\Rar.exe A D:\qqq.rar D:\net\*.* -agYYYY-MM-DD -r -m5 -ed -esh -inul';
  
  // ломается на создании процесса, если подставляю первый вариант переменной p1
  res := CreateProcess(nil, PChar(p1), nil, nil, FALSE, 0, nil, nil, si, pi);
//-------------------

  if res then WaitForSingleObject(pi.hProcess, WaitTimeOut);
  GetExitCodeProcess(pi.hProcess, r);
  result := r;
end;
Чтобы не отвлекать вас полным просмотром кода выделил критическую часть между //---------------
Если использую первый вариант строки p1, то ломается на CreateProcess(...). (пробовал без двойных кавычек, не помогло)
Если использую второй вариант p1 (скопировал RAR.exe в текущую директорию), то запускается и работает.
Первый пришедший на ум вариант: UAC. Тогда я запустил скомпилированный файл от имени администратора, но тоже выходила ошибка. Значит UAC ни при чём.

Почему так происходит?
Обходной вариант нашёл, но хочу понять на будущее почему так происходит.
Timofey_p вне форума Ответить с цитированием
Старый 19.09.2018, 11:42   #2
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,238
По умолчанию

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

ещё попробуйте заменить создание архива, на, например, тестирование архива.
Serge_Bliznykov вне форума Ответить с цитированием
Старый 19.09.2018, 12:08   #3
Timofey_p
Пользователь
 
Регистрация: 27.11.2016
Сообщений: 10
По умолчанию

Не знаю какая ошибка, в консоли ничего не выводится, просто программа завершает свою работу.
Забыл написать, что пишу консольное приложение, если это важно.
При отладке BreakPoint срабатывает ещё останавливается на CreateProcess, на следующем шаге работа программы перекидывается на конец функции. А так как в программе пока только одна функция, то она завершается.
При запуске скомпилированного файла предлагает его закрыть, в подробностях ничего информативного.

Думаю, что RAR в своей папке ничего не делает, т.к. параметры ".... A D:\qqq.rar D:\net\*.* ...." предполагают архивирование папки D:\net\*.* с созданием архива D:\qqq.rar

CMD-файл отрабатывает с этой строкой всё как надо. Поэтому её и скопировал в Delphi.
Timofey_p вне форума Ответить с цитированием
Старый 19.09.2018, 12:20   #4
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 19,042
По умолчанию

Ключ w есть для папки временных файлов. Можно с ним поиграться
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 19.09.2018, 12:23   #5
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,515
По умолчанию

Цитата:
Не знаю какая ошибка, в консоли ничего не выводится, просто программа завершает свою работу.
Код:
res := CreateProcess(...
if res then ...
ELSE begin
  errcode:=GetLastError;//это сто раз да (КОД ошибки CreateProcess)
// и дальше на вывод ...
  SysErrorToMessage(errcode);// не знаю не проверял
end;
Цитата:
Думаю, что RAR в своей папке ничего не делает,
он делает что-то в ТЕКУЩЕЙ папке(рабочем каталоге)

1. при запуске из командной строки
рабочим каталогом будет какая то ТВОЯ папка (та что выводится в приглашении) --> есть право записи
2. при СreateProcess из "твоей" папки
рабочим будет опять твоя (та откуда запускаем) --> есть право записи
3. при CreateProcess из ProgramFiles
рабочим (ЕСЛИ мы его не задали принудительно, как один из ПАРАМЕТРОВ CreateProcess) будет опять же та откуда запускаем (тот самый Programs Files) --> право записи ????

проверить можешь запустив в командной строке и при этом избрав текущей папкой тот самый Programs Files(команда сd ... если что).
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 19.09.2018 в 12:41.
evg_m вне форума Ответить с цитированием
Старый 19.09.2018, 13:04   #6
Sciv
Старожил
 
Аватар для Sciv
 
Регистрация: 16.05.2012
Сообщений: 3,211
По умолчанию

UniqueString Вам в помощь:

Код:
  with si do
  begin
    cb := sizeof(si);
    lpReserved := nil;
    lpDesktop := nil;
//    lpTitle := PChar('External program "' + ACmd + '"');
    dwFlags := 0;
    cbReserved2 := 0;
    lpReserved2 := nil;
  end;


//-------------------
  // 2 строки с запуском RAR (меняю местами или комментирую для тестов)
  p1 := '"C:\Program Files\WinRAR\Rar.exe" A "D:\qqq.rar" "D:\net\*.*" -agYYYY-MM-DD -r -m5 -ed -esh -inul';
  UniqueString(p1);
//  p1 := GetCurrentDir + '\Rar.exe A D:\qqq.rar D:\net\*.* -agYYYY-MM-DD -r -m5 -ed -esh -inul';
  // ломается на создании процесса, если подставляю первый вариант переменной p1
  res := CreateProcess(nil, PChar(p1), nil, nil, FALSE, 0, nil, nil, si, pi);
//-------------------
  if res then WaitForSingleObject(pi.hProcess, INFINITE);

  GetExitCodeProcess(pi.hProcess, r);
  result := r;
Начал решать проблему с помощью регулярных выражений. Теперь решаю две проблемы...
Sciv вне форума Ответить с цитированием
Старый 19.09.2018, 13:29   #7
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,238
По умолчанию

Цитата:
Сообщение от Sciv Посмотреть сообщение
UniqueString Вам в помощь
очень сильно сомневаюсь, что это тут поможет!
Serge_Bliznykov вне форума Ответить с цитированием
Старый 19.09.2018, 13:36   #8
Sciv
Старожил
 
Аватар для Sciv
 
Регистрация: 16.05.2012
Сообщений: 3,211
По умолчанию

Цитата:
очень сильно сомневаюсь, что это тут поможет!
Я не на коленке писал, в XE2 проверил предварительно

пруф, если нужно: https://www.gunsmoker.ru/2015/01/nev...llExecute.html


Конкретная цитата из комментов:
Цитата:
ACmdLine может быть константой. Соответственно, CmdLine тоже будет константой. Счётчик ссылок у обеих будет -1 и они будут указывать на read-only память. UniqueString делает копию в куче - в памяти для чтения/записи.
В случае, описанном ТС, мы как раз таки имеем контантно заданную строку запуска приложения.
Начал решать проблему с помощью регулярных выражений. Теперь решаю две проблемы...

Последний раз редактировалось Sciv; 19.09.2018 в 13:45.
Sciv вне форума Ответить с цитированием
Старый 19.09.2018, 14:17   #9
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,238
По умолчанию

Цитата:
Сообщение от Sciv Посмотреть сообщение
Я не на коленке писал, в XE2 проверил предварительно
Понятно. Хорошо, я не буду спорить, в отличие от Вас, я не проверял.
Значит, я не прав!
Serge_Bliznykov вне форума Ответить с цитированием
Старый 22.09.2018, 08:20   #10
Timofey_p
Пользователь
 
Регистрация: 27.11.2016
Сообщений: 10
По умолчанию

Цитата:
Сообщение от evg_m Посмотреть сообщение
Код:
res := CreateProcess(...
if res then ...
ELSE begin
  errcode:=GetLastError;//это сто раз да (КОД ошибки CreateProcess)
// и дальше на вывод ...
  SysErrorToMessage(errcode);// не знаю не проверял
end;
Там всё жёсче ломается, сразу после CreateProcess(...) прыгает в конец моей функции, т.е. if res then ... и всё остальное игнорируется, видимо, try поможет.

После экспериментов у меня перестало ломаться после того как я определил первый аргумент в CreateProcess(...)
Код:
p1 := 'C:\Program Files\WinRAR\Rar.exe';
p2 := 'C:\Program Files\WinRAR\Rar.exe A D:\qqq.rar D:\net\*.* -agYYYY-MM-DD -r -m5 -ed -esh -inul';
res := CreateProcess(PChar(p1), PChar(p2), nil, nil, FALSE, 0, nil, nil, si, pi);
Но появлялся результат выполнения - 7 (Ошибка при указании параметра в командной строке). Не разбирался, как это исправить, т.к. выход найден.

UniqueString - реально помогло!

Видимо я не до конца представляю как работает CreateProcess(...) и какие папки в каких случаях используются, поэтому появлялось необработанное исключение из-за несогласованности прав и папок. (кстати, ключ -w не помог)

Всем спасибо за ответы и помощь!
Появилась информация для переваривания..
Timofey_p вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ошибка при запуске программы SLAUR Общие вопросы Delphi 6 08.09.2017 11:15
Ошибка при запуске программы lisica198808 Помощь студентам 5 08.12.2013 23:45
Ошибка при запуске программы (C++) Nonamelol Помощь студентам 2 28.09.2013 14:01
Ошибка при запуске программы mimit Общие вопросы Delphi 5 01.11.2012 23:25
Ошибка при запуске программы stakam Visual C++ 1 18.12.2010 18:19