UWP调用Package::Current().InstalledLocation()崩溃,求返回StorageFolder的替代方案
解决方案
首先崩溃的核心原因是:Package::Current()仅能在拥有包标识的进程中调用,如果你运行的是未打包的UWP/WinUI3程序,或者直接运行了编译出来的exe而非通过打包后的应用入口启动,调用该接口就会直接抛出异常,和权限无关。
以下是符合返回值要求的两种实现方案:
方案1:适配带包标识的正常场景
如果你的程序是标准打包UWP应用、或者打包模式的WinUI3应用,不需要替换原有接口,仅需要增加前置判断避免崩溃:
#include <winrt/Windows.ApplicationModel.h> #include <winrt/Windows.Storage.h> using namespace winrt::Windows::ApplicationModel; using namespace winrt::Windows::Storage; StorageFolder GetInstalledLocation() { if (Package::Current() != nullptr) { return Package::Current().InstalledLocation(); } throw winrt::hresult_error(E_FAIL, L"当前进程无包标识"); }
使用该方案只需要在Visual Studio中选择打包后的项目作为启动项运行即可正常返回结果。
方案2:适配无包标识的未打包场景
如果你的程序是未打包的桌面程序,无法获取包标识,可以先读取当前exe所在目录,再将路径转换为StorageFolder对象,和原有接口语义完全一致:
#include <winrt/Windows.Storage.h> #include <Windows.h> using namespace winrt::Windows::Storage; StorageFolder GetInstalledLocation() { wchar_t exePath[MAX_PATH] = { 0 }; GetModuleFileNameW(nullptr, exePath, MAX_PATH); std::wstring dirPath = exePath; // 截取得到exe所在目录路径 size_t lastSplitPos = dirPath.find_last_of(L"\\/"); dirPath = dirPath.substr(0, lastSplitPos); // 本地路径读取无异步开销,直接同步获取 return StorageFolder::GetFolderFromPathAsync(dirPath).get(); }
注意事项
- 如果是在UI线程调用该方法,建议将方法改为异步返回
IAsyncOperation<StorageFolder>,避免get()调用阻塞UI。 - 两种方案返回的
StorageFolder对象都支持原有后续所有的文件读写操作,不需要修改后续业务逻辑。
内容的提问来源于stack exchange,提问作者user14880070
相关产品推荐
相关产品推荐

