2010-02-23 15 views
6

Estoy usando el objeto System.Diagnostic.Process de C#.
Una de sus propiedades es Id.
El Id que este produce no es el mismo que el PID, que se muestra en Windows Task Manager.
¿Por qué es esto?System.Diaganostics.Process.Id No se muestra el mismo ID de proceso en el Administrador de tareas. ¿Por qué?

Verá, una vez que se inicia este proceso.
Lanza otros dos procesos no administrados, para los cuales no puedo obtener identificadores explícitamente por las referencias de propiedades del objeto.
Tengo que buscar en todos los procesos para encontrarlos por nombre de proceso a través de System.Diagnostics.Process.GetProcesses().

Estoy tratando de encontrar una manera confiable de matar este proceso y todos los procesos asociados por PID, el que se muestra en Task Manager.
¿Hay una manera mejor?

No puedo simplemente matar todos los procesos con los nombres de proceso asociados, porque eso puede matar a otras instancias de esos procesos que no tienen nada que ver con mi programa.

+2

Si se inicia el proceso con System.Diagnostics.Process, a continuación, llamar .Refresh() antes de comprobar la ID. El sistema operativo asigna la ID cuando se inicia el proceso, no cuando se crea una instancia del objeto Proceso. –

Respuesta

13

La clave es que no desea matar su proceso por Id. De hecho, esa es una condición de carrera: su proceso engendrado podría morir y otro proceso podría crearse con el mismo Id. Luego, cuando vaya a matarlo, terminaría matando el nuevo proceso en lugar del antiguo que ya estaba muerto.

La manera más confiable de eliminar procesos engendrados es ponerlos en un objeto de Trabajo y terminar el Trabajo una vez que se complete su tarea.

Aquí hay un código simple de implementar una clase de empleo:

class Job 
{ 
    [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] 
    public static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, string lpName); 

    [DllImport("kernel32.dll")] 
    public static extern bool AssignProcessToJobObject(IntPtr hJob, IntPtr hProcess); 

    [DllImport("kernel32.dll")] 
    public static extern bool TerminateJobObject(IntPtr hJob, uint uExitCode); 

    IntPtr job; 

    public Process StartProc(string commandLine) 
    { 
     if (job == IntPtr.Zero) 
      job = CreateJobObject(IntPtr.Zero, null); 
     ProcessStartInfo si = new ProcessStartInfo(@"c:\windows\system32\cmd.exe"); 
     si.Arguments = "/c " + commandLine; 
     si.CreateNoWindow = false; 
     si.UseShellExecute = false; 
     Process proc = Process.Start(si); 
     AssignProcessToJobObject(job, proc.Handle); 
     return proc; 
    } 

    public void TerminateProc() 
    { 
     // terminate the Job object, which kills all processes within it 
     if (job != null) 
      TerminateJobObject(job, 0); 
     job = IntPtr.Zero; 
    } 
} 
+0

Sí imaginé esa posibilidad, pero no sabía qué hacer. ¿Aquellos subprocesos que no se administran (que son iniciados indirectamente por el proceso que inicio) se relacionan subordinadamente también con este objeto de trabajo? ¿De modo que si mato el trabajo, los 3 procesos mueren? –

+0

Por cierto, me da miedo el código en corchetes angulares; No lo entiendo todavía ¿Están esos atributos en la parte superior? ¿Este código está limitado a la arquitectura de 32 bits? –

+1

La terminación del objeto Trabajo finalizará el proceso que inició y cada proceso iniciado por él, y así sucesivamente. Y sí, esos son los atributos en la parte superior entre paréntesis. No he ejecutado esto en una máquina de 64 bits, pero no hay ninguna razón para creer que no funcionará. – Gabe

1

No puedo reproducir esto. Acabo de ejecutar el siguiente código:

foreach (var proc in Process.GetProcesses() 
          .OrderBy(proc => proc.Id)) 
{ 
    Console.WriteLine("{0}: {1}", p.Id, p.ProcessName); 
} 

Todos los procesos enumerados tienen coincidencias con el PID en el Administrador de tareas. Esto es usar Windows 7, ¿qué sistema operativo estás usando? Si observa otros procesos, ¿se corresponde con el PID que se muestra en el Administrador de tareas?

+0

Jon, los otros dos procesos (los no administrados comenzaron indirectamente por el proceso que inicio) coinciden. Pero, el ID del proceso que inicio es diferente en el administrador de tareas, que en la referencia de propiedad a través de myProcess.Id. –

+0

Por cierto, me gusta el método .OrderBy que publicaste. No sabía que pudieras hacer eso. –

Cuestiones relacionadas