Pregunta

Tengo un escenario en el que tengo que comprobar si el usuario ya abrió Microsoft Word.Si es así, entonces tengo que finalizar el proceso winword.exe y continuar ejecutando mi código.

¿Alguien tiene algún código sencillo para finalizar un proceso usando vb.net o c#?

¿Fue útil?

Solución

Querrás usar el Matanza.del.proceso.de.diagnóstico.del.sistema método.Puedes obtener el proceso que desees utilizandoSystem.Diagnostics.Proccess.GetProcessesByName.

Ya se han publicado ejemplos aquí, pero descubrí que la versión que no es .exe funcionó mejor, así que algo como:

foreach ( Process p in System.Diagnostics.Process.GetProcessesByName("winword") )
{
    try
    {
        p.Kill();
        p.WaitForExit(); // possibly with a timeout
    }
    catch ( Win32Exception winException )
    {
        // process was terminating or can't be terminated - deal with it
    }
    catch ( InvalidOperationException invalidException )
    {
        // process has already exited - might be able to let this one go
     }
}

Probablemente no tengas que lidiar con NotSupportedException, lo que sugiere que el proceso es remoto.

Otros consejos

Es posible eliminar por completo el proceso de Word (consulte algunas de las otras respuestas), pero es totalmente grosero y peligroso:¿Qué pasa si el usuario tiene cambios importantes no guardados en un documento abierto?Sin mencionar los archivos temporales obsoletos que esto dejará atrás...

Probablemente esto sea lo más lejos que pueda llegar en este sentido (VB.NET):

    Dim proc = Process.GetProcessesByName("winword")
    For i As Integer = 0 To proc.Count - 1
        proc(i).CloseMainWindow()
    Next i

Esto cerrará todas las ventanas abiertas de Word de forma ordenada (indicándole al usuario que guarde su trabajo, si corresponde).Por supuesto, el usuario siempre puede hacer clic en 'Cancelar' en este escenario, por lo que usted también debería poder manejar este caso (preferiblemente abriendo un cuadro de diálogo "cierre todas las instancias de Word, de lo contrario no podremos continuar"... )

Aquí hay un ejemplo sencillo de cómo eliminar todos los procesos de texto.

Process[] procs = Process.GetProcessesByName("winword");

foreach (Process proc in procs)
    proc.Kill();

Puede evitar los problemas de seguridad y crear una aplicación mucho más educada simplemente verificando si el proceso de Word se está ejecutando y pidiendo al usuario que lo cierre, luego haga clic en el botón "Continuar" en su aplicación.Este es el enfoque adoptado por muchos instaladores.

private bool isWordRunning() 
{
    return System.Diagnostics.Process.GetProcessesByName("winword").Length > 0;
}

Por supuesto, sólo puedes hacer esto si tu aplicación tiene una GUI.

    public bool FindAndKillProcess(string name)
    {
        //here we're going to get a list of all running processes on
        //the computer
        foreach (Process clsProcess in Process.GetProcesses()) {
            //now we're going to see if any of the running processes
            //match the currently running processes by using the StartsWith Method,
            //this prevents us from incluing the .EXE for the process we're looking for.
            //. Be sure to not
            //add the .exe to the name you provide, i.e: NOTEPAD,
            //not NOTEPAD.EXE or false is always returned even if
            //notepad is running
            if (clsProcess.ProcessName.StartsWith(name))
            {
                //since we found the proccess we now need to use the
                //Kill Method to kill the process. Remember, if you have
                //the process running more than once, say IE open 4
                //times the loop thr way it is now will close all 4,
                //if you want it to just close the first one it finds
                //then add a return; after the Kill
                try 
                {
                    clsProcess.Kill();
                }
                catch
                {
                    return false;
                }
                //process killed, return true
                return true;
            }
        }
        //process not found, return false
        return false;
    }

En mi aplicación de bandeja, necesitaba limpiar Excel y Word Interops.Entonces, este método simple mata procesos de manera genérica.

Esto utiliza un controlador de excepciones general, pero podría dividirse fácilmente para múltiples excepciones como se indica en otras respuestas.Puedo hacer esto si mi registro produce muchos falsos positivos (es decir, no puedo eliminar a los que ya han sido eliminados).Pero hasta ahora todo es guid (broma de trabajo).

/// <summary>
/// Kills Processes By Name
/// </summary>
/// <param name="names">List of Process Names</param>
private void killProcesses(List<string> names)
{
    var processes = new List<Process>();
    foreach (var name in names)
        processes.AddRange(Process.GetProcessesByName(name).ToList());
    foreach (Process p in processes)
    {
        try
        {
            p.Kill();
            p.WaitForExit();
        }
        catch (Exception ex)
        {
            // Logging
            RunProcess.insertFeedback("Clean Processes Failed", ex);
        }
    }
}

Así lo llamé entonces:

killProcesses((new List<string>() { "winword", "excel" }));

Algo como esto funcionará:

foreach ( Process process in Process.GetProcessesByName( "winword" ) )
{
    process.Kill();
    process.WaitForExit();
}

Es una mejor práctica, más seguro y más educado detectar si el proceso se está ejecutando y decirle al usuario que lo cierre manualmente.Por supuesto, también puedes agregar un tiempo de espera y finalizar el proceso si han desaparecido...

Por favor vea el ejemplo a continuación

public partial class Form1 : Form
{
    [ThreadStatic()]
    static Microsoft.Office.Interop.Word.Application wordObj = null;

    public Form1()
    {
        InitializeComponent();
    }

    public bool OpenDoc(string documentName)
    {
        bool bSuccss = false;
        System.Threading.Thread newThread;
        int iRetryCount;
        int iWait;
        int pid = 0;
        int iMaxRetry = 3;

        try
        {
            iRetryCount = 1;

        TRY_OPEN_DOCUMENT:
            iWait = 0;
            newThread = new Thread(() => OpenDocument(documentName, pid));
            newThread.Start();

        WAIT_FOR_WORD:
            Thread.Sleep(1000);
            iWait = iWait + 1;

            if (iWait < 60) //1 minute wait
                goto WAIT_FOR_WORD;
            else
            {
                iRetryCount = iRetryCount + 1;
                newThread.Abort();

                //'-----------------------------------------
                //'killing unresponsive word instance
                if ((wordObj != null))
                {
                    try
                    {
                        Process.GetProcessById(pid).Kill();
                        Marshal.ReleaseComObject(wordObj);
                        wordObj = null;
                    }
                    catch (Exception ex)
                    {
                    }
                }

                //'----------------------------------------
                if (iMaxRetry >= iRetryCount)
                    goto TRY_OPEN_DOCUMENT;
                else
                    goto WORD_SUCCESS;
            }
        }
        catch (Exception ex)
        {
            bSuccss = false;
        }
    WORD_SUCCESS:

        return bSuccss;
    }

    private bool OpenDocument(string docName, int pid)
    {
        bool bSuccess = false;
        Microsoft.Office.Interop.Word.Application tWord;
        DateTime sTime;
        DateTime eTime;

        try
        {
            tWord = new Microsoft.Office.Interop.Word.Application();
            sTime = DateTime.Now;
            wordObj = new Microsoft.Office.Interop.Word.Application();
            eTime = DateTime.Now;
            tWord.Quit(false);
            Marshal.ReleaseComObject(tWord);
            tWord = null;
            wordObj.Visible = false;
            pid = GETPID(sTime, eTime);

            //now do stuff
            wordObj.Documents.OpenNoRepairDialog(docName);
            //other code

            if (wordObj != null)
            {
                wordObj.Quit(false);
                Marshal.ReleaseComObject(wordObj);
                wordObj = null;
            }
            bSuccess = true;
        }
        catch
        { }

        return bSuccess;
    }

    private int GETPID(System.DateTime startTime, System.DateTime endTime)
    {
        int pid = 0;

        try
        {
            foreach (Process p in Process.GetProcessesByName("WINWORD"))
            {
                if (string.IsNullOrEmpty(string.Empty + p.MainWindowTitle) & p.HasExited == false && (p.StartTime.Ticks >= startTime.Ticks & p.StartTime.Ticks <= endTime.Ticks))
                {
                    pid = p.Id;
                    break;
                }
            }
        }
        catch
        {
        }
        return pid;
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top