.net - Sådan genstartes Windows Explorer Explorer programatisk

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg arbejder med en Windows Shell-udvidelse, og desværre, når jeg ændrer DLL'en, skal jeg genstarte Windows Explorer (da den holder DLL'en i hukommelsen).


Jeg fandt dette program fra Dino Esposito, men det virker ikke for mig.



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


Har nogen noget, de kan dele for at gøre dette?


P. S. Jeg er klar over, at jeg kan gå til task manager og dræbe explorer processen, men jeg vil bare gøre det doven. Desuden gør det muligt automatisering.


P.P.S Jeg bruger .NET til udviklingen, men shell genstart funktionalitet kunne være i C, C + + eller et. NET sprog. Det vil simpelthen være en lille stand-alone eksekverbar.

Bedste reference


En idiotsikker løsning:


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

Andre referencer 1


Efter at have analyseret nogle af de tidligere svar og lavet en del forskning, har jeg lavet et lille komplet eksempel i C #. Dette lukker explorerskallen og venter derefter på, at den helt lukkes ned og genstarter den. Håber det hjælper, der er meget af interessant info i denne tråd.


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

    }
}
}

Andre referencer 2


Jeg lagde mærke til, at ingen tog op på spørgsmålet om at starte explorer.exe som skallen, snarere end at bare åbne et explorer-vindue. Tog mig et stykke tid for at finde ud af det, viser sig at det var noget simpelt:


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


Du skal indstille StartInfo.UseshellExecute som sand for at få det til at genstarte som shell.

Andre referencer 3


Efter FindWindow bruger GetWindowThreadProcessId, så OpenProcess og derefter TerminateProcess.

Andre referencer 4


Efter nogle flere googling kom jeg op på følgende C # løsning:



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

Andre referencer 5


Dette virker for mig på 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);


Men jeg kan ikke finde nogen måde at undertrykke det udforskningsvindue, der åbnes (jeg forsøgte, derfor SW\_HIDE). På Vista kører explorer.exe uden parametre det samme som at køre 'explorer.exe/e' på tidligere systemer Du skal prøve det selv på XP, jeg har det ikke her.


Bemærk: Brug TerminateProcess virker ekstremt, men udstationering af en WM\_CLOSE til explorer provokerer en windows shutdown dialog.

Andre referencer 6


Dette er til Windows 7/8 (og skal testes, måske endda fungerer på Vista).


Da er der en ordentlig måde at lukke Explorer (progman) med i Windows 7 & 8 - ved at højreklikke på proceslinjen (Shell\_TrayWnd i Win8 eller StartMenu på Win7) mens du trykker på Ctrl-Shift , vises det i pop op-menuen en skjult mulighed for at lukke Explorer og grave det ved hjælp af Spy ++, det udløses af meddelelsen WM\_USER + 436 .


Så jeg testede og gør følgende, det virker godt.


PostMessage(FindWindow('Shell\_TrayWnd'),nil),WM\_USER+436,0,0);


Det lukker Explorer, med alle de åbne instanser. Og for at genstarte explorer skal du bruge de ovenfor beskrevne metoder.


bekræft venligst i kommentarer, hvis dette virker på 32bit/64bit udgaver af din Windows Vista/7/8 eller andre.

Andre referencer 7


En C # -løsning, der giver større sikkerhed for, at 'de rigtige' explorer-processer bliver ramt.


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