Перезапустите Приложение Delphi Программно
невозможно запустить несколько экземпляров моего приложения. Поэтому источник проекта содержит:
CreateMutex (nil, False, PChar (ID));
if (GetLastError = ERROR_ALREADY_EXISTS) then
Halt;
теперь я хочу перезапустить приложение программно. Обычным способом было бы:--3-->
AppName := PChar(Application.ExeName) ;
ShellExecute(Handle,'open', AppName, nil, nil, SW_SHOWNORMAL) ;
Application.Terminate;
но это не будет работать в моем случае из-за мьютекса. Даже если я выпущу мьютекс перед запуском второго instace, он не будет работать, потому что завершение работы занимает некоторое время, и два экземпляра не могут работать параллельно (из-за общих ресурсов и других эффекты.)
есть ли способ перезапустить приложение с такими характеристиками? (Если возможно без дополнительного исполняемого файла)
спасибо заранее.
9 ответов
Возможно, вам следует думать нестандартно. Вместо futzing с логикой мьютекса / экземпляра, вы можете просто создать другое исполняемый файл, который ждет закрытия вашего приложения, а затем запускает его снова. В качестве дополнительного бонуса вы можете позже использовать этот механизм, например, для обновления некоторых двоичных файлов вашего основного приложения. Также намного проще запустить его повышенным, а не поддерживать разные уровни целостности внутри одного приложения и т. д.
Почему вы не можете просто освободить мьютекс перед попыткой перезапуска? Если по какой-то случайности другой экземпляр запускается перед тем, который вы явно вызываете с перезапуском, который не имеет значения, у вас все равно будет ваше приложение снова запущено с любыми изменениями, которые потребовали перезапуска. Я не думаю, что вам нужна какая-либо сложность других решений.
включите в свой ShellExecute некоторый параметр, например, /WaitForShutDown и создайте еще один мьютекс. В вашей программе, перед инициализацией, например, в its .dpr файл, вставьте что-то вроде:
if (Pos ('/WaitForShutDown', CmdLine) 0) тогда WaitForSingleObject (ShutDownMutexHandle, INFINITE);
кроме того, в вашей программе, после все завершения и выпуска своих общих ресурсов, включая как
ReleaseMutex (ShutDownMutexHandle);
правка...
OK. Теперь я понимаю, в чем твоя проблема... У вас проблемы с доработкой программных блоков!
попробуйте добавить в раздел программы как первый блок мой нижний блок RestartMutex.
program MyProgramName;
uses
Mutex,
Forms,
...
;
unit RestartMutex;
interface
var
Restart: boolean = false;
implementation
uses
windows,
ShellApi;
var
MutexHandle: cardinal;
AppName: PChar;
const
ID = 'MyProgram';
initialization
MutexHandle := CreateMutex (nil, False, PChar (ID));
if (GetLastError = ERROR_ALREADY_EXISTS) then
Halt;
finalization
ReleaseMutex(MutexHandle);
if Restart then
begin
AppName := PChar('MyProgramName.exe') ;
ShellExecute(0,'open', AppName, nil, nil, SW_SHOWNORMAL) ;
end:
end.
когда вы хотите перезапустить приложение просто установить переменную перезагрузка true и чем завершить приложение.
Итак, потому что RestartMutex добавлен как во-первых, в разделе программы это будет означать, что финализация unit RestartMutex будет завершена почти в конце закрытия приложения, а все остальные подразделения завершат работу до unit RestartMutex, что означает, что приложение может начать безопасно снова!
вы можете передать аргумент командной строки, например "restart" и запустить Sleep (), прежде чем пытаться получить мьютекс или попытаться получить мьютекс в цикле, который спит некоторое время.
также вы можете настроить связь между обоими процессами, но это может быть излишним.
привет, взгляните на следующие статьи by Zarko Gajic - там вы получите некоторые идеи, примеры кода и даже целый компонент для использования.
hth, Рейнхард!--3-->
код ReleaseMutex
вероятно, сбой, так как вы передаете "False" для "bInitialOwner" при вызове CreateMutex
. Либо иметь начальное владение мьютексом, либо вызвать CloseHandle
вместо "ReleaseMutex" передает ваш дескриптор мьютекса.
оформить заказ таким образом:
просто запускает новое приложение и убивает currernt;
http://www.delphitricks.com/source-code/windows/restart_the_own_program.html
(отбивая идею сна)
Если вы хотите, чтобы убедиться, что исходный процесс действительно прекращен/закрытые до создания мьютекса, то один из вариантов-передать PID нового процесса (командная строка-это самый простой, и любой другой МПК метод работает так же), а затем использовать для открытия процесса(синхронизация, ложь, пид) и waitforsingleobject (я бы использовать цикл с таймаутом (100 мс-это хорошее качество) и действовать соответственно, если исходный процесс занимает слишком много времени, чтобы закрыть)
Что я закончил помимо вышеизложенного, нужно было также создать процедуру RestartSelf в том же блоке с мьютексом и сделать логику там, чтобы сохранить один экземпляр и перезапустить логику в том же месте (параметр жестко закодирован, вы не хотите, чтобы жестко закодированные вещи были разбросаны вокруг вашего приложения(приложений).