【问题标题】:How to search in the system path for a file?如何在系统路径中搜索文件?
【发布时间】:2014-03-20 15:23:59
【问题描述】:

我在某个文件夹中有x.dll,它是系统路径的一部分。而且我在同一个文件夹中还有另一个文件x.zzz,这不是可执行文件。

在 C++ 程序中,我想在不加载 x.dll 的情况下搜索 x.zzz。但我希望它能够像LoadLibrary 函数一样工作。即,它的搜索顺序应与 LoadLibrary 相同。

这可能吗?

PS: 我检查了SearchPath() 函数,但documentation 中有一条注释说这不应该用于此目的。

不推荐使用 SearchPath 函数作为查找 .dll 文件的方法,如果 输出的预期用途是调用 LoadLibrary 函数。这可能导致 在定位错误的 .dll 文件中,因为 SearchPath 函数的搜索顺序 与 LoadLibrary 函数使用的搜索顺序不同。如果您需要定位 并加载 .dll 文件,使用 LoadLibrary 函数。

【问题讨论】:

  • 我怀疑您提出的问题没有好的答案。你真正的根本问题是什么?
  • @David:x.zzz 包含一些我们用来实现反射的辅助信息。所以,我们需要打开这个文件并检查这里是否存在一些类。是的,看起来没有直接的方法可以实现这一点。我们会找到一些肮脏的方法来实现这一点。谢谢。
  • 与其使用肮脏的方式来做到这一点,也许您可​​以实施更好的解决方案
  • 是的。我所描述的“肮脏”是用 findfiles 等或类似的东西自己编写一个很长的例程.... :)
  • 我们对这个确切问题的解决方案是通过一系列低级调用(我记得是 FIndFirstFile)来模拟 LoadLibrary 的行为。没有其他方法做得很对。

标签: c++ winapi


【解决方案1】:

使用任何内置函数的问题在于它们会专门寻找可执行文件或 dll。我想说你最好的选择是实际解析路径变量并手动遍历目录。这可以通过目录迭代的 C 函数来完成。以下内容应该适用于大多数平台。

#include <dirent.h>
#include <cstdlib>
#include <iostream>
#include <string>
...
std::string findInPath(const std::string &key, char delim = ';');
std::string findInDir(const std::string &key, const std::string &dir);
...
std::string findInDir(const std::string &key, const std::string &directory)
{
  DIR *dir = opendir(directory.c_str());
  if(!dir)
    return "";

  dirent *dirEntry;
  while(dirEntry = readdir(dir))
  {
    if(key == dirEntry->d_name) // Found!
      return directory+'/'+key;
  }
  return "";
}

std::string findInPath(const std::string &key, char delim)
{
  std::string path(std::getenv("PATH"));
  size_t posPrev = -1;
  size_t posCur;
  while((posCur = path.find(delim, posPrev+1)) != std::string::npos)
  {
    // Locate the next directory in the path
    std::string pathCurrent = path.substr(posPrev+1, posCur-posPrev-1);

    // Search the current directory
    std::string found = findInDir(key, pathCurrent);
    if(!found.empty())
      return found;

    posPrev = posCur;
  }

  // Locate the last directory in the path
  std::string pathCurrent = path.substr(posPrev+1, path.size()-posPrev-1);

  // Search the current directory
  std::string found = findInDir(key, pathCurrent);
  if(!found.empty())
    return found;

  return "";
}

【讨论】:

  • LoadLibrary 的搜索逻辑比仅仅在 PATH 中查找要多得多。
【解决方案2】:

如何使用带有标志 LOAD_LIBRARY_AS_IMAGE_RESOURCE 的 LoadLibraryEx()?

来自LoadLibraryEx documentation:

如果使用此值,系统会将文件作为映像文件映射到进程的虚拟地址空间。但是,加载器不会加载静态导入或执行其他通常的初始化步骤。如果您只想加载 DLL 以从中提取消息或资源,请使用此标志。

我意识到您说“不加载”...但是使用此技术可以防止 .dll 的函数和变量污染您的命名空间等。如果您有性能要求或其他特定原因来指定“不加载” ",请继续扩展。

【讨论】:

  • 我以前见过这种情况,但由于加载开销而被排除在外。但看起来这是我所能得到的。如果再过半小时没有其他消息,我会接受。
  • 除非文件是 PE 文件,否则我认为这不会起作用。即使是这样,您将如何找到文件名?致电GetModuleFileName?!
  • 如果你使用LOAD_LIBRARY_AS_DATAFILE,“你不能用这个DLL调用函数像GetModuleFileName、GetModuleHandle或GetProcAddress”。因此,您必须找到另一种方法来检索与已加载 DLL 的句柄关联的文件名。
  • 公平地说,我已经编辑了答案,甚至没有提到 _AS_DATAFILE。
猜你喜欢
  • 2018-12-28
  • 1970-01-01
  • 2017-01-11
  • 2011-09-13
  • 2014-12-13
  • 2012-04-30
  • 2022-08-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多