【问题标题】:How to get the full path to the Windows Explorer in C++如何在 C++ 中获取 Windows 资源管理器的完整路径
【发布时间】:2012-11-21 00:26:32
【问题描述】:

我可以安全地假设 Windows 资源管理器总是从 Windows 系统目录启动吗?另外,它的进程是否总是命名为“explorer.exe”?

如果没有,如何获取其完整的文件路径?

编辑: 忘了提——我需要它来稍后找出在给定用户会话中运行的 Windows 资源管理器的进程 ID。因此我在寻找它的完整路径。

编辑 2:感谢所有做出贡献的人,尤其是 sehe!在他的帖子之后,我找到了this page,它解释了如何设置自己的 shell。我通过用自己的进程完全替换 explorer.exe 进行了疯狂测试,结果如下: 这是full-size link,如果你重新调整大小的话。

如您所见,从技术上讲,我可以用我想出的任何进程替换 explorer.exe。正如您在我的屏幕截图中看到的那样,Windows 让我可以完全控制 Shell(屏幕截图是我的整个窗口。)

因此,最重要的是,获取“explorer.exe”文件路径(或使用的任何 Shell 进程)的唯一方法是使用我上面引用的链接中的那些注册表项 - 非常接近 sehe 建议的内容,只需再做一些检查,但这是一个非常简单的事情。

至于 Sean Cline 的建议,只有当我们运行带有具有特定类名的托盘窗口的“普通”Windows 资源管理器时,这将是一个非常优雅的解决方案。

【问题讨论】:

  • 您可能希望更具体地了解您要完成的工作。根据您想要做什么,可能没有必要对 shell 的名称或位置做出任何假设。
  • 是的,我很抱歉。我需要知道在给定用户会话中运行的 Windows 资源管理器的进程 ID。因此我在寻找它的完整路径。
  • 我自己想不出有什么理由知道 shell 进程的 PID,但我已经更新了我的答案。希望它能为您指明正确的方向。
  • 如果您解释为什么需要 pid,也许有人可以解决您的实际问题。你不能用 explorer 的 pid 做很多事情。您应该使用适当的 shell API。有explorer不是shell的终端服务场景,当然也有运行多个explorer副本的情况。
  • @RaymondChen:我需要 Windows Explorer 的 PID 来确定特定进程是由用户启动还是由系统启动。这是一个完全不同的讨论,但简而言之,我使用子父进程树来确定这种继承。

标签: c++ winapi windows-explorer


【解决方案1】:

可以安全地假设 explorer.exe 始终位于 %windir% 或 %SystemRoot% 中,因为它已经多年没有移动了。但是,如果您尝试通过 Explorer 调用某些东西,您可能想改用 ShellExecute() 函数。

如果您确实需要该路径,获取它的最简单方法可能是使用 FOLDERID_Windows 作为第一个参数调用 SHGetKnownFolderPath()。

编辑: 这是我知道您正在寻找 shell 进程的 PID 的一些代码:

DWORD trayPID;
HWND trayWnd = FindWindow("Shell_TrayWnd", NULL);
GetWindowThreadProcessId(trayWnd, &trayPID);

它查找任务栏的 hWnd 并找到拥有的 PID。您可能需要为资源管理器未运行且该窗口不存在的情况添加一些错误处理 - 不太可能,但可能。

【讨论】:

  • 我实际上是使用 GetWindowsDirectory() 来获取系统文件夹。但是现在在阅读了@sehe 的评论后,我倾向于认为我需要从外壳(从注册表)中获取资源管理器的名称。
  • 是的,非正统解决方案 +1。虽然仍然不是最终答案,但正如您所指出的,托盘窗口可能不存在。
  • 更新:在我的原始答案中发布了解决方案。
【解决方案2】:

不,您不能安全地假设这与 C++ 无关。

另外,您没有显示任何代码。如下:

此注册表项是Software\Microsoft\Windows NT\CurrentVersion\WinLogon\Shell(请参阅here)。

#include <windows.h>
#include <malloc.h>
#include <stdio.h>
#include <string>

LONG GetStringRegKey(HKEY hKey, const std::wstring &strValueName, std::wstring &strValue, const std::wstring &strDefaultValue)
{
    strValue = strDefaultValue;
    WCHAR szBuffer[512];
    DWORD dwBufferSize = sizeof(szBuffer);
    ULONG nError;
    nError = RegQueryValueExW(hKey, strValueName.c_str(), 0, NULL, (LPBYTE)szBuffer, &dwBufferSize);
    if (ERROR_SUCCESS == nError)
    {
        strValue = szBuffer;
    }
    return nError;
}

int main()
{
    HKEY hKey;
    LONG lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon", 0, KEY_READ, &hKey);
    bool bExistsAndSuccess (lRes == ERROR_SUCCESS);
    bool bDoesNotExistsSpecifically (lRes == ERROR_FILE_NOT_FOUND);
    std::wstring shell;
    GetStringRegKey(hKey, L"Shell", shell, L"");
}

【讨论】:

  • 应该注意,“Shell”注册表项有几个注意事项。它不包括完整路径,只包括可执行文件名称。此外,任何安装了常规 shell 替代品的用户都将对该键具有不同的值,尽管这种情况非常罕见。
  • @sehe 感谢您的意见。我不知道这样的注册表项。那么,由于那里没有完整路径,我可以假设该文件位于我可以从 GetWindowsDirectory() 调用中获取的系统文件夹中吗?
  • 我根据您的建议用解决方案更新了我的原始问题。再次感谢。
  • @SeanCline 哦,这让我很惊讶。我没有 Windows 机器来测试代码。我只是在文本编辑器中编写的。此外,如果用户使用不同的 shell,您将获得不同的可执行文件,这完全是目的!为什么不“硬编码”%WINDIR%\explorer.exe,否则
【解决方案3】:

两者都是。 Windows 资源管理器始终位于 %WINDIR%\Explorer.exe

【讨论】:

  • 真的吗?!我不相信。你能引用一个来源吗?
  • 是的,同意。虽然,由于我没有通过将 Shell 进程称为 explorer.exe 来正确表达我最初的问题,但他可能专门针对“股票”Windows Explorer 的说法是正确的。
猜你喜欢
  • 2018-05-20
  • 2015-02-19
  • 1970-01-01
  • 2017-01-08
  • 2017-10-30
  • 2017-07-07
  • 2010-11-05
  • 2020-08-03
  • 1970-01-01
相关资源
最近更新 更多