【问题标题】:How to restart explorer without taskkill如何在没有taskkill的情况下重新启动资源管理器
【发布时间】:2020-04-26 08:34:01
【问题描述】:

没有taskkill有没有办法重启资源管理器?

我编写了一个程序,在其中我对注册表进行了一些更改,并且要应用这些更改需要重新启动 explorer.exe,但是我不想使用taskkill,有没有其他方法可以重新启动@ 987654323@?

【问题讨论】:

  • 那么,您已经了解了如何重新启动其他程序,但是这对资源管理器不起作用?它在什么方面不起作用?
  • @UlrichEckhardt 不,它适用于资源管理器,但我不想使用它,taskkill 关闭所有打开的窗口,我不希望发生这种情况
  • @mopebi 那些窗口是 explorer.exe,它是文件资源管理器,GUI 的主要外壳
  • 你认为那些打开的窗口是从哪里来的?计算不是魔法,你杀死进程,你就失去了窗口。
  • 通常的礼仪主要安装程序正在请求关闭资源管理器的权限,因此用户可以完成他们正在做的任何事情然后继续安装,或者接受程序在重新启动之前无法使用。

标签: c++ c windows winapi explorer


【解决方案1】:

您可以使用Restart Manager API:

重启管理器按以下顺序停止应用程序,并且 应用程序更新后,重新启动应用程序 已按相反顺序注册重启。

  • GUI 应用程序
  • 控制台应用程序
  • Windows 服务 Windows
  • 探索者

【讨论】:

  • 谢谢,这样对我的情况有用吗? 我的程序不是一个大程序,它是模拟任务栏设置>任务栏>打开或关闭系统图标的大学家庭作业我编写了代码,如果用户例如选择隐藏时钟图标,我更改 HideClock in HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer,我认为有一些方法不需要 taskkill explorer.exe,因为当我们在任务栏设置中进行这些更改时,它不需要任何东西
  • @mop - 我看不出它不应该工作的原因,这是微软的官方方式。由于它与资源管理器合作,重启前打开的文件夹视图窗口在重启后重新打开,因此最终用户体验几乎是无缝的。例如,许多供应商将其用于需要安装 shell 扩展的设置。
  • 谢谢,我用过,它工作正常,但问题是当我使用RmShutdown 然后RmRestart 屏幕变黑并且任务栏消失(就像我们在重新启动资源管理器时一样任务管理器)。我不喜欢这种情况发生,我想应用这些更改,例如当我们从 Taskbar Settings > Taskbar > Turn system icon on or off 更改它们时有什么办法吗?
  • @mopebi - 如果我没记错的话,任务栏会消失并重新出现。所以它有点闪烁,这在视觉上并不好。然而,这仍然是要走的路。检查一切是否正常工作的一件事是验证打开的视图(如文件资源管理器视图)应该在关机前的状态(位置、大小、内容等)下自动重新打开
【解决方案2】:

Sheng Jiang's blog(来自 Microsoft)有一篇很好的文章解释了如何使用重启管理器 API 优雅地重启资源管理器:

//returns the process id and create time for the oldest explorer.exe 
RM_UNIQUE_PROCESS GetExplorerApplication()
{
    RM_UNIQUE_PROCESS  result={0};
    DWORD bytesReturned=0;
    DWORD processIdSize=4096;
    std::vector<DWORD> processIds;
    processIds.resize(1024);
    EnumProcesses(processIds.data(),processIdSize,&bytesReturned);
    while(bytesReturned==processIdSize)
    {
        processIdSize+=processIdSize;
        processIds.resize(processIdSize/4);
        EnumProcesses(processIds.data(),processIdSize,&bytesReturned);
    }    std::for_each(processIds.begin(), processIds.end(), [&result] (DWORD processId) {
         HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,
                                   FALSE, processId);
         if (hProcess) {
            std::wstring imageName;
            imageName.resize(4096);
            if(GetProcessImageFileName (hProcess,(LPWSTR)imageName.data(),4096)>0)
            {
                if(wcscmp(L"explorer.exe",PathFindFileName(imageName.data()))==0)
                {
                    //this is assmuing the user is not running elevated and won't see explorer processes in other sessions
                    FILETIME ftCreate, ftExit, ftKernel, ftUser;
                    if (GetProcessTimes(hProcess, &ftCreate, &ftExit,&ftKernel, &ftUser))
                    {
                        if(result.dwProcessId==0)
                        {
                            result.dwProcessId=processId;
                            result.ProcessStartTime=ftCreate;
                        }
                        else if(CompareFileTime(&result.ProcessStartTime,&ftCreate)>0)
                        {
                            result.dwProcessId=processId;
                            result.ProcessStartTime=ftCreate;
                        }
                    }
                }
            }
            CloseHandle(hProcess);
         }
    });
    return result;
}

//taskbar position calculating code omitted
    DWORD dwSession=0;
    WCHAR szSessionKey[CCH_RM_SESSION_KEY+1] = { 0 };
    DWORD dwError = RmStartSession(&dwSession, 0, szSessionKey);
    if (dwError == ERROR_SUCCESS) {
        RM_UNIQUE_PROCESS rgApplications[1]={GetExplorerApplication()};
        dwError=RmRegisterResources(
            dwSession,0,NULL,1,rgApplications,0,NULL);
        DWORD dwReason;
        UINT nProcInfoNeeded;
        UINT nProcInfo = 10;
        RM_PROCESS_INFO rgpi[10];
        dwError = RmGetList(dwSession, &nProcInfoNeeded,
                       &nProcInfo, rgpi, &dwReason);
        if(dwReason==RmRebootReasonNone)//now free to restart explorer
        {
            RmShutdown(dwSession,RmForceShutdown,NULL);//important, if we change the registry before shutting down explorer will override our change
            //using undocumented setting structure, could break any time
            //edge setting is stored at HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\StuckRects2!Settings
            HKEY hKey={0};
            DWORD result=0;
            result=::RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StuckRects2"),
                    0, KEY_READ|KEY_WRITE, &hKey) ;
            if (result== ERROR_SUCCESS)
            {
                std::vector<BYTE> data;
                data.resize(256);
                TCHAR settingValue[]= _T("Settings");
                DWORD dwKeyDataType=0;
                DWORD dwDataBufSize=data.size();
                result=::RegQueryValueEx(hKey,settingValue, NULL, &dwKeyDataType,
                    (LPBYTE) data.data(), &dwDataBufSize);
                while(ERROR_MORE_DATA==result)
                {
                    data.resize(256+data.size());
                    dwDataBufSize=data.size();
                    result=::RegQueryValueEx(hKey,settingValue, NULL, &dwKeyDataType, 
                        (LPBYTE) data.data(), &dwDataBufSize);
                }
                data.resize(dwDataBufSize);
                if(result==ERROR_SUCCESS)
                {
                    switch ( dwKeyDataType )
                    {
                        case REG_BINARY:
                            if(data.size()==40)
                            {
                                BYTE taskbarPosition=data[12];
                                taskbarPosition=edge;
                                data[12]=taskbarPosition;
                                RECT* taskbarRect=(RECT*)&data[24];
                                CopyRect (taskbarRect,&abd.rc);
                                result=::RegSetValueEx(hKey,settingValue,0,REG_BINARY,(LPBYTE) data.data(), dwDataBufSize);
                            }
                            break;
                    }
                }
                ::RegCloseKey( hKey );
            }
            RmRestart (dwSession,0,NULL);
        }
    }
    RmEndSession(dwSession);

【讨论】:

  • 谢谢,我用过,它工作正常,但问题是当我使用RmShutdown 然后RmRestart 屏幕变黑并且任务栏消失(就像我们在任务管理器)。我不喜欢这种情况发生,我想应用这些更改,例如当我们从 Taskbar Settings &gt; Taskbar &gt; Turn system icon on or off 更改它们时有什么办法吗?
  • 这是一个不同的问题 - 如何在不重新启动资源管理器的情况下关闭系统图标。我不知道,对不起..
【解决方案3】:

可能根本不需要重新启动资源管理器。

可能有一些 Windows 消息可以用来更新必要的东西。 例如,通知区域图标在RegiserWindowsMessage("TaskbarCreated") 上重新创建,一些设置适用于WM_SETTINGCHANGE

或者,有问题的设置可以通过除了注册表写入之外刷新的 API 访问。

在重新启动之前考虑“更温和”的方法。

【讨论】:

  • 我在更改注册表后测试了SendMessage(GetSystemTray(), WM_PAINT, 0, 0);SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0, SMTO_ABORTIFHUNG, 100, 0);,但没有效果...
  • 这些只是例子,还有更多的刷新方式。大多数此类设置应仅由某些 API 更改,因此这些 API 会进行刷新和注册表更新。对于 shell,有很多 shell API 函数和接口。
  • 使用 procmon 并查看注册表更改的调用堆栈可能有助于找到正确的 API。或披露相关设置。
猜你喜欢
  • 2018-12-16
  • 1970-01-01
  • 2013-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-24
  • 1970-01-01
相关资源
最近更新 更多