none
Como obtener procesos hijos de un proceso RRS feed

  • Pregunta

  • Hola, tengo una aplicacion windows form (vb.net) en la cual lanzo un proceso (cmd.exe) que a su vez llama a otros programas.

    He establecido el valor WaitForExit para que espere maximo X milisegundos. y despues necesitaria matar el proceso (cmd.exe) y los subprocesos existentes.

    Como con la opcion process.Kill() solo mato el proceso y no los hijos he pensado en hacer una comprobacion cada vez que voy a lanzar el proceso padre del siguiente modo:

    -Cojo el ID del proceso SUperior (aplicacion Windows) recorro todos los procesos actuales y compruebo el ID de su padre si coincide con el de la aplicacion Windows entonces elimino el proceso, asi podria eliminar el cmd.exe y los subprocesos que este lanza.

    El problema es que al recorrer todos los procesos en algunos me da "Acceso denegado" y falla la aplicacion. Adjunto el codigo:

    <System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack:=1)> _
        Public Structure Process_Basic_Information
            Public ExitStatus As IntPtr
            Public PepBaseAddress As IntPtr
            Public AffinityMask As IntPtr
            Public BasePriority As IntPtr
            Public UniqueProcessID As IntPtr
            Public InheritedFromUniqueProcessId As IntPtr
        End Structure
    
        <System.Runtime.InteropServices.DllImport("ntdll.dll", EntryPoint:="NtQueryInformationProcess")> _
        Public Shared Function NtQueryInformationProcess(ByVal handle As IntPtr, ByVal processinformationclass As UInteger, ByRef ProcessInformation As Process_Basic_Information, ByVal ProcessInformationLength As Integer, ByRef ReturnLength As UInteger) As Integer
        End Function
        Public Const PROCESSBASICINFORMATION As UInteger = 0
    
    '''Código función VB.NET
    For Each q As Process In System.Diagnostics.Process.GetProcesses
          Dim ProccessInfo As New Process_Basic_Information
          'A quick and dirty example of getting the handle of a specific process
          Dim ProcHandle As IntPtr = Process.GetProcessesByName(q.ProcessName)(0).Handle
          'Used as an output parameter by the API function
          Dim RetLength As UInteger
          'Here we actually call the function and pass in the relevant information
          NtQueryInformationProcess(ProcHandle, PROCESSBASICINFORMATION, ProccessInfo, System.Runtime.InteropServices.Marshal.SizeOf(ProccessInfo), RetLength)
          If ProccessInfo.InheritedFromUniqueProcessId = IDPadre Then
                q.Kill()
          End If
    Next

    Gracias por su ayuda.
    martes, 27 de noviembre de 2012 11:24

Respuestas

  • Ok, entonces simplemente encierre esa línea en un try..catch.  No sé de VB.net, pero en C# sería algo como:

    IntPtr procHandle = IntPtr.Zero;
    try
    {
        //Nótese que el uso de Process.GetProcessesByName es incorrecto.
        procHandle = q.Handle;
    }
    catch (AccessDeniedException)
    { }
    //Listo.  Revisar si procHandle es IntPtr.Zero.  Si lo es, hubo una excepción.
    if (procHandle != IntPtr.Zero)
    {
        //Hacer el resto.
    }

    Como le hice notar en el código, el uso de GetProcessesByName es incorrecto e innecesario.


    Jose R. MCP
    Code Samples

    • Marcado como respuesta _PSK_ martes, 27 de noviembre de 2012 17:50
    martes, 27 de noviembre de 2012 15:25
    Moderador

Todas las respuestas

  • ¿Qué línea de código le arroja el error, exactamente?  Porque si es una excepción estándar de .net simplemente ignórela y continúe con la enumeración.  Utilice un try..catch.

    Jose R. MCP
    Code Samples

    martes, 27 de noviembre de 2012 14:35
    Moderador
  • esta es la línea que arroja el error:

    Dim ProcHandle As IntPtr = Process.GetProcessesByName(q.ProcessName)(0).Handle

    en un proceso que está ejecutado por NT AUTHORITY\Servicio Local.
    martes, 27 de noviembre de 2012 15:02
  • Ok, entonces simplemente encierre esa línea en un try..catch.  No sé de VB.net, pero en C# sería algo como:

    IntPtr procHandle = IntPtr.Zero;
    try
    {
        //Nótese que el uso de Process.GetProcessesByName es incorrecto.
        procHandle = q.Handle;
    }
    catch (AccessDeniedException)
    { }
    //Listo.  Revisar si procHandle es IntPtr.Zero.  Si lo es, hubo una excepción.
    if (procHandle != IntPtr.Zero)
    {
        //Hacer el resto.
    }

    Como le hice notar en el código, el uso de GetProcessesByName es incorrecto e innecesario.


    Jose R. MCP
    Code Samples

    • Marcado como respuesta _PSK_ martes, 27 de noviembre de 2012 17:50
    martes, 27 de noviembre de 2012 15:25
    Moderador
  • Gracias por tu ayuda al final lo solucioné con el Catch como me indicaste aunque no me convence 100% eso de que si falla omitirlo pero para los procesos que deseo eliminar no falla, solo para alguno de sistema así que me es válida la idea.

    También cambié a q.handle en lugar de GetProcessesByName.

    Gracias por tu ayuda.

    martes, 27 de noviembre de 2012 17:51