WindowsAppSDK: FileOpenPicker PickMultipleFilesAsync Break in WinUI3 Desktop
Describe the bug
The FileOpenPicker in WinUI3 Preview4 Desktop sample solution breaks and closes the application when trying to open multiple items. Exception details below in the last section.
Steps to reproduce the bug
- Clone the WinUI3 Preview4 Problems FilePicker repository.
- Go to the FilePickerWinUIPreview4 folder.
- Open the FilePickerWinUIPreview4 solution in Visual Studio 2019 Preview.
- Build and run with Debug x64.
- Click the second / bottom button “FileOpenPicker: Multiple Files”. (The first button should work as expected.)
- Select one or more files.
- Click “Open”. Crash should occur.
Expected behavior
We expect the application to display the path of the selected file(s) or folder.
We expect the FileOpenPicker to allow the user to select multiple files as it does in UWP.
Screenshots
Screenshot#1a and 1b - Current Behavior (Single File working and Crash Error Message)
Screenshot#2 - Expected Behavior (File paths of selected files)
Version Info
NuGet package version:
[Microsoft.WinUI 3.0.0-preview4.210210.4]
Targeting: Target: Universal Windows Target version: Windows 10, version 1809 (10.0; Build 17763) Min version: Windows 10, version 1803 (10.0; Build 17134)
Windows app type:
UWP | Win32 |
---|---|
Yes |
Windows 10 version | Saw the problem? |
---|---|
Insider Build (xxxxx) | |
May 2020 Update (19041) | |
November 2019 Update (18363) | |
May 2019 Update (18362) | |
October 2018 Update (17763) | Yes |
April 2018 Update (17134) | |
Fall Creators Update (16299) | |
Creators Update (15063) |
Device form factor | Saw the problem? |
---|---|
Desktop | Yes |
Xbox | |
Surface Hub | |
IoT |
Additional context
Exception Details
System.Reflection.TargetInvocationException
HResult=0x80131604
Message=Exception has been thrown by the target of an invocation.
Source=System.Private.CoreLib
StackTrace:
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at WinRT.SingleInterfaceOptimizedObject…ctor(Type type, IObjectReference objRef)
at Windows.Storage.Pickers.FilePickerSelectedFilesArray.<.ctor>b__8_1()
at System.Lazy1.ViaFactory(LazyThreadSafetyMode mode) at System.Lazy
1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
at System.Lazy1.CreateValue() at System.Lazy
1.get_Value()
at Windows.Storage.Pickers.FilePickerSelectedFilesArray.AsInternal(InterfaceTag`1 _)
at Windows.Storage.Pickers.FilePickerSelectedFilesArray.GetEnumerator()
at FileOpenPickerWinUIPreview4.MainWindow.<fileOpenPickerMultipleButton_Click>d__2.MoveNext() in \FileOpenPickerWinUIPreview4\FileOpenPickerWinUIPreview4\MainWindow.xaml.cs:line 60
This exception was originally thrown at this call stack: [External Code]
Inner Exception 1: COMException: The application called an interface that was marshalled for a different thread. (0x8001010E (RPC_E_WRONG_THREAD))
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 52 (8 by maintainers)
I’d like to share the workaround of using Interop GetOpenFileName API call.
By researching several links and verifying some experiments:
https://docs.microsoft.com/en-us/windows/win32/dlgbox/open-and-save-as-dialog-boxes https://stackoverflow.com/questions/9088227/using-getopenfilename-instead-of-openfiledialog https://social.msdn.microsoft.com/forums/vstudio/en-US/2f4dd95e-5c7b-4f48-adfc-44956b350f38/getopenfilename-for-multiple-files
I can workaround this issue as below:
Notes: This works in Project Reunion 0.8 Preview. If you are using WinUI3 Preview or Project Reunion 0.5, may hit this bug:
https://github.com/microsoft/microsoft-ui-xaml/issues/4952
And need to upgrade the project to 0.8 by going through: https://docs.microsoft.com/en-us/windows/apps/project-reunion/update-existing-projects-to-the-latest-release
The helper class is as attached: Libwrap.txt
The calling sample code snippet: ` string[] files = LibWrap.ShowOpenFileDialog(“Select Files”,“c:\users\freistli\documents”, “All files\0 .\0”, true, true);
`
Hope this helps.
@harvinders you’ll have to statically store the current
Window
somewhere you can access it globally. If your app only has one single window, the easiest thing to do is, in your App.xaml.cs, refactor…to…
And then when you need to reference it, you can do…
Yeah, I used the
IInitializeWithWindow
interface. The issue was that I didn’t specify a file type filter. Looking through the docs, I discovered that not specifying it generates an exception. It’s all resolved now. Thanks for the swift response!@eleanorleffler thanks opening the bug and share the code. I could repro this.
I noticed that the doc of this API has the UWP label. I don’t know if this means that this API won’t work in Win32 apps.
I need help from the Project Reunion folks, this API is out of the WinUI domain. @jonwis, can you help us to know what is happening here?
We get:
Below you can find the code snipped:
Is m_hWndOwner correct at : (the window handle passed as 1st parameter of ShowDialog)
PickMultipleFilesAsync is unfortunately not supported right now. You can instead use the Win32 API GetOpenFileName, we’re working on posting a workaround sample for that.
@Aloento make sure when you’re calling
this.As<IWindowNative>()
, thethis
object is aWindow
object. If you’re still seeing problems, you can open a new issue, and please provide a full example of the code you’re calling, what specifically is failing, etc. Thanks!I got the same issue on PickMultipleFilesAsync, which crashes WinUI/Reunion WPF desktop app. But PickSingleFolderAsync works well. Do we have workaround or fix now? Thanks in advance.
See microsoft/ProjectReunion#466 for more information on why this doesn’t work and the workaround.