Skip to content

Public Spec for Microsoft.Windows.Storage.Pickers #5155

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 26, 2025

Conversation

DinahK-2SO
Copy link
Contributor

@DinahK-2SO DinahK-2SO commented Feb 14, 2025

The public Spec for Microsoft.Windows.Storage.Pickers

Preview: Microsoft.Windows.Storage.Pickers.md

The code is also open for review. Find PR: #5240

@benstevens48
Copy link

Is the general principle in WindowsAppSDK to continue using the StorageFile and StorageFolder types? I mean if writing in C#, using the .Net IO functions is more convenient, in which case it's preferable just to have file paths and not have the overhead of the StorageFile/Folder instances. However, I have to admit, I'm not full up to date with all the possible security models that can be used with WindowsAppSDK, so maybe there's a reason for using StorageFile and StorageFolder instead of just returning the file path?

@mominshaikhdevs
Copy link

mominshaikhdevs commented Feb 16, 2025

#8 (comment)

a new picker API that must have these two bare minimum features:

  1. works both in AppContainer/win32-app-isolation and outside of AppContainer.

  2. as fast as raw win32 apis.

EDIT:

longstanding issues that will be finally resolved : #88, #2504, #3536, microsoft/microsoft-ui-xaml#9557

@DinahK-2SO DinahK-2SO changed the title Public Spec for Microsoft.Windows.Storage.Pickers Public Spec for Microsoft.Windows.Storage.Pickers [Milestone 1] Feb 17, 2025
@DinahK-2SO
Copy link
Contributor Author

Is the general principle in WindowsAppSDK to continue using the StorageFile and StorageFolder types? I mean if writing in C#, using the .Net IO functions is more convenient, in which case it's preferable just to have file paths and not have the overhead of the StorageFile/Folder instances. However, I have to admit, I'm not full up to date with all the possible security models that can be used with WindowsAppSDK, so maybe there's a reason for using StorageFile and StorageFolder instead of just returning the file path?

Hello @benstevens48 , The new API returns StorageFile and StorageFolder primarily to maintain consistency with the APIs in Windows.Storage.Pickers that it is intended to replace. This approach allows users currently utilizing Windows.Storage.Pickers to migrate to Microsoft.Windows.Storage.Pickers with minimal changes.

At the current stage, once we have the StorageFile, we can use StorageFile.Path for subsequent operations (as demonstrated in the examples). In future, we may consider adding more methods and return types.

@benstevens48
Copy link

Is the general principle in WindowsAppSDK to continue using the StorageFile and StorageFolder types? I mean if writing in C#, using the .Net IO functions is more convenient, in which case it's preferable just to have file paths and not have the overhead of the StorageFile/Folder instances. However, I have to admit, I'm not full up to date with all the possible security models that can be used with WindowsAppSDK, so maybe there's a reason for using StorageFile and StorageFolder instead of just returning the file path?

Hello @benstevens48 , The new API returns StorageFile and StorageFolder primarily to maintain consistency with the APIs in Windows.Storage.Pickers that it is intended to replace. This approach allows users currently utilizing Windows.Storage.Pickers to migrate to Microsoft.Windows.Storage.Pickers with minimal changes.

At the current stage, once we have the StorageFile, we can use StorageFile.Path for subsequent operations (as demonstrated in the examples). In future, we may consider adding more methods and return types.

@DinahK-2SO Thanks for the reply. That makes sense. I'm just concerned about the ongoing usage of StorageFile in WIndowsAppSDK since it always had very poor performance in UWP (I mean just creating 1 StorageFile could consume 100kB of RAM and loading many StorageFiles was hundreds of times slower than using Win32/.Net APIs). Although I haven't tested in in WIndowsAppSDK , so maybe it behaves differently. Probably in a file picker it doesn't matter too much, although in some cases the user may pick 1000s of files (like all photos in a large folder of photos etc), so it could start to become an issue.

@DrusTheAxe
Copy link
Member

Is the general principle in WindowsAppSDK to continue using the StorageFile and StorageFolder types? I mean if writing in C#, using the .Net IO functions is more convenient, in which case it's preferable just to have file paths and not have the overhead of the StorageFile/Folder instances. However, I have to admit, I'm not full up to date with all the possible security models that can be used with WindowsAppSDK, so maybe there's a reason for using StorageFile and StorageFolder instead of just returning the file path?

Hello @benstevens48 , The new API returns StorageFile and StorageFolder primarily to maintain consistency with the APIs in Windows.Storage.Pickers that it is intended to replace. This approach allows users currently utilizing Windows.Storage.Pickers to migrate to Microsoft.Windows.Storage.Pickers with minimal changes.

Can you provide a variant which returns the file as a string e.g. string PickSingleFileNameAsync(...)?

Properly implementing that would require more than skin deep differences but ahort term that could be implemented as

var storageFile = picker.PickSingleFileAsync();
return storageFile != null ? storageFile.Path : null;

with the deeper implementation optimized to return the string w/o any StorageFile in the callstack. Even if only syntactic candy it lays the foundation for the improved dev experience while deferring the deeper optimized work for later when time permits.

@DrusTheAxe
Copy link
Member

@DinahK-2SO Performance can be a concern if you have the path/file as a string. The cost to create a StorageFile/Folder object can be non-trivial if your sole purpose is to rip the string out of the returned object and free the object.

Is the sole purpose of this spec is to provide WinAppSDK alternatives supporting elevation to Windows.* APIs that don't?

Seems it's maybe that and less given what's spec'd is a subset of Windows.* pickers (no PickMultipleFilesAsync, CreateForUser, etc). It's hard assess the spec without an understanding of the desired endgame. Is that longer-term clear to you but intentionally deferred for now, 'cause, reasons?

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 5 out of 6 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • specs/StoragePickers/FileSavePicker.md: Evaluated as low risk
Comments suppressed due to low confidence (1)

specs/StoragePickers/FileOpenPicker.md:65

  • The method name PickSingleFilesAsync is incorrect. It should be renamed to PickSingleFileAsync.
## FileOpenPicker.PickSingleFilesAsync

@DinahK-2SO DinahK-2SO force-pushed the user/DinahK-2SO/storage_pickers_public_spec branch from da1e3f7 to 6e3e097 Compare March 12, 2025 15:37
@DinahK-2SO DinahK-2SO marked this pull request as ready for review March 12, 2025 15:42
@DinahK-2SO DinahK-2SO force-pushed the user/DinahK-2SO/storage_pickers_public_spec branch from 6e3e097 to cb97ad7 Compare March 12, 2025 15:45
@ghost1372
Copy link
Contributor

ghost1372 commented Mar 14, 2025

Excuse me for sending messages among the elders.

But can you clarify and consider the following questions/requests?

1.Why you are using WindowId instead of hwnd? later you get hwnd like this:

parameters.HWnd = winrt::Microsoft::UI::GetWindowFromWindowId(m_windowId);

So why don't you get hwnd directly?

2.Why are there different properties for extensions?

FileOpenPicker-> FileTypeFilter
FileSavePicker-> FileTypeChoices

Why not use FileTypeChoices for both?

3.When we use Windows.Storage.Picker, we must set FileTypeFilter or FileTypeChoices, otherwise picker will not run. and get exception:

System.Runtime.InteropServices.COMException: 'Unspecified error

I hope the new picker doesn't have this problem.

4.We can set details for extension in FileSavePicker like this:

picker.FileTypeChoices.Add("Images", new string[] {".jpg", ".png" });

but we can not add details and multiple extensions for FileOpenPicker:

picker.FileTypeFilter.Add(".png");

@DinahK-2SO
Copy link
Contributor Author

DinahK-2SO commented Mar 20, 2025

Hi @ghost1372 , thanks for raising these questions and sharing your insights! This is a long answer list following a long question list, so I'll address each part separately.

1.Why you are using WindowId instead of hwnd? later you get hwnd like this:

parameters.HWnd = winrt::Microsoft::UI::GetWindowFromWindowId(m_windowId);

So why don't you get hwnd directly?

The reason for using WindowId instead of hwnd is to simplify the code and improve the developer experience. Using the existing Windows.Storage.Pickers with window handle requires additional steps, as the example shown below:

using Windows.Storage.Pickers;

var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
var picker = new FileOpenPicker();
WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd);
var file = await picker.PickerSingleFileAsync();
string path = file.Path;

In the new Microsoft.Windows.Storage.Pickers, this process will be streamlined by using WindowId:

using Microsoft.Windows.Storage.Pickers;

var picker = new FileOpenPicker(this.AppWindow.Id);
var result = await picker.PickerSingleFileAsync();
string path = result.Path;

We can see the new approach reduces more boilerplate code and makes the API easier to use.

By the way, you might be referring an old commit. If you're looking for the progress on coding, kindly follow our dev branch: user/xianghong/storage-pickers-develop


2.Why are there different properties for extensions?

FileOpenPicker-> FileTypeFilter FileSavePicker-> FileTypeChoices

Why not use FileTypeChoices for both?

Also for the question 4: It's an inspiring request to add FileTypeChoices for the FileOpenPicker. While it might not be implemented in this release, if it can be helpful, do please suggest it in our feedback wanted section.


3.When we use Windows.Storage.Picker, we must set FileTypeFilter or FileTypeChoices, otherwise picker will not run. and get exception:

System.Runtime.InteropServices.COMException: 'Unspecified error

I hope the new picker doesn't have this problem.

Thanks for bringing up this topic!

First, the answer for FileOpenPicker.FileTypeFilter: Yes, we are making it optional. In the new namespace Microsoft.Windows.Storage.Pickers, with FileTypeFilter not specified, the FileOpenPicker would defalt to * - meaning all files. This is also demonstrated in our example code .

For the FileTypeChoices property of FileSavePicker, I can't make it optional for now because it can be essential in some cases:

When the file picked by the end user doesn't exist, FileSavePicker creates the file. And if the user hasn't specified the new file's extension at this point, FileSavePicker will default to using the first extension in the current choice. In this context, FileTypeChoices is essential.


4.We can set details for extension in FileSavePicker like this:

picker.FileTypeChoices.Add("Images", new string[] {".jpg", ".png" });

but we can not add details and multiple extensions for FileOpenPicker:

picker.FileTypeFilter.Add(".png");

Please refer to the previous answer 2.

@ghost1372
Copy link
Contributor

Thank you @DinahK-2SO
i created a request for it.
#5255

@DinahK-2SO DinahK-2SO changed the title Public Spec for Microsoft.Windows.Storage.Pickers [Milestone 1] Public Spec for Microsoft.Windows.Storage.Pickers Mar 21, 2025
@codendone
Copy link
Collaborator

Iteration 5 looks good to me.

@DinahK-2SO DinahK-2SO enabled auto-merge (squash) March 26, 2025 05:22
@yeelam-gordon yeelam-gordon requested a review from Copilot March 26, 2025 05:35
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces the public specification for the Microsoft.Windows.Storage.Pickers API and adds detailed markdown documents for the new classes and enums supporting file and folder picking in elevated desktop applications.

  • Added a comprehensive overview and definition of the API in Microsoft.Windows.Storage.Pickers.md
  • Introduced individual spec documents for FileOpenPicker, FileSavePicker, FolderPicker, and their associated result classes
  • Defined enum specifications for PickerViewMode and PickerLocationId with background context and examples

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
specs/StoragePickers/Microsoft.Windows.Storage.Pickers.md New API overview and definition of core classes and enums
specs/StoragePickers/PickerViewMode.md Specification and examples for PickerViewMode enum
specs/StoragePickers/FileOpenPicker.md Detailed class specification with code examples for FileOpenPicker
specs/StoragePickers/PickerLocationId.md Specification and usage context for PickerLocationId enum
specs/StoragePickers/FolderPicker.md Detailed class specification with code examples for FolderPicker
specs/StoragePickers/PickFolderResult.md Specification for PickFolderResult class and conversion examples
specs/StoragePickers/FileSavePicker.md Detailed class specification with code examples for FileSavePicker
specs/StoragePickers/PickFileResult.md Specification for PickFileResult class including usage examples
Comments suppressed due to low confidence (1)

specs/StoragePickers/PickFileResult.md:21

  • Typo detected in the header: "compatability" should be corrected to "compatibility".
## Backward compatability

@DinahK-2SO
Copy link
Contributor Author

/azp run

Copy link

Azure Pipelines could not run because the pipeline triggers exclude this branch/path.

@DinahK-2SO
Copy link
Contributor Author

/azp run

Copy link

Azure Pipelines could not run because the pipeline triggers exclude this branch/path.

Copy link

@yeelam-gordon yeelam-gordon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clarify do we need to indicate it is for "experimental only" or not need.
Also, for Microsoft doc, do we need to do it ourselves or not? I assume the doc reviewer is need.

@DinahK-2SO DinahK-2SO merged commit e9048aa into main Mar 26, 2025
2 checks passed
@DinahK-2SO DinahK-2SO deleted the user/DinahK-2SO/storage_pickers_public_spec branch March 26, 2025 06:03
@mominshaikhdevs
Copy link

mominshaikhdevs commented Mar 26, 2025

@DinahK-2SO clarify in the docs if it works within AppContainers + win32-app-isolation or not?

@HEIC-to-JPEG-Dev
Copy link

HEIC-to-JPEG-Dev commented Apr 28, 2025

After going through this and the testing with experimental. It appears that this is only for WinUI 3 in elevated Admin privelages. It not only fails in LowIL it also returns a path, which is also not allowed in LowIL. In trying to move from UWP I need to have LowIL because Windows.Storage.Search performance is 20x slower in MediumIL - Is this something that might be fixed, or should I just stay on UWP ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.