C ++ - указатель массива в качестве параметра функции, заполнение массива и доступ к нему из потока пользовательского интерфейса - PullRequest
1 голос
/ 10 декабря 2010

Я не слишком много программировал на C ++ с момента появления HS, и я довольно ржавый / не очень опытный.

Я хочу найти все запущенные процессы на машине и заполнить элемент управления listbox их именами.Я создал приложение C ++ win form, и в обработчике событий загрузки формы у меня есть следующий код -

private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e) {
             // Proccess monitor class
             ProcessMonitor oMonitor;
             // Array pointer
             string* processes = NULL;
             // Call method in process monitor class called get processes, 
             // pass int array pointer as parameter
             oMonitor.GetProcesses(processes);
             // Iterate through array
             for (int i = 0; i < sizeof(processes) / sizeof(string); i++)
             {

             }
         }
};

Надеюсь, код / ​​комментарии достаточно просты.

Это то, что мойМетод GetProcesses выглядит следующим образом -

void ProcessMonitor::GetProcesses(string processNames[])
{
    // Array to hold process ID's
    DWORD aProcesses[1024], cbNeeded, cProcesses;
    // Iterator
    unsigned int i;

    // If no running processes can be detected exit function
    if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
        return;

    // Get number of running processes
    cProcesses = cbNeeded / sizeof(DWORD);
    // Instantiate array that was passed in
    // ***NOTE*** I think this is where my problem lies,
    // as I passed in a pointer to an array, not an actual array
    processNames = new string[cProcesses];
    // Iterate through array and initialize all indicies to an empty string
    for ( int j = 0; j < sizeof(processNames) / sizeof(string); i++)
    {
        processNames[i] = "";
    }

    // Enumerate through processes and fill array with process names
    for ( i = 0; i < cProcesses; i++ )
    {
        if( aProcesses[i] != 0 )
        {
            TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");

            HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i]);

            if (NULL != hProcess )
            {
                HMODULE hMod;
                DWORD cbNeeded;

                /*Given a handle to a process, this returns all the modules running within the process.
                The first module is the executable running the process,
                and subsequent handles describe DLLs loaded into the process.*/
                if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) )
                {
                    //This function returns the short name for a module,
                    //typically the file name portion of the EXE or DLL
                    GetModuleBaseName( hProcess, hMod, szProcessName,
                        sizeof(szProcessName)/sizeof(TCHAR) );
                    processNames[i] = szProcessName;
                }
            }
            CloseHandle( hProcess );
        }
    }
}

Я считаю, что проблема с моим кодом заключается в том, что я не создаю экземпляр своего массива, пока он уже не находится внутри метода GetProcesses.Когда код возвращается в форму вызывающего окна, указатель на массив, который я передал, является нулевым.Я предполагаю, что мне нужно сделать, это создать экземпляр массива, прежде чем передать его в функцию в качестве параметра.Проблема в том, что я не знаю, какой размер должен иметь массив, пока не определю количество запущенных процессов на машине.

Я понимаю, что могу разбить функцию GetProcesses на два вызова, один для определенияРазмер массива должен быть один, чтобы заполнить массив.Проблема в том, что если вы изучите условие -

if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
        return;

Вызов в этом условии заполняет массив aProcesses всеми идентификаторами процесса.Я не хочу делать это дважды.

У кого-нибудь есть какие-либо идеи относительно того, что я делаю неправильно?

Опять же, если я действительно здесь, я прошу прощения,Я давно ничего не программировал на C ++.

Ответы [ 2 ]

1 голос
/ 10 декабря 2010

ProcessMonitor :: GetProcesses (строка processNames [])

Я думаю, что вам нужно передать указатель на функцию

не слишком уверен в синтаксисе

ProcessMonitor :: GetProcesses (строка * processNames [])

, потому что processNames = новая строка [cProcesses]; выделит его локально, и он не будет возвращен обратно ...

(О, да, я думаю, что управляемый C ++ - худший из всех миров. Но это мое мнение.)

0 голосов
/ 10 декабря 2010

Строки и векторы - ваш друг в C ++:)

#include <string>
#include <vector>

typedef std::vector<std::string> StringVector;


StringVector ProcessMonitor::GetProcesses()
{
StringVector ret;
// Array to hold process ID's
DWORD aProcesses[1024], cbNeeded, cProcesses;
// Iterator
unsigned int i;

// If no running processes can be detected exit function
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
    return;

// Enumerate through processes and fill array with process names
for ( i = 0; i < cProcesses; i++ )
{
    if( aProcesses[i] != 0 )
    {
        TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");

        HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i]);

        if (NULL != hProcess )
        {
            HMODULE hMod;
            DWORD cbNeeded;

            /*Given a handle to a process, this returns all the modules running within the process.
            The first module is the executable running the process,
            and subsequent handles describe DLLs loaded into the process.*/
            if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) )
            {
                //This function returns the short name for a module,
                //typically the file name portion of the EXE or DLL
                GetModuleBaseName( hProcess, hMod, szProcessName,
                    sizeof(szProcessName)/sizeof(TCHAR) );

                // CHANGE HERE!!!
                ret.push_back(szProcessName);
            }
        }
        CloseHandle( hProcess );
    }
}
return ret; // return vector back to caller.
}    

Звоните как:

StringVector ret = monitor.GetProcesses();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...