Question

Je travaille sur une fenêtre shell extension, et malheureusement, lors des modifications à la DLL, je dois redémarrer l'explorateur Windows (car il conserve la DLL en mémoire).

J'ai trouvé ce programme de Dino Esposito, mais il ne fonctionne pas pour moi.

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

Est-ce que quelqu'un a quelque chose qu'ils peuvent partager le faire?

P.S. Je me rends compte que je peux aller le gestionnaire de tâches et de tuer le processus de l'explorateur, mais je veux juste faire de la manière paresseuse. De plus, cela permet l'automatisation.

P.P.S J'utilise .NET pour le développement, mais la fonctionnalité de redémarrage shells peut être en C, C ++ ou un langage .NET. Il sera tout simplement un petit exécutable autonome.

Était-ce utile?

La solution

Une solution infaillible:

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

Autres conseils

Après l'analyse quelques-unes des réponses précédentes et de faire un peu de recherche, j'ai créé un petit exemple complet en C #. Cela ferme la coquille de l'explorateur attend ensuite à arrêter complètement et redémarre. Espérons que cela aide, il y a beaucoup d'informations intéressantes dans ce fil.

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

    }
}
}

Je ne remarqué abordé la question de explorer.exe à partir de la coquille, plutôt que de simplement ouvrir une fenêtre de l'explorateur. Il m'a fallu un certain temps pour comprendre cela, se révèle qu'il était quelque chose de 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();

Vous devez définir le StartInfo.UseshellExecute comme vrai pour l'obtenir pour redémarrer comme shell.

Après FindWindow utiliser GetWindowThreadProcessId, puis OpenProcess, puis TerminateProcess.

Après un peu plus googler, je suis venu avec la solution C # suivante:


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

Cela fonctionne pour moi sur 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);

Mais je ne peux pas trouver un moyen de supprimer la fenêtre Explorer qui ouvre (j'ai essayé, d'où le SW_HIDE). Sur Vista, en cours d'exécution explorer.exe sans paramètres semble être le même que l'exécution « explorer.exe / e » sur les systèmes antérieurs. Vous devrez essayer pour vous-même sur XP, je ne l'ai pas ici.

Remarque: L'utilisation TerminateProcess ne semble extrême, mais affichant un WM_CLOSE à explorer provoque une boîte de dialogue d'arrêt Windows

.

Ceci est pour Windows 7/8 (et besoin d'être testé, peut-être fonctionne même sur Vista).

Depuis il y a une bonne façon de fermer l'explorateur (progman) inclus dans Windows 7 et 8 - en cliquant à droite la barre des tâches (Shell_TrayWnd dans Win8 ou StartMenu sur Win7) tout en appuyant sur les touches Ctrl-Shift , il affiche dans le menu contextuel une option cachée pour fermer l'explorateur , et creuser à l'aide de Spy ++ il est déclenché par un message WM_USER + 436 .

J'ai testé et de faire ce qui suit, il fonctionne très bien.

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

Il ferme Explorer, avec toutes les instances ouvertes. Et pour relancer l'explorateur, utilisez les méthodes fournies ci-dessus.

s'il vous plaît confirmer dans les commentaires si cela fonctionne sur les éditions 32 bits / 64 bits de Windows Vista / 7/8 ou tout autre.

Une solution C # qui fournit plus de certitude que les processus de l'explorateur « droit » tués.

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);
 }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top