关于c ++:GetModuleFileNameEx,访问被拒绝错误

GetModuleFileNameEx, Access Denied Error

我正在尝试获取所有打开进程的名称。 这就是我所拥有的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
   #include"stdafx.h"
#include <Psapi.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int iCmdShow)
{
    bool _result;
    DWORD *pProcessIds = new DWORD[1000];
    DWORD cb;
    DWORD pBytesReturned;

    _result =  EnumProcesses(pProcessIds, 1000, &pBytesReturned);

    HANDLE hndProccesse;


    for (int i = 0; i < pBytesReturned / sizeof(DWORD); ++i)
    {
        hndProccesse =   OpenProcess(STANDARD_RIGHTS_ALL,  false, *pProcessIds);
        DWORD _len;

        DWORD _len2 =0;
        LPWSTR lpFilename = new WCHAR[100];
        _len =GetModuleFileNameEx(hndProccesse,NULL, lpFilename, _len2);
        DWORD _errr;
        _errr =  GetLastError();
        MessageBox(NULL, lpFilename, NULL, 0);
        CloseHandle(hndProccesse);

        pProcessIds ++;



    }

    return 0;
}

一切正常,直到GetModuleFileNameEx给出访问被拒绝错误(5)。

这也是消息框中显示的内容:
enter image description here

有任何想法吗?


GetModuleFileNameEx()的第四个参数必须是在第三个参数中传递的数组的大小。您传入_len2。但是,您将_len2设置为零,而不是lpFilename数组的大小(100)。因此,GetModuleFileNameEx()认为它无关紧要,甚至不接触您的lpFilename数组。堆数据不一定要初始化为零,因此lpFilename仍然包含随机垃圾,因此是随机消息框的内容。

我想猜想GetModuleFileNameEx()返回零是因为它不需要写任何东西,但是由于没有任何失败而没有设置最后的错误代码,因此该程序的较早部分遗留下了拒绝访问错误。

更多注意事项:

请记住,乔纳森·波特(Jonathan Potter)所说的有关检查Windows API函数返回的错误的正确方法。您从_len中的GetModuleFileNameEx()返回值。 MSDN说GetModuleFileNameEx()会返回零错误。因此,在获取最后的错误值之前,您需要检查_len以查看其是否等于零,否则它将没有意义。如前所述,GetModuleFileNameEx()如果成功,则不必清除最后一个错误值。

HANDLE hndProccesse = new HANDLE;绝对是错误的,但不是程序中的错误(尽管这是内存泄漏!)。 HANDLE本身是一个指针,这就是允许new运行的原因。但是这样做是没有意义的,因为HANDLE由操作系统返回,通常不应用作指针。而是将它们视为不透明值。

关于内存泄漏,您永远不会delete[]在循环中创建的每个lpFilename,也不会delete[] pProcessIds。对于您上面发布的小程序来说,这可能并不重要,但是如果您的程序不断增长,那么您肯定会解决该问题。

通常,使用MAX_PATH作为文件名缓冲区的标称长度而不是100。这是各种Shell函数使用的名称。 (更长的时间也不会伤害,但是会更短。)


您需要使用FormatMessage获得有用的错误描述。下面显示了一个示例。此示例与您的示例完全相同,但所做的只是合并了错误检查。它不能解决问题!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <windows.h>
#include <Psapi.h>

void ShowError(DWORD err)
{
    LPTSTR lpMsgBuf = nullptr;
    FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPTSTR>(&lpMsgBuf), 0, nullptr);
    MessageBoxA(NULL, lpMsgBuf,"ERROR", 0);
    LocalFree(lpMsgBuf);
}

int main()
{
    DWORD* pProcessIds = new DWORD[1000];
    DWORD pBytesReturned = 0;

    bool res =  EnumProcesses(&pProcessIds[0], 1000, &pBytesReturned);

    if (!res)
    {
        DWORD err = GetLastError();
        MessageBoxW(NULL, L"ENUMPROCESSES FAILED", L"Error", 0);
        ShowError(err);
        delete[] pProcessIds;
        return EXIT_FAILURE;
    }

    for (unsigned int i = 0; i < pBytesReturned / sizeof(DWORD); ++i)
    {
        if (pProcessIds[i] == 0) //error.. process id is 0..
            continue;

        wchar_t lpFilename[256] = {0};
        HANDLE hndProccess =   OpenProcess(STANDARD_RIGHTS_ALL,  false, pProcessIds[i]);

        if (hndProccess == NULL || hndProccess == INVALID_HANDLE_VALUE)
        {
            DWORD err = GetLastError();
            MessageBoxW(NULL, L"FAILED TO OPEN PROCESS", L"ERROR", 0);
            ShowError(err);
            delete[] pProcessIds;
            return EXIT_FAILURE;
        }

        int len = GetModuleFileNameExW(hndProccess, NULL, lpFilename, sizeof(lpFilename) / sizeof(lpFilename[0]));
        if (len <= 0)
        {
            DWORD err = GetLastError();
            if (err)
            {
                MessageBoxW(NULL, L"FAILED TO GET MODULEFILENAME", L"ERROR", 0);
                ShowError(err);
                delete[] pProcessIds;
                return EXIT_FAILURE;
            }
        }          

        CloseHandle(hndProccess);

        MessageBoxW(NULL, lpFilename, L"NAME", 0);
    }

    delete[] pProcessIds;
    return 0;
}