Recently, I'm developing a tool with WinUI, but now I view a problem when using FileOpenPicker
throw exception In Administrator model, you guys can reproduce this problem with following code.
private async void myButton_Click(object sender, RoutedEventArgs e)
{
myButton.Content = "Clicked";
var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
// See the sample code below for how to make the window accessible from the App class.
var window = App.Current.m_window;
// Retrieve the window handle (HWND) of the current WinUI 3 window.
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(window);
// Initialize the file picker with the window handle (HWND).
WinRT.Interop.InitializeWithWindow.Initialize(openPicker, hWnd);
// Set options for your file picker
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.FileTypeFilter.Add("*");
// Open the picker for the user to pick a file
var file = await openPicker.PickSingleFileAsync();
if (file != null)
{
await Windows.Storage.FileIO.ReadTextAsync(file);
}
else
{
throw new Exception("file is null");
}
}
For making sure the app run in Administrator, please edit project profile like this answer .
This doesn't work because FilePicker was designed in the UWP era for apps that only had an access to the local files through a sandbox in a enduser-controlled manner, so it's some sort of a by-design-limited thing. I don't see it as adding any value to developers when you're not running in the UWP sandbox, as administrator or not.
What you can do though is reference a class library dll and use Windows forms (or WPF) OpenFileDialog from there.
In fact, to enable Windows Forms usage from WinUI you can just create a class library project with nothing in it, like this for example (UseWindowsForms
is the important thing here, adapt TargetFramework
to your needs):
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
</Project>
Now you can do this from your WinUI project running as admin:
using System.Windows.Forms; // needs a reference on ClassLibrary1
using Microsoft.UI;
using Microsoft.UI.Xaml;
namespace WithAdminApp
{
public sealed partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void myButton_Click(object sender, RoutedEventArgs e)
{
var ofd = new OpenFileDialog();
if (ofd.ShowDialog(new Win32Window(Win32Interop.GetWindowFromWindowId(AppWindow.Id))) == DialogResult.OK)
{
MessageBox.Show(ofd.FileName);
}
}
}
public class Win32Window(nint handle) : IWin32Window
{
public nint Handle => handle;
}
}
PS: you can also write a wrapper (or reuse some existing one) over the IFileDialog interface wich is the root interface of Windows file dialogs implementation, but IMHO this is completely overkill in most cases https://stackoverflow.com/a/66187224/403671).