我正在开发一个Windows shell扩展,不幸的是,在更改DLL时,我必须重新启动Windows资源管理器(因为它将DLL保存在内存中)。
我从Dino Esposito找到了这个程序,但它对我不起作用。
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进行开发,但shell重启功能可以是C,C ++或.NET语言。它只是一个小型的独立可执行文件。
答案 0 :(得分:10)
在解析了一些早期的答案并做了一些研究之后,我在C#中创建了一个完整的例子。这将关闭资源管理器shell,然后等待它完全关闭并重新启动它。希望这会有所帮助,这个帖子中有很多有趣的信息。
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();
}
}
}
答案 1 :(得分:6)
我注意到没有人解决启动explorer.exe作为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();
您必须将StartInfo.UseshellExecute设置为true才能使其作为shell重新启动。
答案 2 :(得分:5)
一个万无一失的解决方案:
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");
答案 3 :(得分:1)
在FindWindow之后使用GetWindowThreadProcessId,然后使用OpenProcess,然后使用TerminateProcess。
答案 4 :(得分:1)
经过一番谷歌搜索后,我想出了以下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");
}
答案 5 :(得分:1)
这适用于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会引发Windows关闭对话框。
答案 6 :(得分:1)
这适用于Windows 7/8(需要测试,甚至可能适用于Vista)。
由于有一种正确的方法可以关闭Windows 7和Windows 7中包含的Explorer (progman)。 8 - 右键单击任务栏(Win8中的Shell_TrayWnd或Win7上的StartMenu),同时按Ctrl-Shift ,它会在弹出菜单中显示关闭的隐藏选项资源管理器,并使用Spy ++挖掘它,它由消息 WM_USER + 436 触发。
所以我测试并做了以下工作,效果很好。
PostMessage(FindWindow('Shell_TrayWnd'),nil),WM_USER+436,0,0);
它会关闭所有已打开实例的资源管理器。要重新启动资源管理器,请使用上面提供的方法。
因此,请在评论中确认,如果这适用于Windows Vista / 7/8或其他任何版本的32位/ 64位版本。
答案 7 :(得分:0)
一种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);
}
答案 8 :(得分:0)
我不知道这是否适用于所有人,但是在我的PC上为我工作时,我的系统是win10。可以用cmd.exe单词解决。调用tskill命令。
Process.Start("cmd.exe", "/s /c tskill explorer");
如果您不想看到它cmd.exe,如果黑色窗口闪烁,您可以使用以下代码
ProcessStartInfo info = new ProcessStartInfo {
FileName = "cmd.exe",
Arguments = "/s /c tskill explorer",
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = true
};
new Process { StartInfo = info }.Start();
现在我认为最好的方法是:
using(Process process = new Process())
{
process.StartInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/c taskkill -f -im explorer.exe",
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = true
};
process.Start();
process.WaitForExit();
process.StartInfo.Arguments = "/c explorer";
process.Start();
}