start /wait taskkill.exe /F /IM program.exe
start program.exe
Как заставить прогу перезапустить саму себя
Нужно в проге выполнить действия требующие после себя полной переинициализации всего приложения, как бы соорудить чтото типа как в WinAmp, когда он перезапускается после установки плагинов
ну создай двойника и умри
получив новые настройки сохраняешь их в файл, чтобы при старте их учесть. потом используешь батник следующего содержания:
Код:
которы запускаешь функцией winexec('batnik.bat',0). создать батник заранее или во время выполнения твоей программы - решать тебе.
winexec(pchar(paramstr(0)),SW_SHOWNORMAL);
exitprocess(0);
а как ты будешь это реализовывать, если твоя прога должна быть запущена в единственном экземпляре? вдруг не успеешь выгрузиться.
Очень просто - в Delphi есть секции initialise и finalize. Первая отвечает за действия при запуске программы, вторая - при заверщении.
Для анализа запущенности программы производится проверка некоторых системных флагов в секции инициализации: если есть флаг - значит, выход. Так вот, если в секции финализации обнулить эти флаги, а уже потом дать команду на запуск, то другая программа решит, что она единственная, даже если первая ещё не исчезла из списков процессов системы.
т.к. ты в этом по-видимому знаток, то, пожале, объясни мне, где найти эти секции на следующем примере или как их добавить, чтобы к ним добавить нужный код:
Код:
program Project1;
uses
windows;
begin
end.
uses
windows;
begin
end.
Код:
unit Unit_name;
interface
// код
implementation
// код
initialization
// код
finalization
// код
end.
interface
// код
implementation
// код
initialization
// код
finalization
// код
end.
1. interface. Производится объявление типов, классов, глобальных функций и объектов. Также подключаются другие модули (uses). Объявленные элементы доступны в других модулях
2. implementation. Всё тоже самое, но ещё производится реализация функций и методов классов. Объявленные элементы не доступны в других модулях
3. initialization. Указанная последовательность команд выполняется в момент запуска программы. Обратите внимание - здесь не объявляются функции или переменные - они вызываются так, как вызывались бы внутри функции
4. finalization. Указанная последовательность команд выполняется в момент завершения программы
Код:
initialization // начало блока запуска
OleCheck(CoGetMalloc(1, GlobalMalloc)); // Эта команда выполнится при запуске программы
finalization // начало блока завершения
GlobalMalloc := nil; // эта команда выполнится при завершении программы
end. // конец модуля :D
OleCheck(CoGetMalloc(1, GlobalMalloc)); // Эта команда выполнится при запуске программы
finalization // начало блока завершения
GlobalMalloc := nil; // эта команда выполнится при завершении программы
end. // конец модуля :D
потому что если использовать ExitProcess то очень быстро вылетаешь из приложения
.....
ну даже если не успеешь выгрузиться и ну что дальше?.....
потому что если использовать ExitProcess то очень быстро вылетаешь из приложения
.....
ну даже если не успеешь выгрузиться и ну что дальше?.....[/QUOTE]
Проблема в том, что "быстро вылетать" из приложения может быть вредно для самого приложения :( - ситуации бывают разные. Да и быстродействие у компьютеров может различаться.
Кроме того, если рассуждать "ну даже если не успеешь" и заниматься гаданием подобным на кофейной гуще, то лучше вообще отказаться от возможности автоматического перезапуска.
Лучше сделать так, как я предлагал, в отдельном либо главном модуле
Код:
initialization[INDENT]if (Test_Running) then // Проверка возможности запуска программы
Set_Running (true); // Установка флага запущенности программы
else begin
// Программа уже запущена - отменить повторный запуск программы
end;[/INDENT]finalization[INDENT]Set_Running (false); //Снятие флага запущенности программы
if (Need_Restarting) then // Проверка требования перезапуска
Restart_Program; //Перезапуск программы
[/INDENT]end.
Set_Running (true); // Установка флага запущенности программы
else begin
// Программа уже запущена - отменить повторный запуск программы
end;[/INDENT]finalization[INDENT]Set_Running (false); //Снятие флага запущенности программы
if (Need_Restarting) then // Проверка требования перезапуска
Restart_Program; //Перезапуск программы
[/INDENT]end.
Функции Test_Running, Set_Running и Restart_Program напишите сами. По крайней мере, алгоритмы для проверки запущенности программы приведены во многих книгах по программированию.
мне кажется то, что предлагает el scorpio (или то, что я предложил) может понадобиться, если прога ищет себя по окнам или в процессах, а если проверять запущенность с помощью мьютексов, то в случае необходимости вызвать ReleaseMutex(потом то, что писал ahilles) и вновь запущенная прога работающую не обнаружит.
Кстати, я тоже в расчёте на мьютексы и им подобное код писал. Только конкретную реализацию не расписывал
мьютексы, на мой взгляд, лучший способ для определения того, запущена прога или нет.
просто сами подумайте что быстрее уничтожение процесса + выгрузка его из памяти намного быстрее чем создание процесса + загрузка его в память + всякие инициилизации
-----------------------------------------
ЛОМАТЬ - НЕ СТРОИТЬ!!!!
-----------------------------------------
просто сами подумайте что быстрее уничтожение процесса + выгрузка его из памяти намного быстрее чем создание процесса + загрузка его в память + всякие инициилизации
[/QUOTE]
Не факт, не факт :)
Статистика - вещь хорошая, но по закону подлости, ваша программа как раз и будет периодически попадать в оставшиеся 0.01% :D
Мой же способ сработает на все сто :cool:
я как раз делал такую прогу и никгода не задумывался об 0.01%
я как раз делал такую прогу и никгода не задумывался об 0.01%[/QUOTE]
Зря, зря...
"Авоська" - парень добрый - или выручит, или выучит :D
Если неприятность может случится - она случается :D
Подобные закономерности, регулярно подтверждаемые практикой, любой специалист со стажем может цитировать десятками.
хмм... а если между закрытием проги и запуском её необходимо, например, файл проги обновить.....
имеешь ввиду сам экзе файл обновить... тогда, наверное, по принципу прог, которые могут удалять сами себя, т.е. размещаешь в памяти, обновляешь файл, а потом перезапуск, вроде так, хотя может и ошибаюсь.
Забить цикл копирования обновлённой версии в исходный файл. Условие выхода из цикла - безошибочный процесс копирования, или же - пока время создания файла не станет равным времени обновлённого.
А дальше - опять запуск программы.
Код:
start /wait taskkill.exe /F /IM program.exe
copy newprog.exe program.exe
start program.exe
copy newprog.exe program.exe
start program.exe
А если программа требует "правильного" закрытия. Например, при работе с одной БД через BDE, при прерывании работы программы, база данных продолжала считаться "открытой" - соответственно, ексклюзивный доступ к ней получался невозможным :(
Или же при завершении нужно сохранить данные в файл.
Цитата:
Например, при работе с одной БД через BDE...
блин... вот тока не надо в крайности... моя прога не на столько тупая, чтобы перед вызовом этого BAT оставить открытую БД, несохраненные данные, невысвобожденную память и всё в таком духе....
всмысле обновить прогу:1) подправить пару байт; 2) полностью заменить экзе. если пункт 1, то смотри мой первый ответ на твой вопрос, если 2, то что это за необходимость полностью файл менять?
Рад за вас. Но вот только даже самая "умная" прога всё равно использует объекты ОС и файлы, которые остаются открыты во время работы - а тут ей, ни с того, ни с сего - taskkill :(.
P.S.
А причём в батнике "start /wait"? Что это означает - я знаю; просто не могу понять - зачем?
[/QUOTE]
так он же перед вызовом все, что можно закроет, а то что останется вряд ли к какой-то большой ошибке приведет - ось должна сама справиться. можно подумать, что никто зависшую прогу с помощью диспетчера задач не закрывал ни разу.
[QUOTE=el scorpio]
А причём в батнике "start /wait"? Что это означает - я знаю; просто не могу понять - зачем?[/QUOTE]
очевидно, чтобы в памяти не висели две копии проги - и в этом я с verybadbug'ом согласен - потому что две копии проги в памяти - это неправильно.
[/QUOTE]
Закрывали - только порой он закрыть файлы - закроет, а вот сохранить изменения в этих файлах не сможет :(. Так что лучше завершать программу правильно.
Если использовать taskkill с ключём /f (форсированное закрытие), то "хвосты" останутся. Если же использовать без этого ключа, то программа может не закрыться, а просто вывести сообщение типа "Вы уверены?" или "Сохранить изменения?" - соответственно, выполнение её не прервётся.
Цитата:
очевидно, чтобы в памяти не висели две копии проги - и в этом я с verybadbug'ом согласен - потому что две копии проги в памяти - это неправильно.
Дело в том, что "start /wait" в батниках используется для ожидания завершения оконных приложений. Консольные же (к числу коих относится и
Цитата:
...что это за необходимость полностью файл менять...
обновление программных модулей например....
хорошо... у меня тут ещё одна идея возникла... а что если использовать след порядок действий?
прога
1. прога создаёт батник
2. прога запускает его
3. прога закрывается
батник
1. копирование пока возникает ошибка
2. запуск проги
Протестую - это плагиат :)
Подобную идею я предложил на последнем посте страницы 2 этой темы.
Цитата:
Протестую...
хмм... действительно... а ты пробовал так делать?
Надо только вспомнить, как же правильно использовать переменную ERRORLEVEL...
1.bat
Код:
:CopyLoop
copy 1.exe 2.exe
if ERRORLEVEL 1 goto CopyLoop
start 2.exe
copy 1.exe 2.exe
if ERRORLEVEL 1 goto CopyLoop
start 2.exe
где-то в проге...
Код:
ShellExecute(Handle,
'open',
PChar(ExtractFilePath(Application.ExeName) + '1.bat'),
nil,
PChar(ExtractFilePath(Application.ExeName)),
SW_SHOWMINIMIZED);
Close;
'open',
PChar(ExtractFilePath(Application.ExeName) + '1.bat'),
nil,
PChar(ExtractFilePath(Application.ExeName)),
SW_SHOWMINIMIZED);
Close;