2014-09-02 105 views
0

我使用下面的函数来尝试并获得文件夹的路径,然后转换该路径的std :: string:HRESULT串(获得的文件路径)C++

std::string getpath() { 
    TCHAR documents[MAX_PATH]; 
    HRESULT result = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documents); 
    std::stringstream pff; 
    pff << result; 
    return pff.str(); 
} 

当这个执行,当试图将“\ filename”附加到字符串时,我得到一个“无效的文件名错误”。

请帮忙!

编辑:这是我如何附加到路径:

std::string folder = getpath() + "\\Folder"; 

我假定双逃逸符号仍然适用。

回答

1

您未打印documents,但result

尝试这样:

std::string getpath() { 
    TCHAR documents[MAX_PATH]; 

    HRESULT result = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documents); 
    if (result == S_OK) // SUCCEEDED(result) can be problematic 
         // since S_FALSE is a possible return value 
    { 
     std::stringstream pff; 
     pff << documents; 
     return pff.str(); 
    } 
    // handle error somehow 
    return ""; 
} 

这是一个Unicode的版本:

std::wstring getpath() { 
    TCHAR documents[MAX_PATH]; 

    HRESULT result = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documents); 
    if (result == S_OK) // SUCCEEDED(result) can be problematic 
     // since S_FALSE is a possible return value 
    { 
     std::wstringstream pff; 
     pff << documents; 
     return pff.str(); 
    } 
    // handle error somehow 
    return L""; 
} 
+0

文档仍然是TCHAR – user3295336 2014-09-02 14:14:28

+0

+1,但某处需要将字符串缓冲区的长度传递给SHGetFolderPath:其中一个参数不应为NULL。 – Bathsheba 2014-09-02 14:17:37

+0

@Bathsheba它应该是MAX_PATH缓冲区,请参阅[SHGetFolderPath](http://msdn.microsoft.com/en-us/library/windows/desktop/bb762181%28v=vs.85%29.aspx)。 – AlexD 2014-09-02 14:19:32

-2

我最终抛弃的SHGetFolderPath并用更直接的_dupenv_s打算:

std::string getpath() { 
    char* buf = 0; 
    size_t sz = 0; 
    if (_dupenv_s(&buf, &sz, "USERPROFILE") == 0) { 
     std::string path(buf); 
     path += "\\Documents\\Folder"; 
     return path; 
    } 
    return NULL; 
} 
+0

对于其中文档文件夹位于其他位置的系统,此操作将失败。由于文档文件夹是可自定义的用户设置,因此您的代码失败不仅仅是理论上的可能性。泄漏内存,并使用MBCS字符编码只是增加了错误。请做[参观]并访问[帮助]了解,堆栈溢出是关于**质量**答案。这一个肯定不是。 – IInspectable 2016-09-22 13:21:36

+0

我想让我的答案留在问题的背景下。我没有具体说明解决方案是否应该安全。这是为了测试和概念的目的,以训练自己。尽管如此,我想我应该至少添加一个try-catch,并明确指出:这不适用于商业用途。 因此,“-1”可能会误导你。这是关于**学习**的。下次我将通过帮助中心运行我的答案。 – user3295336 2016-09-22 13:53:18

+0

*“这是关于学习。” - - 这是错误的。 SO是一个问答网站。这是关于**解决**问题,**质量**解决方案。我不知道,一个try-catch块怎么会有好处。如果有的话,它会进一步恶化这个代码。这是错误的,原因很多,最重要的是,它不会解决问题(请参阅[文件夹重定向概述](https://technet.microsoft.com/zh-cn/library/cc732275) .aspx)了解,为什么它可以并将失败)。有鉴于此,反对票是适当的。 – IInspectable 2016-09-22 14:06:43

1

您的代码失败,因为您确实正在构建一个脱离返回值的字符串。错误代码)SHGetFolderPath。您应该使用返回的路径。

由于SHGetFolderPath已弃用,因此应该使用SHGetKnownFolderPath来代替。除此之外,你不会意外地构造一个MBCS编码的路径名。并没有任意的MAX_PATH(260)字符限制。

下面的代码获取当前用户的文档路径:

#include <string> 
#include <ShlObj.h> 
#include <comdef.h> 

std::wstring GetDocumentPath() { 
    wchar_t* pOut = nullptr; 
    // Retrieve document path (CheckError throws a _com_error exception on failure) 
    _com_util::CheckError(::SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_DEFAULT, 
                nullptr, &pOut)); 
    // Attach returned buffer to a smart pointer with custom deleter. This 
    // is necessary, because the std::wstring c'tor throws on failure. 
    // Without this smart pointer, any exception would leak memory. 
    auto deleter = [](void* p) { ::CoTaskMemFree(p); }; 
    std::unique_ptr<wchar_t, decltype(deleter)> buffer{ pOut, deleter }; 
    return std::wstring{ buffer.get() }; 
    // Invisible: Run deleter for buffer, cleaning up allocated resources. 
} 

注:_com_util::CheckError没有正式文件,因此它可能成为编译器的未来版本中不可用。具有类似功能的自定义实现可能是这样的:

inline void CheckError(HRESULT hr) { 
    if (FAILED(hr)) { 
     _com_raise_error(hr); 
    } 
} 

_com_raise_error在案,以抛出一个异常_com_error。还记录了FAILED宏。


已知的文件夹路径是可定制的(参见Folder Redirection Overview)。你不能简单地尝试自己构建它们。你必须向壳牌索取这些信息。