ローカル Windows システムで実行されているプロセスのインスタンス数を知る必要があります。C++/MFC/WinAPI を使用して実行できる必要があります。では、これを行うための信頼できる方法は何ですか?
そのためにプロセスIDを使用することを考えていました。これは、プロセスがアクセスできる共有メモリ配列にリストとして保存されます。しかし問題は、プロセスが閉じられたりクラッシュしたりしたときに、そのプロセス ID が再利用されるのはどのくらいの時間になるのかということです。
プロセスのインスタンス数を制限しようとしている場合は、セマフォを使用できます。
ここで詳細を読むことができます:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686946(v=vs.85).aspx
簡単に言えば、セマフォは現在のカウントと最大カウントで初期化されます。プロセスの各インスタンスは、セマフォを取得するときにカウントを減らします。n 番目のプロセスがそれを取得しようとしたが、カウントがゼロに達した場合、そのプロセスは取得に失敗し、終了するか、適切なアクションを実行できます。
次のコードは、あなたがしなければならないことの要点を与えるはずです:
#include <windows.h>
#include <stdio.h>
// maximum number of instances of your process
#define MAX_INSTANCES 10
// name shared by all your processes. See http://msdn.microsoft.com/en-us/library/windows/desktop/aa382954(v=vs.85).aspx
#define SEMAPHORE_NAME "Global\MyProcess"
// access rights for semaphore, see http://msdn.microsoft.com/en-us/library/windows/desktop/ms686670(v=vs.85).aspx
#define MY_SEMAPHORE_ACCESS SEMAPHORE_ALL_ACCESS
DWORD WINAPI ThreadProc( LPVOID );
int main( void )
{
HANDLE semaphore;
// Create a semaphore with initial and max counts of MAX_SEM_COUNT
semaphore = CreateSemaphore(
NULL, // default security attributes
MAX_INSTANCES, // initial count
MAX_INSTANCES, // maximum count
SEMAPHORE_NAME );
if (semaphore == NULL)
{
semaphore = OpenSemaphore(
MY_SEMAPHORE_ACCESS,
FALSE, // don't inherit the handle for child processes
SEMAPHORE_NAME );
if (semaphore == NULL)
{
printf("Error creating/opening semaphore: %d\n", GetLastError());
return 1;
}
}
// acquire semaphore and decrement count
DWORD acquireResult = 0;
acquireResult = WaitForSingleObject(
semaphore,
0L); // timeout after 0 seconds trying to acquire
if(acquireResult == WAIT_TIMEOUT)
{
printf("Too many processes have the semaphore. Exiting.");
CloseHandle(semaphore);
return 1;
}
// do your application's business here
// now that you're done release the semaphore
LONG prevCount = 0;
BOOL releaseResult = ReleaseSemaphore(
semaphore,
1, // increment count by 1
&prevCount );
if(!releaseResult)
{
printf("Error releasing semaphore");
CloseHandle(semaphore);
return 1;
}
printf("Semaphore released, prev count is %d", prevCount);
CloseHandle(semaphore);
return 0;
}
この質問で説明されている方法を使用して、プロセスの名前でプロセス ハンドルを取得できます。これはプロセス ウォーキングと呼ばれます。これは、プロセス ID やファイル パスよりも信頼性が高くなります。
この回答のバリエーションは、あなたが探しているものです。でプロセスをループしProcess32Next
、 で同じ名前のプロセスを探しますMatchProcessName
。私が提供したリンクの例とは異なり、同じ名前のプロセスのリストを数えたり作成したりすることになりますが、それは些細な追加です。
プロセスとスレッドの識別子は、すべてのハンドルが閉じられた後いつでも再利用できます。プロセス ID が再利用できるようになるのはいつですか?を参照してください。詳細については、
ただし、{識別子、プロセス開始時刻}のペアを保存する場合は、これらのあいまいさを解決して、識別子の再利用を検出できます。名前付きファイル マッピングを作成してプロセス間で情報を共有し、IPC を使用してこの共有データへのアクセスを同期できます。
さて、あなたのソリューションはあまり信頼できません。PID は、後でいつでも OS によって再利用できます。すべてのプロセスを調べて、それらのコマンド ライン文字列 (実行可能ファイルのパス) をプロセスのコマンド ライン文字列と比較することで、一度実行しました。かなりうまく機能します。
バッチ ファイルを介して起動されるプログラム (一部の Java アプリ/サーバーなど) には特に注意が必要です。
他のソリューションには、おそらく名前付きパイプ、ソケット、共有メモリ(あなたが述べたように)を介したIPCが含まれます。しかし、どれも実装と保守がそれほど簡単ではありません。