以编程方式重启Delphi应用程序

时间:2010-12-21 10:26:42

标签: delphi delphi-2010 application-restart

不应该运行我的应用程序的多个实例。因此项目源包含:

CreateMutex (nil, False, PChar (ID));
if (GetLastError = ERROR_ALREADY_EXISTS) then
  Halt;

现在我想以编程方式重新启动我的应用程序。通常的方式是:

AppName := PChar(Application.ExeName) ;
ShellExecute(Handle,'open', AppName, nil, nil, SW_SHOWNORMAL) ;
Application.Terminate;

但是由于互斥锁,这在我的情况下不起作用。即使我在启动第二个实例之前释放互斥锁也无法工作,因为关闭需要一些时间,并且两个实例不能并行运行(因为常见的资源和其他影响)。

有没有办法重新启动具有此类特征的应用程序? (如果可能,没有额外的可执行文件)

提前致谢。

9 个答案:

答案 0 :(得分:15)

也许你应该跳出框框思考。您可以简单地创建另一个可执行文件,等待您的应用程序关闭然后再次启动它,而不是使用互斥锁/实例逻辑。作为一个额外的好处,您可以稍后使用此机制,例如,更新您的一些主应用程序的二进制文件。它也更容易运行升级,而不是在同一个应用程序内保持不同的完整性级别等。

答案 1 :(得分:2)

为什么不能在尝试重启之前释放互斥锁?如果某个机会在你显式调用的那个实例之前进行了一次无关紧要的重启,那么你仍然可以让你的应用程序启动并再次运行需要重启的任何更改。我认为您不需要其他解决方案的任何复杂性。

答案 2 :(得分:1)

在ShellExecute中包含一些参数,例如/ WaitForShutDown并再创建一个互斥锁。在程序中,在初始化之前,例如,在其.dpr文件中,插入如下内容:

if(Pos('/ WaitForShutDown',CmdLine)<> 0)然后   WaitForSingleObject(ShutDownMutexHandle,INFINITE);

此外,在您的程序中,在完成所有最终确定并发布公共资源之后,请包含类似

的内容

ReleaseMutex(ShutDownMutexHandle);

答案 3 :(得分:1)

修改...

行。现在我相信我知道你的问题在哪里...... 程序单元最终确定存在问题!

尝试添加程序部分作为第一单元我的底部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,这将使得单元RestartMutex的最终确定几乎在关闭应用程序时结束,所有其他单元将在单元RestartMutex之前完成,这意味着应用程序可以启动安全了!

答案 4 :(得分:0)

您可以在尝试获取互斥锁之前传递命令行参数,例如“restart”并运行Sleep(),或尝试在一段时间内获取互斥锁。

此外,您可以在两个进程之间建立通信,但这可能有点过分。

答案 5 :(得分:0)

您可以查看以下文章by Zarko Gajic - 您将获得一些想法,示例代码甚至整个组件。

HTH, 莱因哈德

答案 6 :(得分:0)

您的ReleaseMutex可能失败,因为您在调用CreateMutex时为'bInitialOwner'传递了'False'。要么拥有互斥锁的初始所有权,要么通过您的互斥锁句柄调用CloseHandle而不是'ReleaseMutex'。

答案 7 :(得分:0)

以这种方式结账:

只需运行一个新的应用程序并杀死当前的应用程序;

http://www.delphitricks.com/source-code/windows/restart_the_own_program.html

答案 8 :(得分:0)

(打败睡眠的想法)

如果你想在创建互斥锁之前确保原始进程真正终止/关闭,那么一个想法是将PID传递给新进程(命令行是最简单的,任何其他IPC方法都可以工作) ,然后使用OpenProcess(SYNCHRONIZE,false,pid)和WaitForSingleObject(我使用带超时的循环(100毫秒是一个很好的值),如果原始进程需要很长时间才能关闭)

除了上面的内容之外,我最后还要做的是在与互斥锁相同的单元中创建一个RestartSelf过程,然后在那里执行逻辑,以便将单个实例和重新启动逻辑放在同一个地方(参数是硬编码的,你不希望硬编码的东西分散在你的应用程序中。