Pergunta

Eu tenho um cenário em que tenho que verificar se o usuário já abriu o Microsoft Word. Se ele tiver, então eu tenho que matar o processo winword.exe e continuar executando meu código.

Alguém tem algum código direto para matar um processo usando vb.net ou c#?

Foi útil?

Solução

Você vai querer usar o System.diagnostics.process.kill método. Você pode obter o processo que deseja usarSystem.diagnostics.proccess.getprocesssbyName.

Exemplos já foram publicados aqui, mas descobri que a versão que não é doexe funcionou melhor, então 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
     }
}

Você provavelmente não tem que lidar com NotSupportedException, o que sugere que o processo é remoto.

Outras dicas

É possível matar o processo de texto (veja algumas das outras respostas), mas rude e perigoso: e se o usuário tiver importantes alterações não salvas em um documento aberto? Sem mencionar os arquivos temporários obsoletos que deixarão para trás ...

Provavelmente isso é o mais longe que você pode ir nesse sentido (vb.net):

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

Isso fechará todas as janelas de palavras abertas de maneira ordenada (levando o usuário a salvar seu trabalho, se aplicável). Obviamente, o usuário sempre pode clicar em 'Cancelar' nesse cenário, para que você possa lidar com esse caso (de preferência, colocando um diálogo "Feche todas as instâncias do Word, caso contrário, não podemos continuar" ... )

Aqui está um exemplo fácil de como matar todos os processos de texto.

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

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

Você pode ignorar as preocupações de segurança e criar um aplicativo muito politer, simplesmente verificando se o processo de texto estiver em execução e solicitando ao usuário que o feche e clique em um botão 'Continuar' no seu aplicativo. Esta é a abordagem adotada por muitos instaladores.

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

Claro, você só pode fazer isso se seu aplicativo tiver uma 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;
    }

No meu aplicativo de bandeja, eu precisava limpar o Excel e o Word Interops. Portanto, esse método simples mata processos genericamente.

Isso usa um manipulador de exceção geral, mas pode ser facilmente dividido para várias exceções, como indicado em outras respostas. Eu posso fazer isso se meu log produzir muitos falsos positivos (ou seja, não é possível matar já morto). Mas até agora Guid (piada de trabalho).

/// <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);
        }
    }
}

Foi assim que eu chamei então:

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

Algo assim vai funcionar:

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

É uma prática melhor, mais segura e educada para detectar se o processo está em execução e peça ao usuário que o feche manualmente. Claro que você também pode adicionar um tempo limite e matar o processo se eles desaparecessem ...

Por favor, veja o exemplo abaixo

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top