I am using a FileOpenPicker to get a file (StorageFile^) in a Windows Universal App. That seems to work fine, and if I output the StorageFile->Path->Data()
, it returns the expected file path (C:...\MyFile.txt).
When I try to open it and dump the contents to a string things go wrong (the string receives nothing), so as the first step, I was trying to verify the file path with std::filesystem::exists()
.
To snip it down to the relevant bit:
void MyClass::MyFunction(StorageFile^ InFile)
{
std::filesystem::path FilePath = InFile->Path->Data();
if (std::filesystem::exists(FilePath))
{
//Do things
}
}
When I run this, I get an exception:
Exception thrown at 0x7780A842 in MyApp.exe: Microsoft C++ exception: std::filesystem::filesystem_error at memory location 0x039BC480.
Unhandled exception at 0x7AACF2F6 (ucrtbased.dll) in MyApp.exe: An invalid parameter was passed to a function that considers invalid parameters fatal.
Seemingly, the path I attempt to pass into std::filesystem::exists() is invalid.
Any help pointing out where I am going wrong would be very appreciated!
This question had originally been marked as a duplicate of this question however that solution does not seem to work as it requires CLI(?) whilst I think I am using WinRT (however I can not find where in my project or settings to check that beyond having winrt available in includes).
The key things to remember about StorageFile
in the Windows Runtime (using C++/CX or C++/WinRT) is that (a) it's not necessarily a file on disk, and (b) even if it is a file on disk you don't necessary have permissions to open it directly.
The only 'generally safe' pattern you can use for doing traditional file I/O operations on the StorageFile
instance you are given by the UWP FilePicker is to create a temp directory copy from it and then parse the temp copy:
#include <ppltasks.h>
using namespace concurrency;
using Windows::Storage;
using Windows::Storage::Pickers;
auto openPicker = ref new FileOpenPicker();
openPicker->ViewMode = PickerViewMode::Thumbnail;
openPicker->SuggestedStartLocation = PickerLocationId::PicturesLibrary;
openPicker->FileTypeFilter->Append(".dds");
create_task(openPicker->PickSingleFileAsync()).then([](StorageFile^ file)
{
if (file)
{
auto tempFolder = Windows::Storage::ApplicationData::Current->TemporaryFolder;
create_task(file->CopyAsync(tempFolder, file->Name, NameCollisionOption::GenerateUniqueName)).then([](StorageFile^ tempFile)
{
if (tempFile)
{
std::filesystem::path FilePath = tempFile->Path->Data();
...
}
});
}
});
#include "winrt/Windows.Storage.h"
#include "winrt/Windows.Storage.Pickers.h"
using namespace winrt::Windows::Storage;
using namespace winrt::Windows::Storage::Pickers;
FileOpenPicker openPicker;
openPicker.ViewMode(PickerViewMode::Thumbnail);
openPicker.SuggestedStartLocation(PickerLocationId::PicturesLibrary);
openPicker.FileTypeFilter().Append(L".dds");
auto file = co_await openPicker.PickSingleFileAsync();
if (file)
{
auto tempFolder = ApplicationData::Current().TemporaryFolder();
auto tempFile = co_await file.CopyAsync(tempFolder, file.Name(), NameCollisionOption::GenerateUniqueName);
if (tempFile)
{
std::filesystem::path FilePath = tempFile.Path().c_str();
...
}
}
See Microsoft Docs