简体   繁体   中英

How to search in the system path for a file?

I have x.dll in some folder which is part of the system path. And I also have some another file x.zzz in the same folder and this is not an executable.

From a C++ program, I want to search for x.zzz without loading the x.dll . But I want this to work exactly like the LoadLibrary function. ie, it should go in the same order of search as the LoadLibrary .

Is this possible?

PS : I checked SearchPath() function, but there is a remark in the documentation which says this shouldn't be used for this purpose.

The SearchPath function is not recommended as a method of locating a .dll file if the intended use of the output is in a call to the LoadLibrary function. This can result in locating the wrong .dll file because the search order of the SearchPath function differs from the search order used by the LoadLibrary function. If you need to locate and load a .dll file, use the LoadLibrary function.

The problem with using any built in function is that they'll be specifically looking for executables or dlls. I'd say your best bet is to actually parse the path variable and iterate through the directories manually. This can be done with C functions for directory iteration. The following should work on most platforms.

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

How about using LoadLibraryEx() with flag LOAD_LIBRARY_AS_IMAGE_RESOURCE?

From the LoadLibraryEx documentation :

If this value is used, the system maps the file into the process's virtual address space as an image file. However, the loader does not load the static imports or perform the other usual initialization steps. Use this flag when you want to load a DLL only to extract messages or resources from it.

I realize you said "without loading"... but using this technique would keep the .dll's functions and variables from polluting your namespaces, etc. If you have a performance requirement, or some other specific reason to specify "without loading", do expand on that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM