Pregunta

He aquí mi problema:Necesito cerrar un proceso, ya en ejecución, en un programa de C#.El problema es que el proceso que ahora se ejecuta como un icono (minimizado a la barra de tareas), y a menos que el usuario lo abre al menos una vez (que nunca va a suceder en desatendida máquinas), nunca tiene una ventana principal.

El otro requisito que tengo es que la aplicación se cerrado no mató.La necesito para escribir es búferes de memoria a disco y matar a causa de la pérdida de datos.

Aquí está lo que he probado hasta ahora:

        foreach (Process proc in Process.GetProcesses())
        {
            if (proc.ProcessName.ToLower().StartsWith("myapp"))
            {
                if (proc.MainWindowHandle.ToInt32() != 0)
                {
                    proc.CloseMainWindow();
                    proc.Close();
                    //proc.Kill();  <--- not good!
                }
            }
        }

He añadido el si la cláusula, después de descubrir que MainWindowHandle == 0 cuando la ventana está minimizada.La eliminación de la si no ayuda.Ni el CloseMainWindow() ni el Close() trabajo.El Kill() no, pero como se mencionó anteriormente - no es lo que necesito.

Cualquier idea sería aceptada, incluyendo el uso de arcana funciones de API de Win32 :)

¿Fue útil?

Solución 3

Aquí están algunas de las respuestas y aclaraciones:

rpetrich:Trató de que su método de antes y el problema es que no sé el nombre de la ventana, se diferencia de usuario a usuario, versión a versión - sólo el nombre del exe permanece constante.Todo lo que tengo es el nombre de proceso.Y como se puede ver en el código anterior la MainWindowHandle del proceso es 0.

Roger:Sí, yo quería decir la barra de tareas área de notificación - gracias por la aclaración.Yo NECESIDAD para llamar a PostQuitMessage.Yo no sé cómo, dado un proceso, y no sólo una Ventana.

Craig:Yo estaría encantado de explicar la situación:la aplicación tiene una interfaz de línea de comandos, lo que le permite especificar los parámetros que dictan lo que iba a hacer y donde va a guardar los resultados.Pero una vez que se ejecuta, la única forma de detenerlo y obtener los resultados que está a la derecha-haga clic en en la bandeja de notificación y seleccione "salir".

Ahora los usuarios quieren script/lote de la aplicación.Tenían absolutamente ningún problema a partir de un lote (especificar el nombre del exe y un montón de banderas), pero luego se quedó atascado con el de un proceso en ejecución.Suponiendo que nadie va a cambiar el proceso para proporcionar una API para detenerlo mientras se ejecuta (es bastante antiguo), necesito una manera artificial para cerrarla.

Del mismo modo, en equipos desatendidos, la secuencia de comandos para iniciar el proceso puede ser iniciado por una tarea de programación o de control de operaciones del programa, pero no hay manera de cerrar el proceso.

Espero que aclare mi situación, y de nuevo, gracias a todos los que está tratando de ayudar!

Otros consejos

Esto debería funcionar:

[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr FindWindow(string className, string windowName);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

private const int WM_CLOSE = 0x10;
private const int WM_QUIT = 0x12;

public void SearchAndDestroy(string windowName) 
{
    IntPtr hWnd = FindWindow(null, windowName);
    if (hWnd == IntPtr.Zero)
        throw new Exception("Couldn't find window!");
    SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
}

Desde algunas ventanas no responden a WM_CLOSE, WM_QUIT puede que tenga que ser enviado en su lugar.Estas declaraciones deben trabajar tanto en 32 bits y 64 bits.

Si es en la barra de tareas, que tendrá una ventana.O ¿te refieres a que es en la barra de tareas área de notificación (aka la Bandeja del sistema)?En cuyo caso, se tendrá todavía una ventana.

Las aplicaciones de Win32 realmente no tienen una "ventana principal", excepto por (convención de la ventana principal es la que llama PostQuitMessage en respuesta a WM_DESTROY, causando el bucle de mensajes).

Con el programa en ejecución, ejecutar Spy++.Para encontrar todas las ventanas de la propiedad de un proceso, debe seleccionar Spy -> Procesos desde el menú principal.Esto mostrará un árbol de procesos.A partir de allí, se puede desglosar en los hilos, y luego a windows.Esto le dirá a usted que en windows el proceso.Nota hacia abajo de la ventana de la clase y el título.Con estos, se pueden utilizar FindWindow (o EnumWindows) para encontrar el identificador de ventana en el futuro.

Con el identificador de ventana, usted puede enviar un mensaje wm_close o WM_SYSCOMMAND/SC_CLOSE (equivalente a hacer clic en la 'X' en el título de la ventana) mensaje.Esto debería provocar que el programa se cerró muy bien.

Tenga en cuenta que estoy hablando de un Win32 punto de vista aquí.Usted podría necesitar el uso de P/Invoke o otros trucos para conseguir que esto funcione de una .Programa de RED.

Pregunta para aclarar por qué estás tratando de esto:Si la única interfaz del usuario en el proceso es el icono de bandeja de sistema, ¿por qué quieres matar a ese y sino dejen el proceso de ejecución?Cómo sería el acceso a los usuarios el proceso?Y si la máquina es "desatendida", ¿por qué preocuparse con el icono de la bandeja?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top