On Fri, 11 Sep 2009 01:06:01 -0700
"ポケットうえだ" wrote
in message news:8EC88C86-BB85-44CA...@microsoft.com...
> 二重起動の禁止について
MSDN 2001年10月リリースで
WinMain() の説明に
hPrevInstance
アプリケーションの前のインスタンスのハンドルが入ります。
Win32 アプリケーションでは、常に NULL です。
すでに他のインスタンスが存在するかどうかを調べるには、
CreateMutex 関数を使って一意の名前の付いたミューテックスを作成してください。
CreateMutex 関数は、すでのそのミューテックスが存在していても成功しますが、
GetLastError 関数を呼び出すと ERROR_ALREADY_EXISTS が返ります。
GetLastError 関数からこの値が返された場合、既に同じアプリケーションの他のインスタンスが
存在しており、それが最初のミューテックスを作成しています。
と有るので、説明文に従って CreateMutex関数で可能です。
ポケットうえだ wrote:
> プログラム駆動中に又駆動する、いわゆる二重駆動を禁止したいのですが
> 簡単な方法があったら教えて下さい。
ちゅさんからのリプライにあるとおり、ミューテックスなどの同期オブジェクトを
使用するのが真っ当なやり方ですが、以下のようにフラグを共有メモリに置く
方法もあります。
#pragma data_seg(".shared")
volatile bool bRunning = false;
#pragma data_seg()
#pragma comment(linker, "/SECTION:.shared,RWS")
当然ながらプログラマの責任の下で排他制御しなければなりませんが、
InterlockedExchangeなど、Interlocked系のAPIを併用すればそれなりの
信頼性は確保できるかと思います。
Limiting the Number of Instances Running
http://www.codeproject.com/KB/cpp/limitnumins.aspx
--
植田システム設計事務所
Ueta System Design Studio
http://www.usdesign.jp/
植田真一
mailto:ue...@usdesign.jp
おっしゃるように、どこか共有メモリーに書いておけば、電源を落とした場合に
当然その部分が消えるので安全でしょうね。ただ、強制的にプログラムを終了
させた場合で、電源を落としていない状態では共有メモリーも当然保持されて
いることになりますが。その辺は大丈夫なんでしょうか。
ポケットうえだ wrote:
> おっしゃるように、どこか共有メモリーに書いておけば、電源を落とした場合に
> 当然その部分が消えるので安全でしょうね。ただ、強制的にプログラムを終了
> させた場合で、電源を落としていない状態では共有メモリーも当然保持されて
> いることになりますが。その辺は大丈夫なんでしょうか。
ここで言うところの「共有メモリ」は、複数の仮想アドレス空間に同じ物理メモリを
マッピングすることで実現しているものです。
たとえ共有メモリの仮想アドレスが各プロセスごとに異なっていても、実際には
同じ変数を参照しているわけです。
どこか他所に特別なメモリが用意されているわけではなく、仮想メモリの仕組み
に基づいた、ごく単純なトリックです。
裏を返せば、同じ共有メモリを参照するプロセスがすべてお亡くなりになれば、
その共有メモリも存在し得ないことになります。
# 通常のページ(4KB単位の物理メモリ)と同様、いらなくなった共有メモリの
# ページは回収され、再利用されるだけのことです。
WinMain内に記載する場合に
1.変数宣言のすぐ後に書く
2.GetMessage関数のループの直前に書く
3.CALLBACK WndProcの
WM_CREATE: に記載する
の三つが考えられます。
出来れば、二重起動の際に何事もなく起動を無視するようなのが
望ましいのですが、どうでしょうか。
デッドロック状態になってしまう可能性は避けたいのですが。
"ちゅ" からの元のメッセージ:
On Tue, 15 Sep 2009 01:29:02 -0700
"ポケットうえだ" wrote
in message news:CB51D33D-0CA9-46D0...@microsoft.com...
> Re: 二重起動の禁止について
> 1.変数宣言のすぐ後に書く
> 2.GetMessage関数のループの直前に書く
> 3.CALLBACK WndProcの
> WM_CREATE: に記載する
二重起動で破壊されそうなグローバル変数の設定前などに
チェックのコードを挿入した方が良いでしょうから
基本的に、メッセージループに入る前までに記述します。
1と2の間に記述することになるでしょう。
起動して各種環境設定や変数の設定を行っている筈なので
設定している値を破壊しない箇所としか言えません。
--
ちゅ
ご指摘のように
//エントリポイント
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR
lpCmdLine,int nCmdShow)
{
WNDCLASSEX wcex; // ウインドウクラス構造体
HWND hWnd; // ウインドウハンドル
MSG msg; // メッセージ構造体
hMutex = CreateMutex(NULL,TRUE,"reptaexe");
// 二重起動禁止のため
if( hMutex == NULL){ return(FALSE); }
// 二重起動を確認 起動を中止
if( GetLastError() == ERROR_ALREADY_EXISTS ){ return( FALSE ); }
// ウインドウクラス構造体を設定
wcex.cbSize = sizeof(WNDCLASSEX);
以下関数内省略
}
//ウインドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
中略
ReleaseMutex( hMutex ); // 二重起動禁止のための後処理
CloseHandle( hMutex ); // 二重起動禁止のための後処理
sw = DestroyWindow(hWnd);
以下ソフトの最終処理に向かう
とし、テストを行いました。
今のところ、デッドロックなど不安定な動作はしてません。