Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么';解析文件路径的最佳方法是什么?_C++_Windows_Path - Fatal编程技术网

C++ 什么';解析文件路径的最佳方法是什么?

C++ 什么';解析文件路径的最佳方法是什么?,c++,windows,path,C++,Windows,Path,我有一系列文件路径,看起来像这样: ["C:\Program", "Files", "(x86)\Common", "Files\Steam\SteamService.exe", "/RunAsService"] C:\Windows\System32\svchost.exe-k LocalSystemNetworkRestricted C:\Windows\System32\svchost C:\Program Files(x86)\Common Files\Steam\SteamServ

我有一系列文件路径,看起来像这样:

["C:\Program", "Files", "(x86)\Common", "Files\Steam\SteamService.exe", "/RunAsService"]
  • C:\Windows\System32\svchost.exe-k LocalSystemNetworkRestricted
  • C:\Windows\System32\svchost
  • C:\Program Files(x86)\Common Files\Steam\SteamService.exe/RunaService
  • “C:\Program Files(x86)\Common Files\Steam\SteamService.exe”/RunaService
我需要找到这些路径的实际位置。因此,上述内容分别是:

  • C:\Windows\System32\svchost.exe
  • C:\Windows\System32\svchost.exe
  • C:\Program Files(x86)\Common Files\Steam\SteamService.exe
  • C:\Program Files(x86)\Common Files\Steam\SteamService.exe
做这件事最好的方法是什么?windows有API函数来完成它吗?我实际上是想弄清楚,如果我将可执行CreateProcess传递给它,它将调用什么

谢谢

比利3

编辑:这是我目前确定的代码:

#include <algorithm>
#include <vector>
#include <string>
#include <boost/algorithm/string.hpp>
#include <Windows.h>

namespace Path {

bool Exists(const std::wstring& path)
{
    DWORD result = GetFileAttributesW(path.c_str());
    return result != INVALID_FILE_ATTRIBUTES;
}

#define PATH_PREFIX_RESOLVE(path, prefix, environment) \
if (boost::algorithm::istarts_with(path, prefix)) { \
    ExpandEnvironmentStringsW(environment, buffer, MAX_PATH); \
    path.replace(0, (sizeof(prefix)/sizeof(wchar_t)) - 1, buffer); \
    if (Exists(path)) return path; \
}

std::wstring Resolve(std::wstring path)
{
    using namespace boost::algorithm;
    wchar_t buffer[MAX_PATH];
    trim(path);
    if (path.empty() || Exists(path)) return path;

    //Start by trying to see if we have a quoted path
    if (path[0] == L'"') {
        return std::wstring(path.begin() + 1, std::find(path.begin() + 1, path.end(), L'"'));
    }

    //Check for those nasty cases where the beginning of the path has no root
    PATH_PREFIX_RESOLVE(path, L"\\", L"");
    PATH_PREFIX_RESOLVE(path, L"?\?\\", L"");
    PATH_PREFIX_RESOLVE(path, L"\\?\\", L"");
    PATH_PREFIX_RESOLVE(path, L"globalroot\\", L"");
    PATH_PREFIX_RESOLVE(path, L"system32\\", L"%systemroot%\\System32\\");
    PATH_PREFIX_RESOLVE(path, L"systemroot\\", L"%systemroot%\\");

    static std::vector<std::wstring> pathExts;
    if (pathExts.empty()) {
        #define MAX_ENVVAR 32767
        wchar_t pathext[MAX_ENVVAR];
        DWORD length = GetEnvironmentVariableW(L"PATHEXT", pathext, MAX_ENVVAR);
        if (!length) WindowsApiException::ThrowFromLastError();
        split(pathExts, pathext, std::bind2nd(std::equal_to<wchar_t>(), L';'));
        pathExts.insert(pathExts.begin(), std::wstring());
    }
    std::wstring::iterator currentSpace = path.begin();
    do {
        currentSpace = std::find(currentSpace, path.end(), L' ');
        std::wstring currentPath(path.begin(), currentSpace);
        std::wstring::size_type currentPathLength = currentPath.size();
        typedef std::vector<std::wstring>::const_iterator ExtIteratorType;
        for(ExtIteratorType it = pathExts.begin(); it != pathExts.end(); it++) {
            currentPath.replace(currentPathLength, currentPath.size() - currentPathLength, *it);
            if (Exists(currentPath)) return currentPath;
        }
        if (currentSpace != path.end())
            currentSpace++;
    } while (currentSpace != path.end());

    return path;
}

}
#包括
#包括
#包括
#包括
#包括
名称空间路径{
布尔存在(常量std::wstring和path)
{
DWORD result=GetFileAttributesW(path.c_str());
返回结果!=无效的\u文件\u属性;
}
#定义路径\前缀\解析(路径、前缀、环境)\
if(boost::algorithm::istart_with(path,prefix)){\
ExpandEnvironmentStringsW(环境、缓冲区、最大路径)\
替换(0,(sizeof(前缀)/sizeof(wchar__t))-1,缓冲区)\
如果(存在(路径))返回路径\
}
std::wstring解析(std::wstring路径)
{
使用名称空间boost::算法;
wchar_t缓冲区[最大路径];
修剪(路径);
如果(path.empty()| | Exists(path))返回路径;
//首先尝试查看是否有引用的路径
如果(路径[0]==L'){
返回std::wstring(path.begin()+1,std::find(path.begin()+1,path.end(),L');
}
//检查路径开头没有根的严重情况
路径前缀解析(路径,L“\\”,L“);
路径前缀解析(路径,L“?\”,L“);
路径前缀解析(路径,L“\?\”,L“);
路径前缀解析(路径,L“globalroot\\”,L“”);
路径\前缀\解析(路径,L“system32\\”,L“%systemroot%\\system32\\”;
路径前缀解析(路径,L“systemroot\”,L“%systemroot%\\”;
静态std::向量路径exts;
if(pathExts.empty()){
#定义MAX_ENVVAR 32767
wchar_t pathext[MAX_ENVVAR];
DWORD长度=GetEnvironmentVariable(L“PATHEXT”,PATHEXT,MAX_ENVVAR);
如果(!length)WindowsApiException::ThrowFromLastError();
拆分(pathExts,pathext,std::bind2nd(std::equal_to(),L';');
insert(pathExts.begin(),std::wstring());
}
std::wstring::迭代器currentSpace=path.begin();
做{
currentSpace=std::find(currentSpace,path.end(),L“”);
std::wstring currentPath(path.begin(),currentSpace);
std::wstring::size_type currentPathLength=currentPath.size();
typedef std::vector::const_迭代器ExtIteratorType;
对于(ExtIteratorType it=pathExts.begin();it!=pathExts.end();it++){
替换(currentPathLength,currentPath.size()-currentPathLength,*it);
如果(存在(currentPath))返回currentPath;
}
if(currentSpace!=path.end())
currentSpace++;
}while(currentSpace!=path.end());
返回路径;
}
}

第4项应该相对容易。如果路径以“字符开始,只需一直读到下一个”开头,这就是路径。对于其他命令行,它稍微有点棘手,但Windows的做法是简单地将命令行分成几个部分,然后一次尝试一个,因此看看#3,它将命令行分成如下数组:

["C:\Program", "Files", "(x86)\Common", "Files\Steam\SteamService.exe", "/RunAsService"]
然后从最左边的元素开始查找文件:

  • C:\程序
  • C:\程序文件
  • C:\ProgramFiles(x86)\Common
  • C:\Program Files(x86)\Common Files\Stream\StreamService.exe
  • C:\Program Files(x86)\Common Files\Steam\SteamService.exe/RunaService
  • 每一步,它都会检查具有该名称的文件是否存在。如果是的话,那就是它选择的。它还尝试将“.exe”附加到名称。所以在第一步中,它检查是否有一个名为“C:\Program.exe”的文件,如果是,这是第一步。如果没有,它将移动到第二步并尝试“C:\Program Files.exe”。如果不存在,它将移动到下一个,依此类推

    在过去,该算法的工作方式存在一些问题,例如。

    请参见shlwapi.h中的。
    你的例子应该是
    ::PathRemoveArgs(sPath)
    ,然后是
    ::PathMatchSpec(sPath,_T(“*.exe”)

    这些不是路径,这些是恰好以路径开头的命令行。@bmargulies:我想这是真的——我想我需要上述命令行的路径部分。#3是个大问题。您如何确定您已经完成了路径(并且不要忘记有一半的时间路径是用正斜杠指定的)和斜杠分隔的参数?至少加上引号,这是可行的…@MPelletier:这就是问题的原因。CeaPATH进程似乎可以接受这些路径,尽管我认为它们是畸形的。我感觉到了你的痛苦,但是我不知道内核之外的API,它实现了创建过程的规则。这不可能完全正确——我相信CreateProcess正在解析PATEXT环境变量。如果我创建一个运行密钥(
    HKEY\U LOCAL\U MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\run\\Runme=“C:\Program”
    ),并将一个可执行文件放在C:\Program.com中,它将在启动时执行。是的,我相信你是正确的。它将尝试C:\Program.exe、C:\Program.com、C:\Program.bat等等-将尝试从PATHEXT进行所有扩展。看起来我必须自己编写grr。。。希望我不要搞砸了!:首先,他还应该调用::PathUnquoteSpaces():-)您还假设该文件是EXE文件,但事实并非如此。另外,有些