Как программно перезапустить процесс Windows Explorer - PullRequest
7 голосов
/ 19 февраля 2009

Я работаю над расширением оболочки Windows, и, к сожалению, при внесении изменений в DLL я должен перезапустить проводник Windows (поскольку он сохраняет 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;
}

У кого-нибудь есть что-то, чем они могут поделиться?

P.S. Я понимаю, что могу зайти в диспетчер задач и убить процесс проводника, но я просто хочу сделать это ленивым способом. Кроме того, это позволяет автоматизировать.

P.P.S Я использую .NET для разработки, но функциональность перезапуска оболочки может быть на языке C, C ++ или .NET. Это будет просто небольшой исполняемый файл.

Ответы [ 8 ]

10 голосов
/ 04 мая 2012

После анализа некоторых из предыдущих ответов и небольшого исследования я создал небольшой законченный пример на C #. Это закрывает оболочку проводника, затем ждет его полного выключения и перезапускает. Надеюсь, это поможет, в этой теме много интересной информации.

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();

    }
}
}
6 голосов
/ 02 мая 2011

Я заметил, что никто не обращался к вопросу запуска 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 как true, чтобы перезапустить его как оболочку.

5 голосов
/ 22 февраля 2009

Надежное решение:

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");
1 голос
/ 03 октября 2011

Это для Windows 7/8 (и нуждается в тестировании, возможно, даже работает на Vista).

Поскольку существует правильный способ закрыть Explorer (progman), включенный в Windows 7 & 8 - , щелкнув правой кнопкой мыши панель задач (Shell_TrayWnd в Win8 или StartMenu на Win7) при нажатии Ctrl-Shift во всплывающем меню отображается скрытый параметр, чтобы закрыть Explorer , и копать его с помощью Spy ++ запускает сообщение WM_USER + 436 .

Итак, я проверил и сделал следующее, он прекрасно работает.

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

Закрывает Проводник со всеми открытыми экземплярами. А чтобы перезапустить проводник, воспользуйтесь указанными выше способами.

Итак, , пожалуйста, подтвердите в комментариях, если это работает на 32-битных / 64-битных выпусках Windows Vista / 7/8 или любых других.

1 голос
/ 19 февраля 2009

Это работает для меня в 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, у меня его здесь нет.

Примечание: использование TerminateProcess кажется экстремальным, но публикация WM_CLOSE в проводнике вызывает диалог закрытия окон.

1 голос
/ 19 февраля 2009

После еще одного поиска, я нашел следующее решение 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");
}
1 голос
/ 19 февраля 2009

После FindWindow используйте GetWindowThreadProcessId, затем OpenProcess, затем TerminateProcess.

0 голосов
/ 25 сентября 2009

Решение на C #, обеспечивающее большую уверенность в том, что «правильные» процессы проводника будут уничтожены.

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