Raymond Chen のブログは、今日の私たちにとって "変わった" Windows API の側面について議論することにほぼ完全に専念しています。幸いなことに、彼はこの質問に正確に答えるブログ投稿を持っています。
16 ビット Windows には、GetInstanceData という関数がありました。この関数は、HINSTANCE、ポインター、および長さを取り、そのインスタンスから現在のインスタンスにメモリをコピーしました。(これは、ReadProcessMemory に相当する 16 ビットの一種ですが、2 番目と 3 番目のパラメーターが同じでなければならないという制限があります。)
...
これが、WinMain への hPrevInstance パラメータの理由です。hPrevInstance が NULL でない場合、それは既に実行されているプログラムのコピーのインスタンス ハンドルです。GetInstanceData を使用してそこからデータをコピーすると、すぐに立ち上がることができます。たとえば、メイン ウィンドウ ハンドルを前のインスタンスからコピーして、それと通信できるようにすることができます。
hPrevInstance が NULL であるかどうかによって、プログラムの最初のコピーであるかどうかがわかります。16 ビット Windows では、プログラムの最初のインスタンスのみがそのクラスを登録しました。2 番目以降のインスタンスは、最初のインスタンスによって登録されたクラスを引き続き使用します。(実際、試みたとしても、クラスが既に存在するため、登録は失敗します。) したがって、hPrevInstance が NULL でない場合、すべての 16 ビット Windows プログラムはクラスの登録をスキップしました。
Win32 を設計した人々は、WinMain を移植するときに、ちょっとした問題に直面しました。hPrevInstance に何を渡すか? 結局のところ、モジュール/インスタンス全体は Win32 には存在しませんでした。別のアドレス空間は、2 番目のインスタンスで再初期化をスキップしたプログラムが機能しなくなることを意味していました。そのため、Win32 は常に NULL を渡し、すべてのプログラムが最初のものであると信じ込ませます。
もちろん、hPrevInstance
互換性の理由を除いて、現在の Windows API とは無関係であるため、MSDN ではミューテックスを使用してアプリケーションの以前のインスタンスを検出することをお勧めしています。
ミューテックスは「相互排除」の略です。については、MSDN のドキュメントを参照できますCreateMutex()
。アプリケーションの以前のインスタンスを検出するためにミューテックスを使用する例はたくさんあります。基本的な考え方は、思いついた一意の名前でミューテックスを作成し、その名前付きミューテックスを作成しようとすることです。CreateMutex()
で失敗した場合ERROR_ALREADY_EXISTS
は、アプリケーションのインスタンスが既に起動されていることがわかります。