2010-11-14 14 views
3

Dans un batchscript, j'ai besoin d'obtenir une liste d'ID de processus avec le chemin binaire donné C:\path\to\binary.exe. Sous Linux, je peux simplement faire pidof /path/to/binary.Quel est l'équivalent Windows de "pidof" de Linux?

Existe-t-il un exécutable Win32 qui fait la même chose, supporté de WinXP Home à Win7 (la liste des tâches ne fonctionnera pas)?

Le paquet qui comprend ceci doit être portable, donc un téléchargement de 10 Mo n'est pas ce que je cherche.

Existe-t-il une fonction C disponible qui prend en charge ce et de WinXP à Win7? Note: Je veux faire correspondre un chemin de processus, pas un nom de fichier qui pourrait aussi être utilisé par d'autres applications.

Répondre

1

Vous pouvez utiliser les API Toolhelp pour énumérer les processus, obtenir leur chemin d'accès complet et le comparer au nom de processus requis. Vous devez parcourir la liste des modules pour chaque processus. Le premier module de la liste est le processus exécutable lui-même. Voici un exemple de code:

int main(int argc, char* argv[]) 
{ 

    if(argc > 1) 
    { 
     printf("\nGetting PID of: %s\n", argv[1]); 
     HANDLE hProcSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 
     if(INVALID_HANDLE_VALUE != hProcSnapshot) 
     { 
      PROCESSENTRY32 procEntry = {0}; 
      procEntry.dwSize = sizeof(PROCESSENTRY32); 
      if(::Process32First(hProcSnapshot, &procEntry)) 
      { 
       do 
       { 
        HANDLE hModSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, procEntry.th32ProcessID); 
        if(INVALID_HANDLE_VALUE != hModSnapshot) 
        { 
         MODULEENTRY32 modEntry = {0}; 
         modEntry.dwSize = sizeof(MODULEENTRY32); 
         if(Module32First(hModSnapshot, &modEntry)) 
         { 
          if(0 == stricmp(argv[1], modEntry.szExePath)) 
          { 
           printf("\nPID: %ld\n", procEntry.th32ProcessID); 
           ::CloseHandle(hModSnapshot); 
           break; 
          } 
         } 
         ::CloseHandle(hModSnapshot); 
        } 
       } 
       while(::Process32Next(hProcSnapshot, &procEntry)); 
      } 
      ::CloseHandle(hProcSnapshot); 
     } 
    } 
    return 0; 
}
+0

Merci, c'est exactement ce dont j'ai besoin. J'ai vu '::' plusieurs fois, est-ce une chose en C++? Maintenant, je vais essayer de le faire fonctionner avec des noms Unicode, comme le chinois. – Lekensteyn

+0

Avec une petite modification, cela fonctionne pour [tous les processus] (http://forum.sysinternals.com/listing-processes-and-finding-executable_topic6595_post26001.html#26001). Cela fonctionne également pour les caractères spéciaux, comme le chinois. Pour que cela fonctionne, le système devait être chinois, sinon il montrerait un '?'. – Lekensteyn

1

PowerShell peut résoudre vos problèmes, s'il est inclus dans Win 7, et téléchargeable sur les autres systèmes d'exploitation.

param($fileName) 
Get-Process | where -FilterScript {$_.MainModule.FileName -eq $fileName} 

Ce script recevra un paramètre, le nom du fichier que vous recherchez, et il affichera le nom de son exécutable.

Vous pouvez appeler cela à partir d'un fichier de chauve-souris en faisant:

powershell -Command "& {Get-Process | où -FilterScript {$ _ -eq MainModule.FileName% FILENAME% de}."

+0

Je voudrais l'avoir portable, sans installer des dizaines de choses. Merci pour votre réponse de toute façon. – Lekensteyn

+0

Assez juste. Gardez à l'esprit que Powershell est une seule chose et le téléchargement est de 5 Mo pour Windows Vista et 1,6 Mo pour Windows XP. Il est également intégré dans la victoire 7. Source: http://www.microsoft.com/windowsserver2003/technologies/management/powershell/download.mspx –

+0

N'est-ce pas exactement en arrière de ce que l'OP a demandé? Il veut savoir quels pids sont ouverts sur un exécutable donné, et non quel exécutable est ouvert sur un pid donné. –

1

Vous pouvez écrire une petite application C# qui commence par appeler Process.GetProcessesByName(String), puis parcourir les résultats et imprimer la propriété Id de chacun d'entre eux lorsque le MainModule. FileName est égal au chemin que vous recherchez.

+0

Cela retourne uniquement un nom de processus comme GetModuleFileName ou CreateToolhelp32Snapshot. Y at-il une fonction qui fonctionne de WinXP à Win7 et retourne un chemin? – Lekensteyn

+0

@Lekensteyn - vous avez raison, j'ai édité la réponse pour le chemin de retour. – rkellerm

4

wmic.exe est disponible sur XP, Vista et 7 et peut le faire. Cependant, il ne vient pas avec Windows XP Home Edition.

wmic process where ExecutablePath='C:\\windows\\system32\\notepad.exe' get ProcessId 

Si vous souhaitez un support pour Windows XP aussi, vous pouvez utiliser EnumProcess et GetModuleFileNameEx. L'inconvénient ici est que vous ne serez pas en mesure d'interroger les noms de processus exécutés par un autre utilisateur si vous n'êtes pas en cours d'exécution en tant qu'administrateur. QueryFullProcessImageName fera probablement l'affaire ici, mais c'est Vista +.

Si cela ne suffit pas, vous aurez besoin de Process32First (le code de swatkat). Pour chaque processus, vous devez appeler Module32First puis obtenir MODULEENTRY32->szExePath. Notez que même cela n'est pas complètement portable et ne fonctionnera pas bien sur x64 où vous aurez besoin de QueryFullProcessImageName.