2010-12-10 7 views
1

Je n'ai pas beaucoup codé en C++ depuis HS et je suis assez rouillé/pas très expérimenté.C++ - Pointeur de tableau comme paramètre de fonction, remplissage de tableau et accès à partir du thread de l'interface utilisateur

Je veux trouver tous les processus en cours sur une machine et remplir un contrôle de la liste avec leurs noms. J'ai créé un C++ gagner formulaire de demande, et le gestionnaire d'événements de charge de forme je le code suivant -

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++) 
      { 

      } 
     } 
}; 

Espérons que le code/commentaires sont droites assez en avant.

C'est ce que ma méthode GetProcesses ressemble -

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); 
     } 
    } 
} 

Je crois que le problème avec mon code est que je ne suis pas instancié avec mon tableau jusqu'à ce qu'il soit déjà à l'intérieur de la méthode GetProcesses. Lorsque le code retourne au formulaire des fenêtres appelantes, le pointeur vers le tableau que j'ai transmis est nul. Je suppose que ce que j'ai à faire est d'instancier le tableau avant de le transmettre à la fonction en tant que paramètre. Le problème est que je ne connais pas la taille que le tableau doit avoir jusqu'à ce que je détermine le nombre de processus en cours sur la machine. Je réalise que je pourrais décomposer la fonction GetProcesses en deux appels, l'un pour déterminer la taille que le tableau doit être, et l'autre pour remplir le tableau. Le problème avec cela est si vous examinez la condition -

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

L'appel dans cette condition remplit le tableau aProcesses avec tous les ID de processus. Je ne veux pas avoir à le faire deux fois.

Est-ce que quelqu'un a des idées en ce qui concerne ce que je fais mal?

Encore une fois, si je suis vraiment ici, je m'excuse, je n'ai rien programmé en C++ depuis un moment.

+0

Ce n'est pas C++. Il pourrait être C++/CLI –

+0

Désolé, vous avez raison à propos de John c'est C++/CLI. –

Répondre

0

Strings et vecteurs sont vos amis en 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. 
}  

Appel comme:

StringVector ret = monitor.GetProcesses(); 
+0

Merci Moo-Juice, j'ai pu obtenir ma zone de liste peuplée en utilisant cette méthode. Une question que j'ai est où devrais-je mettre la déclaration typedef?J'ai dû le mettre dans mon code de formulaire Windows avec mon fichier source et en-tête pour ma classe ProcessMonitor, afin de compiler le code. –

+0

@Zachary, généralement dans un fichier d'en-tête commun que vous incluez dans des endroits où vous pourriez l'utiliser. Vous pouvez également y inclure '' et ''. –

1

ProcessMonitor :: GetProcesses (processNames string [])

Je pense que vous devez passer un pointeur dans la fonction

pas trop sûr de la syntaxe

ProcessMonitor :: GetProcesses (string * processNames [])

car processNames = nouvelle chaîne [cProcesses]; allouera localement et il ne sera pas retourné ...

(Oh oui je pense que géré C++ est le pire de tous les mondes. Mais c'est mon avis.)

+0

+1 pour "(Oh oui je pense que le C++ géré est le pire de tous les mondes, mais c'est mon opinion.)" –

Questions connexes