微软MSIX格式应用程序有严格限制。自身所在目录只读。如果要读写一些数据有自己的特殊目录可以操作。之前我不知道怎么操作。现在我知道怎么操作这2个目录记录下来
程序所在目录(只读)
msix程序安装目录是在这种路径下,只读的:C:\Program Files\WindowsApps\xxxxxxxxxxxxx\VFS\ProgramFilesX86\xxxxxxxx,xxxxxxxxxx是一些包名发布者名字特定计算得到的东西
这个目录通过GetCurrentDirectory这种的API得到的是system32这个文件夹。没有用,需要使用GetModuleFileName这个函数
//获取程序目录路径 带反斜杠结尾
std::string get_app_dir_path_utf8(){
wchar_t appPath[MAX_PATH];
//获取app执行文件路径
if (GetModuleFileNameW(NULL, appPath, MAX_PATH)) {
// 提取目录部分
wchar_t* lastSlash = wcsrchr(appPath, L'\\');
if (lastSlash) {
*(lastSlash+1) = L'\0';//保留反斜杠截取
}
}
std::wstring wAppPath = appPath;
return UnicodeToUtf8(wAppPath);
}UnicodeToUtf8是我自己的函数,把宽字节转换成utf8的,不用也可以直接返回std::wstring。
这种办法获取程序所在目录可以加载当前目录下的一些资源比如图片资源。而其它办法使用./resource/获取程序当前目录内容是无效的。
程序数据文件夹(读写)
msix应用的程序数据文件夹可读写,路径很复杂是这种:C:\Users\jack\AppData\Local\Packages\xxxxxxxxxxxxxxxxxxxxxxxxxxx\LocalState,也是根据包名计算得到的。
这个办法可以获取msix应用对应的自己的程序数据文件夹,并且在判断程序不是msix格式的时候自动设置一个普通文件夹路径。
// 声明函数指针类型
typedef LONG (WINAPI* GetPackageFamilyNameFunc)(HANDLE, UINT32*, PWSTR);
std::wstring GetAppDataPath() {
std::wstring fullPath;
// 尝试动态加载 kernel32.dll 中的函数
HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll");
if (hKernel32) {
GetPackageFamilyNameFunc pGetPackageFamilyName = (GetPackageFamilyNameFunc)GetProcAddress(hKernel32, "GetPackageFamilyName");
if (pGetPackageFamilyName) {
wchar_t pfn[256] = {0};
UINT32 length = 256;
if (pGetPackageFamilyName(GetCurrentProcess(), &length, pfn) == ERROR_SUCCESS) {
// 是MSIX应用
wchar_t path[MAX_PATH];
if (SHGetFolderPathW(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, path) != S_OK) {
return L"";
}
fullPath = path;
fullPath += L"\\Packages\\";
fullPath += pfn;
fullPath += L"\\LocalState\\";
CreateDirectoryW(fullPath.c_str(), nullptr);
return fullPath;
}
}
}
// 回退到传统路径
fullPath = L"./data/";
CreateDirectoryW(fullPath.c_str(), nullptr);
return fullPath;
}
这个路径程序可以读写一些文件,比如用户配置文件
总结
除了特殊的应用自身目录和它的数据文件夹,我测试msix程序可以获取硬盘上正常的其它目录文件进行操作。