سؤال

أنا أعمل على ملحق Windows Shell، وللأسف، عند إجراء تغييرات على DLL، يجب إعادة تشغيل Windows Explorer (لأنه يحتفظ DLL في الذاكرة).

لقد وجدت هذا البرنامج من دينو إسبوزيتو، لكنه لا يعمل بالنسبة لي.

void SHShellRestart(void)
{
    HWND hwnd;
    hwnd = FindWindow("Progman", NULL );
    PostMessage(hwnd, WM_QUIT, 0, 0 );
    ShellExecute(NULL, NULL, "explorer.exe", NULL, NULL, SW_SHOW );
    return;
}

هل لدى أي شخص ما يمكنه مشاركته للقيام بذلك؟

PS أنا أدرك أنه يمكنني الذهاب إلى إدارة المهام وقتل عملية المستكشف، لكنني فقط أريد أن أفعل ذلك بطريقة كسول. الى جانب ذلك، يتيح ذلك الأتمتة.

PPS أنا أستخدمه .NET للتطوير، ولكن وظيفة إعادة تشغيل Shell قد تكون في C، C ++ أو لغة .NET. سيكون ببساطة قابلة للتنفيذ مستقلة مستقلة.

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

المحلول

حل مغمول مقاوم:

foreach (Process p in Process.GetProcesses())
{
    // In case we get Access Denied
    try
    {
        if (p.MainModule.FileName.ToLower().EndsWith(":\\windows\\explorer.exe"))
        {
            p.Kill();
            break;
        }
    }
    catch
    { }
}
Process.Start("explorer.exe");

نصائح أخرى

بعد تحليل بعض الإجابات السابقة والقيام ببعض الأبحاث، قمت بإنشاء مثال كامل قليلا في C #. يؤدي هذا إلى إغلاق Shell Explorer ثم ينتظره لإغلاقه وإعادة تشغيله بالكامل. نأمل أن يساعد هذا، هناك الكثير من المعلومات المثيرة للاهتمام في هذا الموضوع.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;

namespace RestartExplorer
{
class Program
{
    [DllImport("user32.dll", SetLastError = true)]
    static extern bool PostMessage(IntPtr hWnd, [MarshalAs(UnmanagedType.U4)] uint Msg, IntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    const int WM_USER = 0x0400; //http://msdn.microsoft.com/en-us/library/windows/desktop/ms644931(v=vs.85).aspx

    static void Main(string[] args)
    {
        try
        {
            var ptr = FindWindow("Shell_TrayWnd", null);
            Console.WriteLine("INIT PTR: {0}", ptr.ToInt32());
            PostMessage(ptr, WM_USER + 436, (IntPtr)0, (IntPtr)0);

            do
            {
                ptr = FindWindow("Shell_TrayWnd", null);
                Console.WriteLine("PTR: {0}", ptr.ToInt32());

                if (ptr.ToInt32() == 0)
                {
                    Console.WriteLine("Success. Breaking out of loop.");
                    break;
                }

                Thread.Sleep(1000);
            } while (true);
        }
        catch (Exception ex)
        {
            Console.WriteLine("{0} {1}", ex.Message, ex.StackTrace);
        }
        Console.WriteLine("Restarting the shell.");
        string explorer = string.Format("{0}\\{1}", Environment.GetEnvironmentVariable("WINDIR"), "explorer.exe");
        Process process = new Process();           
        process.StartInfo.FileName = explorer;
        process.StartInfo.UseShellExecute = true;
        process.Start();

        Console.ReadLine();

    }
}
}

لقد لاحظت أن أي شخص يعالج مشكلة بدء تشغيل Explorer.exe كقافت، بدلا من فتح نافذة مستكشف فقط. أخذني بعض الوقت لمعرفة ذلك، اتضح أنه شيء بسيط:

string explorer = string.Format("{0}\\{1}", Environment.GetEnvironmentVariable("WINDIR"), "explorer.exe");
        Process process = new Process();
        process.StartInfo.FileName = explorer;
        process.StartInfo.UseShellExecute = true;
        process.Start();

يجب عليك تعيين startinfo.useshellexecute على أنها حقيقية للحصول عليه لإعادة تشغيلها كشرف.

بعد FindWindow استخدم GetWindowthreadProcessID، ثم OpenProcess، ثم إنهاء الإعفاء.

بعد بعض googling، وصلت إلى الحل C # التالي:


using System.Diagnostics;
...
static public void RestartExplorer()
{
    foreach(Process p in Process.GetProcesses())  {
       if(p.MainModule.ModuleName.contains("explorer") == true)
         p.Kill();
    }
    Process.Start("explorer.exe");
}

هذا يعمل بالنسبة لي في Vista:

DWORD dwPID;
HANDLE hExp;
HWND hSysTray = ::FindWindow (TEXT("Shell_TrayWnd"), NULL) ;
GetWindowThreadProcessId (hSysTray, &dwPID);
hExp = OpenProcess (PROCESS_TERMINATE, FALSE, dwPID);

if (hExp)
{
   TerminateProcess (hExp, 0);
}
Sleep (2000);
ShellExecute (NULL, NULL, TEXT("explorer.exe"), NULL, NULL, SW_HIDE);

لكنني لا أستطيع إيجاد أي طريقة لقمع النافذة الاستكشاف التي تفتح (حاولت، وبالتالي SW_Hide). على Vista، يبدو أن تشغيل Explorer.exe بدون معلمات هو نفس تشغيل "Explorer.exe / E" على الأنظمة السابقة. عليك أن تجربها لنفسك على XP، ليس لدي هنا.

ملاحظة: يبدو أن استخدام TermateProcess متطرفا، ولكن نشر WM_CLOSE إلى Explorer يثير مربع حوار إيقاف تشغيل Windows.

هذا هو لنظام التشغيل Windows 7/8 (وتحتاج إلى اختبار، ربما حتى يعمل على نظام التشغيل Vista).

حيث هناك طريقة مناسبة لإغلاق المستكشف (Progman) المدرجة في نظام التشغيل Windows 7 & 8 - بالنقر بزر الماوس الأيمن شريط المهام (shell_traywnd في win8 أو startmenu على win7) أثناء الضغط على Ctrl-Shift, ، يظهر في القائمة المنبثقة خيار مخفي لإغلاق المستكشف, ، وحفره باستخدام التجسس ++ يتم تشغيله بالرسالة WM_USER + 436..

لذلك اختبرت والقيام بما يلي ذلك يعمل بشكل رائع.

PostMessage(FindWindow('Shell_TrayWnd'),nil),WM_USER+436,0,0);

يغلق المستكشف، مع كل المثيلات المفتوحة. وإعادة تشغيل Explorer، استخدم الأساليب المقدمة أعلاه.

وبالتالي، يرجى تأكيد في تعليقات إذا كان هذا يعمل على إصدارات 32 بت / 64 بت من نظام التشغيل Windows Vista / 7/8 أو أي شيء آخر.

AC # الحل الذي يوفر أكثر اليقين أن عمليات المستكشف "الصحيحة" تقتل.

using System;
using System.Diagnostics;

...............

public static void RestartExplorer()
 {
 const string explorer = "explorer.exe";
 string explorerPath = string.Format("{0}\\{1}", Environment.GetEnvironmentVariable("WINDIR"), explorer);
 foreach (Process process in Process.GetProcesses())
  {
  // In case we get Access Denied
  try
   {
   if (string.Compare(process.MainModule.FileName, explorerPath, StringComparison.OrdinalIgnoreCase) == 0)
    {
    process.Kill();
    }
   }
  catch
   {
   }
  }
 Process.Start(explorer);
 }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top