سؤال

لدي سيناريو حيث يتعين علي التحقق مما إذا كان المستخدم قد فتح بالفعل Microsoft Word.إذا كان الأمر كذلك، فلا بد لي من إنهاء عملية winword.exe والاستمرار في تنفيذ التعليمات البرمجية الخاصة بي.

هل لدى أي شخص أي رمز مباشر لقتل عملية باستخدام vb.net أو c#؟

هل كانت مفيدة؟

المحلول

سوف ترغب في استخدام 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, مما يوحي بأن العملية بعيدة.

نصائح أخرى

من الممكن إيقاف عملية Word تمامًا (راجع بعض الردود الأخرى)، ولكنها وقحة وخطيرة تمامًا:ماذا لو كان لدى المستخدم تغييرات مهمة غير محفوظة في مستند مفتوح؟ناهيك عن الملفات المؤقتة التي لا معنى لها والتي سيتركها هذا وراءه...

ربما يكون هذا أقصى ما يمكنك الذهاب إليه في هذا الصدد (VB.NET):

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

سيؤدي هذا إلى إغلاق جميع نوافذ Word المفتوحة بطريقة منظمة (مطالبة المستخدم بحفظ عمله إن أمكن).بالطبع، يمكن للمستخدم دائمًا النقر فوق "إلغاء" في هذا السيناريو، لذا يجب أن تكون قادرًا على التعامل مع هذه الحالة أيضًا (ويفضل أن يكون ذلك عن طريق وضع مربع حوار "يُرجى إغلاق كافة مثيلات Word، وإلا فلن نتمكن من المتابعة"... )

فيما يلي مثال سهل لكيفية إيقاف كافة عمليات Word.

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

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

يمكنك تجاوز المخاوف الأمنية وإنشاء تطبيق أكثر تهذيبًا بمجرد التحقق مما إذا كانت عملية Word قيد التشغيل ومطالبة المستخدم بإغلاقها، ثم النقر فوق الزر "متابعة" في تطبيقك.هذا هو النهج الذي يتبعه العديد من المثبتين.

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

بالطبع، لا يمكنك القيام بذلك إلا إذا كان تطبيقك يحتوي على واجهة مستخدم رسومية

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

في تطبيق الدرج الخاص بي، كنت بحاجة إلى تنظيف 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" }));

شيء من هذا القبيل سوف يعمل:

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

من الأفضل والأكثر أمانًا والأكثر أدبًا اكتشاف ما إذا كانت العملية قيد التشغيل وإخبار المستخدم بإغلاقها يدويًا.بالطبع يمكنك أيضًا إضافة مهلة وإنهاء العملية إذا اختفت...

يرجى الاطلاع على المثال أدناه

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;
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top