1

I'm using the FileOpenPicker to select a file from OneDrive, that I will subsequently access through "standard" C++ interfaces (not C++/WinRT). I'm aware that the path returned by FileOpenPicker is not accessible by those interfaces, so I'm using StorageFile::CopyAsync to copy the file to an accessible location under the ApplicationData.

This works in a UWP x64 build on the desktop, but fails in a UWP arm64 build on the HoloLens 2.

On the HoloLens, the FileOpenPicker is providing only a small fraction of the file. For example, from a file that is 2.83 MB on OneDrive, the FileOpenPicker and CopyAsync are producing a file of only 144.6 KB. I've put in tests for the file size and completeness for both the source file provided by the FileOpenPicker and the destination file for CopyAsync -- e.g.:

uint64_t sourceSize = sourceFile.GetBasicPropertiesAsync().get().Size();
bool sourceIncomplete
    = uint32_t (sourceFile.Attributes())
    & uint32_t (FileAttributes::LocallyIncomplete);

The LocallyIncomplete bit is clear, even though the size is only 144.6 KB out of 2.83 MB.

CopyAsync then successfully copies the 144.6 KB that it was given, but stuff fails later because the source file from the FileOpenPicker is incomplete and invalid.

What am I missing for the HoloLens 2?


Here is a minimal reproducible example -- a slight modification of Scenario1_SingleFile.cpp from the Microsoft GitHub FilePicker sample at https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/FilePicker/cppwinrt

Compile for UWP-arm64, deploy to HoloLens 2, and test with multi-megabyte files on OneDrive.


// Modified version of Scenario1_SingleFile.cpp
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

#include "pch.h"
#include "Scenario1_SingleFile.h"
#include "Scenario1_SingleFile.g.cpp"

#include <winrt/Windows.Storage.FileProperties.h>
#include <sstream>

using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Storage;
using namespace Windows::Storage::Pickers;
using namespace Windows::UI::Xaml;

namespace winrt::SDKTemplate::implementation
{
    Scenario1_SingleFile::Scenario1_SingleFile()
    {
        InitializeComponent();
    }

    fire_and_forget Scenario1_SingleFile::PickAFileButton_Click(IInspectable const&, RoutedEventArgs const&)
    {
        auto lifetime = get_strong();

        // Clear previous returned file name, if it exists, between iterations of this scenario
        OutputTextBlock().Text(L"");

        FileOpenPicker openPicker;
        openPicker.ViewMode(PickerViewMode::Thumbnail);
        openPicker.SuggestedStartLocation(PickerLocationId::PicturesLibrary);
        openPicker.FileTypeFilter().ReplaceAll({ L".jpg", L".jpeg", L".png",
            // twhall@umich.edu added for "big" files:
            L".mp4", L".wmv", L".stl" });
        StorageFile file = co_await openPicker.PickSingleFileAsync();
        if (file != nullptr)
        {
            // Application now has read/write access to the picked file
#if 0
            OutputTextBlock().Text(L"Picked photo: " + file.Name());
#else
            // twhall@umich.edu:
            // *  Add feedback for file size and incompleteness.
            // *  Test on multi-megabyte files picked from OneDrive
            //    on the HoloLens (UWP-arm64)
            auto props = co_await file.GetBasicPropertiesAsync();
            uint64_t size = props.Size();
            uint32_t incomplete = (
                uint32_t (file.Attributes()) &
                uint32_t (FileAttributes::LocallyIncomplete));
            std::wstringstream text{};
            text << L"Picked file: "  << file.Name().c_str()
                 << L" (" << size << L" bytes, "
                 << (incomplete ? L"incomplete)" : L"complete)");
            OutputTextBlock().Text(text.str().c_str());
#endif
        }
        else
        {
            OutputTextBlock().Text(L"Operation cancelled.");
        }
    }
}
Theodore Hall
  • 91
  • 1
  • 6
  • P.S.: If I use the OneDrive app outside of my app to pre-place files in the "3D Objects" folder, and then navigate there with the FileOpenPicker, the code works. It feels like the FileOpenPicker, when navigating OneDrive, fails to fully download a file before returning a StorageFile, and there's no way to test or await the completion of the file. I've tried a couple of variations. These both fail in the same way with OneDrive files, but work with files that are already downloaded to "3D Objects": – Theodore Hall Dec 08 '20 at 00:26
  • ` /* Scenario 1 */ auto sourceFile = co_await filePicker.PickSingleFileAsync(); if (sourceFile) { apartment_context ui_thread; co_await resume_background(); cacheFile = CopyFileToCache (sourceFile); co_await ui_thread; } ` – Theodore Hall Dec 08 '20 at 00:27
  • ` /* Scenario 2 */ auto sourceFileOp = filePicker.PickSingleFileAsync(); if (sourceFileOp) { apartment_context ui_thread; co_await resume_background(); auto sourceFile = sourceFileOp.get(); cacheFile = CopyFileToCache (sourceFile); co_await ui_thread; } ` – Theodore Hall Dec 08 '20 at 00:30
  • Could you try deploying the [File picker sample](https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/FilePicker) to your device? It shows how to access files by letting the user choose them through the file pickers and will help to narrow down if it's an issue with your code. – Hernando - MSFT Dec 08 '20 at 07:12
  • Done. I modified Scenario1_SingleFile.cpp slightly to allow picking of ".stl" files (my app's target type) and to display the size of the file in the text box. It seems to work on the smallish sample photos, but fails on big megabyte-sized STL files: 9.44 MB > 1,080,245 bytes; 28.3 MB > 1,497,604 bytes. I'd be happy to post the modified code someplace. I doubt there's anything special about ".stl" files -- I suspect that any large file is a problem. – Theodore Hall Dec 09 '20 at 22:11
  • This is specifically for files from OneDrive. Files already loaded on the HoloLens in the "3D Objects" folder work fine. The OneDrive app does not seem to have a problem. But rather than load big files directly from OneDrive into my app, I need to use a two-step process: first use the OneDrive app to copy the file into "3D Objects", and then browse into that folder from my app. – Theodore Hall Dec 09 '20 at 22:14
  • OK, it seems that you already have a temporary workaround, could you provide an MVCE(stackoverflow.com/help/minimal-reproducible-example), so that we can reproduce and field this issue? – Hernando - MSFT Dec 10 '20 at 08:52
  • 1
    I edited my original post a few days ago to include an MCVE; not sure whether Stack Overflow sends any notifications for that. – Theodore Hall Dec 16 '20 at 20:37
  • Yesterday I updated my HoloLens 2 OS version to 21H1 and verified that this is still broken. – Theodore Hall Jun 11 '21 at 23:24

0 Answers0