Domanda

Ho uno scenario in cui devo verificare se l'utente ha già aperto Microsoft Word. In tal caso, devo interrompere il processo winword.exe e continuare a eseguire il mio codice.

Qualcuno ha un codice diretto per uccidere un processo usando vb.net o c #?

È stato utile?

Soluzione

Ti consigliamo di utilizzare System.Diagnostics Metodo .Process.Kill . È possibile ottenere il processo che si desidera utilizzare System.Diagnostics.Proccess.GetProcessesByName .

Alcuni esempi sono già stati pubblicati qui, ma ho scoperto che la versione non .exe ha funzionato meglio, quindi qualcosa del tipo:

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
     }
}

Probabilmente non devi avere a che fare con NotSupportedException , il che suggerisce che il processo è remoto.

Altri suggerimenti

È possibile uccidere completamente il processo di Word (vedere alcune delle altre risposte), ma apertamente maleducato e pericoloso: cosa succede se l'utente ha importanti modifiche non salvate in un documento aperto? Per non parlare dei file temporanei obsoleti che questo lascerà alle spalle ...

Questo è probabilmente per quanto si può andare in questo senso (VB.NET):

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

Questo chiuderà tutte le finestre di Word aperte in modo ordinato (chiedendo all'utente di salvare il suo lavoro, se applicabile). Ovviamente, l'utente può sempre fare clic su "Annulla" in questo scenario, quindi dovresti essere in grado di gestire anche questo caso (preferibilmente inserendo un " per favore chiudi tutte le istanze di Word, altrimenti non possiamo continuare " dialog .. .)

Ecco un semplice esempio di come uccidere tutti i processi di Word.

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

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

Puoi ignorare i problemi di sicurezza e creare un'applicazione molto più semplice semplicemente controllando se il processo di Word è in esecuzione e chiedendo all'utente di chiuderlo, quindi fai clic su un pulsante "Continua" nella tua app. Questo è l'approccio adottato da molti installatori.

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

Ovviamente, puoi farlo solo se la tua app ha 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;
    }

Nell'app della barra delle applicazioni, dovevo pulire Excel e Word Interops. Quindi questo semplice metodo uccide i processi genericamente.

Utilizza un gestore di eccezioni generale, ma può essere facilmente diviso per più eccezioni come indicato in altre risposte. Potrei farlo se la mia registrazione produce molti falsi positivi (cioè non posso uccidere già ucciso). Ma finora finora guid (scherzo di lavoro).

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

Ecco come l'ho chiamato allora:

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

Qualcosa del genere funzionerà:

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

È meglio, più sicuro e più educato rilevare se il processo è in esecuzione e dire all'utente di chiuderlo manualmente. Ovviamente potresti anche aggiungere un timeout e terminare il processo se sono andati via ...

Vedi l'esempio di seguito

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;
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top