Pregunta

Estoy trabajando en un Windows Shell Extension, y por desgracia, al realizar cambios en el archivo DLL, debo reiniciar el Explorador de Windows (ya que mantiene el archivo DLL en la memoria).

He encontrado este programa de Dino Esposito, pero no funciona para mí.

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

¿Alguien tiene algo que pueden compartir para hacer esto?

P.S. Soy consciente de que puedo ir al Administrador de tareas y matar el proceso explorador, pero sólo quiero hacerlo de la manera perezosa. Además, esto permite la automatización.

P.P.S estoy usando .NET para el desarrollo, pero la funcionalidad de reinicio Shell podría estar en C, C ++ o un lenguaje .NET. Será simplemente un pequeño ejecutable independiente.

¿Fue útil?

Solución

Una solución a toda prueba:

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

Otros consejos

Después de analizar algunas de las respuestas anteriores y haciendo un poco de investigación, he creado un pequeño ejemplo completo en C #. Esto cierra la concha explorador entonces espera a que apagar completamente y lo reinicia. Espero que esta ayuda, hay una gran cantidad de información interesante en este hilo.

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

    }
}
}

Me di cuenta de que nadie abordó la cuestión de explorer.exe comenzando como la concha, en lugar de simplemente abrir una ventana del explorador. Me tomó un tiempo para resolver esto, resulta que era algo simple:

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

Se tiene que establecer la StartInfo.UseshellExecute como verdadero para conseguir que se reinicie como la cáscara.

Después de FindWindow utilizar GetWindowThreadProcessId, entonces OpenProcess, entonces TerminateProcess.

Después de un poco más de google, me ocurrió con la siguiente solución 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");
}

Esto funciona para mí en 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);

Pero no puedo encontrar ninguna manera de suprimir la ventana que se abre explorar (probé, de ahí el SW_HIDE). En Vista, corriendo explorer.exe sin parámetros parece ser el mismo que ejecutar "explorer.exe / e" en los sistemas anteriores. Vas a tener que intentarlo por sí mismo en XP, no tengo aquí.

Nota: El uso TerminateProcess no parecer extremo, pero publicar un WM_CLOSE a explorador provoca un cuadro de diálogo de apagado de Windows

.

Esto es para Windows 7/8 (y la necesidad de pruebas, tal vez incluso funciona en Vista).

Desde hay una forma correcta de cerrar el Explorador (progman) incluido en Windows 7 y 8 - haciendo clic derecho la barra de tareas (Shell_TrayWnd en Win8 o StartMenu en Win7) mientras pulsa Ctrl-Shift , se muestra en el menú desplegable una opción oculta para cerrar el Explorador , y la excavación utilizando Spy ++ que es disparado por el mensaje WM_USER + 436 .

Así que probar y haciendo lo siguiente funciona muy bien.

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

Se cierra el Explorador, con todas las instancias abiertas. Y para relanzar Explorer, utilice los métodos proporcionados anteriormente.

Por lo tanto, por favor confirmar en los comentarios si esto funciona en las ediciones de 32 bits / 64 bits de Windows Vista / 7/8 o cualquier otro.

Una solución de C # que proporciona más seguridad de que los procesos de explorador "correctas" matan.

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);
 }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top