Another API exception which should not have been thrown

From the documentation on StorageFolder.TryGetItemAsync(String) Method:

Tries to get the file or folder with the specified name from the current folder. Returns null instead of raising a FileNotFoundException if the specified file or folder is not found.

using IStorageItem = winrt::Windows::Storage::IStorageItem;
IStorageItem EventStorageItem { m_Configuration.m_ApplicationStorageFolder.TryGetItemAsync(m_FileName).get() };

Exception thrown at 0x00007FFB06BDA799 (KernelBase.dll) in DownloadIssue.exe: WinRT originate error – 0x80070002 : ‘An item cannot be found with the specified name (Issue-1714684927.tsv).’.

It looks like TryGetItemAsync is a wrapper over GetItemAsync to suppress exception if file is not found, and it should be the other way around: if there is no file, there is nullptr result with no exception. In conjunction with missing mode equivalent to OPEN_ALWAYS it makes it not really convenient to write code free from exceptions.

Exceptionless workaround via file query:

#if 1
	using namespace winrt::Windows::Storage;
	StorageFile EventStorageFile(nullptr);
	Search::StorageFileQueryResult const FileQueryResult { m_Configuration.m_ApplicationStorageFolder.CreateFileQuery() };
	auto const FileVector { FileQueryResult.GetFilesAsync().get() };
	for(auto FileVectorIterator { FileVector.First() }; FileVectorIterator.HasCurrent(); FileVectorIterator.MoveNext())
	{
		auto const StorageFile { FileVectorIterator.Current() };
		if(StorageFile.IsOfType(StorageItemTypes::File) && _wcsicmp(StorageFile.Name().c_str(), m_FileName.c_str()) == 0)
		{
			EventStorageFile = StorageFile;
			break;
		}
	}
	if(!EventStorageFile)
		return;
#else
	// TODO: Get rid of exception if file is missing
	IStorageItem EventStorageItem { m_Configuration.m_ApplicationStorageFolder.TryGetItemAsync(m_FileName).get() };
	if(!EventStorageItem)
		return;
	StorageFile EventStorageFile { EventStorageItem.as<StorageFile>() };
#endif

Leave a Reply