EnumProcesses - 奇怪的行为

时间:2017-06-06 23:01:05

标签: c++ windows shell api

使用WIndows API函数EnumProcesses()

时,我有一些奇怪的行为

我有一个函数可以确定某个名称的进程是否已经在运行,哪个传递不同的结果,我手动打开.executable(双击)或通过shell打开它。

当我通过shell打开它时,它检测到它只运行一次(本身),一切都很好。当我在.exe文件上使用doubleclick打开它时,但该函数返回true(已经在运行),因为循环列出了两次相同的进程。

对于以下代码剪切,请提及:

this->thisExecutableFile

包含argv [0](从运行程序初始化)以获取自己的进程名称,如下所示:

int main(int argc, char* argv[])
{
    ClientUpdate* update = ClientUpdate::getInstance();
    update->setThisExecutableFile(argv[0]);
    if (update->clientUpdateProcessIsRunning() == false) {
    ...

我的目标是找出此进程的另一个实例是否已在运行,在这种情况下退出它。

这是我的代码:

bool ClientUpdate::clientUpdateProcessIsRunning()
{
    bool retVal = false;

    uint16_t processCount = 0;
    unsigned long aProcesses[1024], cbNeeded, cProcesses;
    if(!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
        return false;

    cProcesses = cbNeeded / sizeof(unsigned long);

    for(unsigned int i = 0; i < cProcesses; i++) {
        if (aProcesses[i] == 0) {
            continue;
        }

        HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, aProcesses[i]);
        wchar_t buffer[50];
        GetModuleBaseNameW(hProcess, 0, buffer, 50);
        CloseHandle(hProcess);

        std::wstring tempBuffer(buffer);
        std::string tempStringBuffer(tempBuffer.begin(), tempBuffer.end());
        boost::filesystem::path p(this->thisExecutableFile);
        if(_strcmpi(p.filename().string().c_str(), tempStringBuffer.c_str()) == 0) {
            processCount++;
            if(processCount > 1) {
                retVal = true;
                break;
            }
        }
    }

    return retVal;
}

我知道在文件上使用doubleclick或通过shell调用它时,基本路径是不同的。 (shell只生成文件名,而doubleclick将整个路径+文件名传递给argv [0])但我用

修复了这个问题
boost::filesystem::path p(this->thisExecutableFile);
p.fileName()

在我使用print检查的两种情况下,返回正确的文件名(没有路径)。

我很困惑为什么EnumProcesses()在通过doubleclick而不是shell调用文件时两次返回相同的文件。它没有产生两个处理过的,在任务管理器中我也没有看到这样的东西。

这是一个错误还是我需要了解一些我在文档中找不到的方法?

1 个答案:

答案 0 :(得分:1)

感谢理查德克里滕的暗示,我能够解决它。我的方法现在变得更小,更容易。 (也可能还有更多的性能,然后扫描整个进程堆栈。):D

这是解决方案

bool ClientUpdate::clientUpdateProcessIsRunning()
{

    HANDLE hMutex = CreateMutexA(NULL, TRUE, "client-updater-mtx");
    DWORD dwErr = GetLastError();
    return dwErr == ERROR_ALREADY_EXISTS;
}

谢谢!