如何使用Vb.NET或C#终止一个进程?

72

我有一个场景需要检查用户是否已经打开了Microsoft Word。如果是,我需要杀死winword.exe进程并继续执行我的代码。

有没有人有用VB.NET或C#杀死进程的简单代码?

10个回答

98

您需要使用System.Diagnostics.Process.Kill方法。您可以使用System.Diagnostics.Proccess.GetProcessesByName获取所需的进程。

已经在此处发布了示例,但我发现非.exe版本效果更好,因此类似以下内容:

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

你可能不需要处理NotSupportedException,这表示该进程是远程的。


它在许多其他情况下也不起作用(例如,如果进程使用ACL进行了保护)。实际上,“杀死”进程是一个可怕的想法,长期来看只会产生问题。应该始终关闭进程而不是杀死它们,以便它们可以正常关闭。这个答案是典型的初学者错误。 - specializt

31

完全杀死Word进程是可能的(请参见其他回复),但完全粗鲁和危险:如果用户在打开的文档中有重要的未保存更改怎么办?更不用说这将留下过时的临时文件了...

在这方面,这可能是你能做的最远的地方(VB.NET):

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

这将按顺序关闭所有打开的Word窗口(如适用,提示用户保存其工作)。当然,在这种情况下,用户总是可以点击“取消”,因此您应该能够处理这种情况(最好通过弹出一个“请关闭所有Word实例,否则我们无法继续”的对话框...)


我同意这种方法。终止进程应该是最后的选择。可能会产生意想不到的后果。 - Nathan

15

这里有一个简单的示例,可以说明如何终止所有的Word进程。

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

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

1
一个注释 - 使用“winword”而不是“winword.exe”。 - Rami

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

5

您可以绕过安全问题,通过检查Word进程是否正在运行,并要求用户关闭它,然后在您的应用程序中单击“继续”按钮来创建一个更加礼貌的应用程序。这是许多安装程序采用的方法。

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

当然,只有当你的应用程序有GUI时才能这样做。

2
在我的托盘应用程序中,我需要清除Excel和Word Interops。因此,这个简单的方法可以通用地终止进程。
虽然这里使用了一个通用的异常处理程序,但是它可以很容易地分为多个异常,就像其他答案中所述。如果我的日志产生了很多错误警报(例如无法杀死已经被杀死的进程),那么我可能会这样做。但是到目前为止一切都很好(工作上的玩笑)。
/// <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);
        }
    }
}

这是我当时称呼它的方式:
killProcesses((new List<string>() { "winword", "excel" }));

“clean Excel and Word Interops” 这句话是什么意思? - specializt
如果我没有使用这个过程来清理,我将会有数百个 Word 和 Excel 实例,最终会导致我的机器崩溃。 - tyler_mitchell
杀死正在运行的进程可能会导致您的机器挂起,您可能会丢失重要数据,甚至可能完全破坏安装,迫使用户进行修复或重新安装。因此,总结一下:您的“干净”算法实际上将在某一天毁掉整个系统;在处理进程控制时应该非常小心,特别是当涉及到微软进程时,因为它们紧密编织在操作系统中,如果处理不当会引起一系列问题。但现在,微软已经从他们的错误中吸取教训,并保护它们免受破坏。 - specializt
所以...你这次运气不错。但请从你自己的错误中吸取教训,停止杀死进程。看看CloseMainWindow。我只希望他们有一天开始废弃像这样有害的API,这显然是内核级别的,任何用户空间应用程序都不应该有这种可能性。 - specializt
你只是在看一个非常小的代码片段,没有上下文说明它是如何使用的... - tyler_mitchell
那是个彻头彻尾的谎言。 - specializt

1

类似这样的代码可以正常工作:

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

3
当使用GetProcessesByName时,我无法找到进程,尽管“winword”可以正常工作。 - Blair Conrad

0

最好的做法是检测进程是否正在运行,并告诉用户手动关闭它,这样更安全、更礼貌。当然,您也可以添加超时并在用户离开后终止进程...


-1

我打开了一个Word文件, 2. 现在我通过vb.net程序运行时以编程方式打开另一个Word文件。 3. 我想要单独通过编程方式终止第二个进程。 4. 不要终止第一个进程。

(Note: The text is written in simplified Chinese.)

-2
请看下面的示例
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;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接