7

アプリケーションの複数のインスタンスを実行できないようにする必要があります。したがって、プロジェクトソースには次のものが含まれます。

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;

しかし、私の場合、ミューテックスのためにこれは機能しません。2番目のインスタンスを開始する前にミューテックスを解放しても、シャットダウンに時間がかかり、2つのインスタンスを並行して実行できないため(共通のリソースやその他の影響のため)、動作しません。

そのような特性を持つアプリケーションを再起動する方法はありますか?(可能であれば、追加の実行可能ファイルなしで)

前もって感謝します。

4

9 に答える 9

15

おそらく、あなたは箱の外で考える必要があります。ミューテックス/インスタンスロジックをいじくり回す代わりに、アプリが閉じるのを待ってから再起動する別の実行可能ファイルを作成するだけで済みます。追加のボーナスとして、後でこのメカニズムを使用して、たとえば、メインアプリのバイナリの一部を更新できます。また、同じアプリ内で異なる整合性レベルを維持する代わりに、昇格して実行する方がはるかに簡単です。

于 2010-12-21T13:47:40.100 に答える
2

再起動を試みる前にミューテックスを解放できないのはなぜですか?万が一、再起動を使用して明示的に呼び出したインスタンスの前に別のインスタンスが発生した場合でも、再起動が必要な変更を加えても、アプリは再び稼働します。他のソリューションのような複雑さは必要ないと思います。

于 2010-12-21T10:51:26.163 に答える
1

ShellExecuteにいくつかのパラメーター(たとえば、/ WaitForShutDown)を含めて、もう1つのミューテックスを作成します。プログラムの初期化の前に、たとえば.dprファイルに、次のようなものを挿入します。

if(Pos('/ WaitForShutDown'、CmdLine)<> 0)then WaitForSingleObject(ShutDownMutexHandle、INFINITE);

また、プログラムには、すべてのファイナライズと共通リソースのリリースの後に、次のようなものを含めます。

ReleaseMutex(ShutDownMutexHandle);

于 2010-12-21T10:44:39.247 に答える
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.

アプリケーションを再起動する場合は、変数Restartをtrueに設定してから、アプリケーションを終了します。

したがって、RestartMutexはプログラムセクションの最初に追加されるため、これにより、ユニットRestartMutexのファイナライズはアプリケーションのクローズのほぼ終了時にヘップされ、他のすべてのユニットはユニットRestartMutexの前にファイナライズを実行します。つまり、アプリケーションは安全に再開できます。

于 2010-12-21T11:13:16.037 に答える
0

ミューテックスを取得しようとする前、またはしばらくスリープするループでミューテックスを取得しようとする前に、「restart」などのコマンドライン引数を渡してSleep()を実行できます。

また、両方のプロセス間に通信を設定することもできますが、それはやり過ぎかもしれません。

于 2010-12-21T10:35:57.527 に答える
0

こんにちは、Zarko Gajicによる次の記事をご覧ください。ここでは、いくつかのアイデア、サンプルコード、さらには使用するコンポーネント全体を入手できます。

hth、ラインハルト

于 2010-12-21T10:50:54.847 に答える
0

を呼び出しているときに「 bInitialOwner ReleaseMutex」の「False」を渡しているため、おそらく失敗していますCreateMutex。ミューテックスの初期所有権を持っているかCloseHandle、ミューテックスハンドルを渡す「ReleaseMutex」の代わりに呼び出します。

于 2010-12-21T11:47:26.300 に答える
0

この方法でチェックアウト:

新しいアプリケーションを実行して、現在のアプリケーションを強制終了するだけです。

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

于 2015-02-11T20:25:15.443 に答える
0

(睡眠のアイデアを打ち負かす)

ミューテックスを作成する前に元のプロセスが実際に終了/クローズされていることを確認したい場合は、PIDを新しいプロセスに渡すことをお勧めします(コマンドラインが最も簡単で、他のIPCメソッドも同様に機能します)。 OpenProcess(SYNCHRONIZE、false、pid)およびWaitForSingleObject(タイムアウト付きのループを使用し(100ミリ秒が適切な値)、元のプロセスが閉じるのに時間がかかりすぎる場合はそれに応じて動作します)

上記のほかに、ミューテックスと同じユニットでRestartSelfプロシージャを作成し、そこでロジックを実行して、単一のインスタンスと再起動ロジックを同じ場所に保持することにしました(パラメーターはハードコーディングされています) 、ハードコードされたものがアプリケーション全体に散らばってほしくない。

于 2016-01-23T13:44:58.057 に答える