Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用c+;计算Windows上进程运行实例的可靠方法+/WinAPI_C++_Windows_Winapi_Pid - Fatal编程技术网

C++ 使用c+;计算Windows上进程运行实例的可靠方法+/WinAPI

C++ 使用c+;计算Windows上进程运行实例的可靠方法+/WinAPI,c++,windows,winapi,pid,C++,Windows,Winapi,Pid,我需要知道本地Windows系统上运行了多少个进程实例。我需要能够使用C++/MFC/WinAPI来完成它。那么,什么是可靠的方法呢 我在考虑使用进程ID来实现这一点,它作为一个列表存储在一个共享内存数组中,进程可以访问该数组。但问题是,当一个进程关闭或崩溃时,它的进程ID多久才能被重用?好吧,您的解决方案不是很可靠。PIDs可以在以后的任何时候被操作系统重用。 我通过遍历所有进程并将它们的命令行字符串(可执行文件的路径)与我的进程的命令行字符串进行比较,完成了一次。效果很好 对于通过批处理文件

我需要知道本地Windows系统上运行了多少个进程实例。我需要能够使用C++/MFC/WinAPI来完成它。那么,什么是可靠的方法呢


我在考虑使用进程ID来实现这一点,它作为一个列表存储在一个共享内存数组中,进程可以访问该数组。但问题是,当一个进程关闭或崩溃时,它的进程ID多久才能被重用?

好吧,您的解决方案不是很可靠。PIDs可以在以后的任何时候被操作系统重用。 我通过遍历所有进程并将它们的命令行字符串(可执行文件的路径)与我的进程的命令行字符串进行比较,完成了一次。效果很好

对于通过批处理文件启动的程序(如一些java应用程序/服务器),应格外小心


其他解决方案涉及IPC,可能通过命名管道、套接字和共享内存(如您所述)。但是它们都没有那么容易实现和维护。

您可以使用中描述的方法,通过进程名称来捕获进程句柄。它叫。这将比进程id或文件路径更可靠


你要找的是一种变化。只需使用
Process32Next
循环遍历进程,并使用
MatchProcessName
查找具有相同名称的进程。与我提供的链接中的示例不同,您需要计算或创建具有相同名称的进程列表,但这只是一个简单的添加。

在关闭所有句柄后,可以随时重用进程和线程标识符。有关这方面的更多信息,请参阅


但是,如果要存储一对{identifier,process start time},则可以解决这些歧义并检测标识符重用。您可以创建命名文件映射以在进程之间共享信息,并使用IPC同步对此共享数据的访问。

如果您试图将进程实例的数量限制在某个数量,则可以使用信号量。
您可以在此处详细阅读:

简而言之,信号量是用当前计数和最大计数初始化的。进程的每个实例在获取信号量时都会减少计数。当第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;
}
#包括
#包括
//进程的最大实例数
#定义最多10个实例
//所有进程共享的名称。看见http://msdn.microsoft.com/en-us/library/windows/desktop/aa382954(v=vs.85).aspx
#定义信号量\u名称“Global\MyProcess”
//信号量的访问权限,请参阅http://msdn.microsoft.com/en-us/library/windows/desktop/ms686670(v=vs.85).aspx
#定义我的\u信号量\u访问信号量\u所有\u访问
DWORD WINAPI ThreadProc(LPVOID);
内部主(空)
{
处理信号量;
//创建一个信号量,初始计数和最大计数为max_SEM_COUNT
信号量=创建信号量(
NULL,//默认安全属性
最大实例数,//初始计数
最大实例数,//最大计数
信号量(名称);
if(信号量==NULL)
{
信号量=开放信号量(
我的信号量访问,
FALSE,//不继承子进程的句柄
信号量(名称);
if(信号量==NULL)
{
printf(“创建/打开信号量时出错:%d\n”,GetLastError());
返回1;
}
}
//获取信号量和减量计数
DWORD ESULT=0;
收单机构结果=WaitForSingleObject(
信号灯,
0L);//尝试获取0秒后超时
如果(收单机构结果==等待\u超时)
{
printf(“太多进程具有信号量。正在退出”);
关闭手柄(信号灯);
返回1;
}
//在这里处理您的应用程序
//现在您已经完成了释放信号灯
长prevCount=0;
BOOL releaseResult=释放信号量(
信号灯,
1,//按1递增计数
&prevCount);
如果(!releaseResult)
{
printf(“错误释放信号量”);
关闭手柄(信号灯);
返回1;
}
printf(“信号量已释放,上一计数为%d”,上一计数);
关闭手柄(信号灯);
返回0;
}

谢谢分享。尽管我对比较文件路径非常谨慎,因为有很多方法可以启动进程。示例:短文件名、虚拟文件夹、网络共享等。我不是说你应该在应用程序中硬编码路径。然而,你是对的。如果你的应用程序是独立的和可移植的(可以复制到网络共享、USB驱动器等),那么这也确实不可靠。我猜你被某种形式的IPC困住了,不管你觉得哪个更方便。很好。非常感谢。我没有考虑使用进程开始时间。那么,我需要什么API来获取它呢?在某个时刻,您将在共享内存中使用某些值初始化数组(静态“当前时间”初始化一次),因此,如果您在数组上看到另一个具有相同标识符但时间不同的条目,您将作为一个已完成的进程来清理它。事实上,仔细地做这件事,你就能在没有时间的情况下完成这件事。只是初始化代码需要清理可能存在的具有相同id(如果有的话)的先前进程引用。还要注意PSAPI进程行走答案,它也可能是一个有用的替代选项。另外,
GetProcessTimes
可以获得进程创建时间。是的,我也找到了它。比如说,如果我将从GetProcessTimes()获取的PID和FILETIME ftCreationTime成对存储在共享内存数组中。然后说,为了检查进程是否仍然处于活动状态,我在PID上执行OpenProcess(),并使用进程句柄调用GetProcessTimes()以获取cr