Reputation: 147
I'm working with C++/WinRT for UWP. I am trying to create a file, but an exception is thrown at line 11 :
#include "pch.h"
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Storage;
IAsyncAction createFile()
{
try
{
StorageFolder local{ ApplicationData::Current().LocalFolder() }; // line 11
StorageFolder folder = co_await local.CreateFolderAsync(L"myapp", CreationCollisionOption::OpenIfExists);
StorageFile file = co_await folder.CreateFileAsync(L"file", CreationCollisionOption::ReplaceExisting);
co_await FileIO::WriteTextAsync(file, L"wide chars here.");
}
catch (const winrt::hresult_error& ex)
{
}
}
int main()
{
init_apartment();
createFile();
}
The debugger doesn't shows me the error, because it crashes. The output says
onecoreuap\base\appmodel\statemanager\winrt\lib\windows.storage.applicationdatafactory.server.cpp(126)\Windows.Storage.ApplicationData.dll!00007FFE8A7A1202: (caller: 00007FFE8A799081) ReturnHr(1) tid(3ad8) 80073D54 The process has no package identity.
onecoreuap\base\appmodel\statemanager\winrt\lib\windows.storage.applicationdatafactory.server.cpp(74)\Windows.Storage.ApplicationData.dll!00007FFE8A7990A9: (caller: 00007FF733954323) ReturnHr(2) tid(3ad8) 80073D54 The process has no package identity.
Debug Error!
Program: D:\Developpement\CPP\test\x64\Debug\Tests.exe
abort() has been called
I found nothing about it on google, so what could this error mean, and how can I solve it ? Thanks
Upvotes: 2
Views: 2054
Reputation: 451
The issue here is with ApplicationData::Current(). https://learn.microsoft.com/en-us/uwp/api/windows.storage.applicationdata.current?view=winrt-18362
The API to get current application information is based on the identity of the application. Any Windows App can have identity (it doesn't have to be a UWP), but it must be installed using the packaged installer to get it (a.k.a. MSIX installer). You can learn more about packaged "full trust" applications here: https://learn.microsoft.com/en-us/windows/msix/desktop/desktop-to-uwp-prepare
You can use the desktop app packaging project here to make it a bit easier to wrap your app up: https://learn.microsoft.com/en-us/windows/msix/desktop/desktop-to-uwp-packaging-dot-net
All that said, if you just want to open a file in app local data, without getting into the issue of packaging, you can create folders based on the location of %appdata%. Without a packaged installer, it's your responsibility to handle cleanup.
So it's more work in the short term to set up your application as a packaged app, but if this is something that you want to distribute, taking care of this up front will likely save you a lot of work in the long run.
If you want to manually set up an app folder, you can do something along these lines to get started:
int main()
{
init_apartment();
wstring appfolderstring;
appfolderstring.resize(ExpandEnvironmentStrings(L"%AppData%", nullptr, 0));
ExpandEnvironmentStringsW(L"%AppData%", &appfolderstring.front(), appfolderstring.size());
wprintf(L"path: %ls!\n", appfolderstring.c_str());
// Note: off-by-one issue... ExpandEnvironmentStringsW wants to write the final null character.
// Leave buffer space to write it above, then trim it off here.
appfolderstring.resize(appfolderstring.size()-1);
StorageFolder folder{ StorageFolder::GetFolderFromPathAsync(appfolderstring).get() };
printf("folder: %ls!\n", folder.DisplayName().c_str());
}
Upvotes: 3