【问题标题】:Get App path for fopen() in UWP在 UWP 中获取 fopen() 的应用路径
【发布时间】:2017-01-01 05:17:12
【问题描述】:

我正在将现有的 C/C++ 应用程序移植到使用 fopen()/fclose() 的 UWP。在Win32上,我曾经使用以下两个函数来获取app资源的路径(只读),以及获取app存储的路径(读/写):

char resourcePath[2048];
const char *GetResourcePath(void)
{
    GetCurrentDirectoryA(sizeof(resourcePath), resourcePath);
    strcat(resourcePath, "/");
    return resourcePath;
}

char storagePath[2048];
const char *GetStoragePath(void)
{
    GetCurrentDirectoryA(sizeof(storagePath), storagePath);
    strcat(storagePath, "/");
    return storagePath;
}

什么是 UWP 等效项?我似乎只能在 C# 中找到信息。 看来我可以从这个文件夹中“rb”fopen()文件,但我不能“wb”。为什么不?它是应用程序的文件夹,不是吗?

【问题讨论】:

标签: c++ uwp


【解决方案1】:

GetCurrentDirectory 适用于 UWP,但您必须使用 Unicode 变体(GetCurrentDirectoryW 而不是 GetCurrentDirectoryA)。但是,我不会使用它来获取应用程序的安装位置,因为它可以通过使用 SetCurrentDirectory 轻松覆盖。

您可以使用Package.InstalledLocation 属性,然后在返回的StorageFolder 上使用Path 属性,但如果使用该属性,您将无法与您的Win32 应用程序共享代码。

我建议改为使用 GetModuleFileNameW 检索可执行文件的路径,然后修剪最后一个路径组件以获取目录:

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

extern "C" IMAGE_DOS_HEADER __ImageBase;

std::wstring GetExecutablePath()
{
    std::wstring buffer;
    size_t nextBufferLength = MAX_PATH;

    for (;;)
    {
        buffer.resize(nextBufferLength);
        nextBufferLength *= 2;

        SetLastError(ERROR_SUCCESS);

        auto pathLength = GetModuleFileName(reinterpret_cast<HMODULE>(&__ImageBase), &buffer[0], static_cast<DWORD>(buffer.length()));

        if (pathLength == 0)
            throw std::exception("GetModuleFileName failed"); // You can call GetLastError() to get more info here

        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
        {
            buffer.resize(pathLength);
            return buffer;
        }
    }
}

void RemoveLastPathComponent(std::wstring& path)
{
    auto directoryLength = path.length() - 1;

    while (directoryLength > 0 && path[directoryLength] != '\\' && path[directoryLength] != '/')
        directoryLength--;

    if (directoryLength > 0)
        path.resize(directoryLength);
}

std::wstring GetExecutableDirectory()
{
    auto executablePath = GetExecutablePath();
    RemoveLastPathComponent(executablePath);
    return executablePath;
}

另外值得注意的是:不要使用 fopen。如果用户在其用户名中包含在当前代码页中无法表示的非英语字符,则您的代码将失败。请改用 _wfopen 或 CreateFile2。

【讨论】:

  • 谢谢!这是/大多数/我的答案,但不是关于本地 WRITE 存储位置,即:Windows::Storage::StorageFolder^ localFolder = Windows::Storage::ApplicationData::Current->LocalFolder;
  • 啊,是的,我错过了读/写路径。 LocalFolder 确实是一个合适的地方,并且没有其他方法(与 win32 路径兼容)可用。
  • 我会坚持使用Package.InstallLocation 而不是上面的技巧,因为无论如何你都需要获取数据目录(这是 UWP 特有的)。
  • @PeterTorr-MSFT 显然 Package.InstallLocation 被可选包破坏。如果您在 DLL 中分发您的代码,则可以将它与其他依赖文件一起放在一个可选包中。在这种情况下,Package.InstallLocation 将失败,而使用 GetModuleFileNameW 仍然有效。
  • 如果您尝试加载本地化到不同包中的资源,它也会中断。您要读取什么样的文件?
猜你喜欢
  • 1970-01-01
  • 2018-10-20
  • 1970-01-01
  • 1970-01-01
  • 2023-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多