WindowsAppSDK: Trying to use a FileOpenPicker while running the app as Administrator will crash the app

Describe the bug

I am trying to open a File Picker but it works only if I am not using the app in elevation mode.

I’m getting the following error:

System.Runtime.InteropServices.COMException: 'Error HRESULT E_FAIL has been returned from a call to a COM component.'

The error appears when the code tries to execute the following line of code:

var file = await picker.PickSingleFileAsync();

Steps to reproduce the bug

  1. Create a WASDK app using version 1.4.2 and .NET 7
  2. Create an extension method so you can get the Window Handle

AppWindowExtension.cs

public static IntPtr GetHandle(this Microsoft.UI.Xaml.Window window)
{
    return WinRT.Interop.WindowNative.GetWindowHandle(window);
}
  1. Make the MainWindow available outside the App class

App.xaml.cs

public static Window MainWindow { get; private set; }
  1. Use the generated Button_Click event method to open the File Picker

MainWindow.xaml.cs

var picker = new FileOpenPicker();
picker.FileTypeFilter.Add("*");

InitializeWithWindow.Initialize(picker, App.MainWindow.GetHandle());

var file = await picker.PickSingleFileAsync();
  1. Build the app and try to Run as Administrator (it’s not neccesary to configure elevation, just right click on the app works)
  2. Click the button to open the File Picker
  3. The app will crash 😦

Expected behavior

I would expect this basic feature of picking a file to work even if I run the app as admin. My app has a lot of features that require elevation so getting rid of elevation is not an option for me.

Screenshots

No response

NuGet package version

1.4.2

Packaging type

Packaged (MSIX)

Windows version

Insider Build (xxxxx) (only on Windows 11)

IDE

Visual Studio 2022

Additional context

The same for FolderPicker

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 7
  • Comments: 55 (1 by maintainers)

Commits related to this issue

Most upvoted comments

Yes, the problem still exist in WinUI3 with admin right. Please fix this!

As mentioned above the Picker apis are not designed for Admin.

Because the storage apis return heavy weight objects, a better approach would be to use IFileDialog. A good example has been published here: learn.microsoft.com/en-us/uwp/api/windows.storage.pickers.filesavepicker?view=winrt-22621#in-a-desktop-app-that-requires-elevation

In my opinion, if I have to write 150 lines just to get a dialog in 2023, I just never use this SDK again.

As mentioned above the Picker apis are not designed for Admin.

Because the storage apis return heavy weight objects, a better approach would be to use IFileDialog. A good example has been published here: https://learn.microsoft.com/en-us/uwp/api/windows.storage.pickers.filesavepicker?view=winrt-22621#in-a-desktop-app-that-requires-elevation

Ah, seeing that new post reminded me that I never did follow up here.

I rewrote my music server app in WPF and it runs perfectly on Win 10 & 11 and I can deploy it (copy the files to another PC) with ease! I can also run it 24 hours a day – and use memory! It’s amazing! I think this WPF thing could catch on!

Or maybe I’m one of the few remaining developers who still write code they want to run on PCs and have no desire for a “UI framework” that throttles their memory usage and app performance. If I were targeting a mobile device or needed to worry about batteries, I would welcome such features – and I’d probably have little need for an open file dialog.

This could be a simple case of misinformation - I was under the impression that WinUI3 was for writing desktop apps. Honestly, I wish it were, but I don’t think a framework that arrests so much control from the developer is going to succeed for serious desktop apps.

As mentioned above the Picker apis are not designed for Admin.

It seems that this is causing a lot of friction with devs (myself included), perhaps the apis need to be rethought to support this scenario.

Really? This is modern SDK or what? I don’t care if it’s returning heavy objects or other objects. Run windows programs as admin is a normal thing many apps need it .

@AdamBraden I noticed even WinUI 3 Gallery has the same problem in their FilePicker example - up til now. Running the app as Admin makes the function break. Conclusion: it’s a WinUI/SDK bug. When will the actual problem be solved? 😃

Probably in 2-3 years.

Indeed, such a simple thing like a FilePicker requires advanced knowledge and years of experience to understand. I’m a C# developer and I need to use unmanaged code with C++ to open a file picker…this is not how developement experience for WASDK should be.

WinUI3 makes me crazy for even basic stuff is not working. I return back to use electron.

What we could consider is creating a WinAppSDK wrapper around IFileDialog apis that provide an equivalent to the Picker apis. There are some opportunities to improve as well - StorageFiles are very heavyweight objects, and so we could consider returning something more optimized.

It’s 2024 and Windows App SDK has no working file dialog. What an achievement.

December 17, No any update yet? This issue seems like almost a year but i cant see any update in this problem.

@AdamBraden I noticed even WinUI 3 Gallery has the same problem in their FilePicker example - up til now. Running the app as Admin makes the function break. Conclusion: it’s a WinUI/SDK bug. When will the actual problem be solved? 😃

Wow - at least an hour wasted on this bug. Yes, it’s a bug. It cannot be “by design” that an administrator cannot open a file.

This is 2023 and I really wanted to like WinUI3 but I think this is the last straw for me - I’m moving back to WPF.

Calling MediaDevice.GetAudioRenderSelector() crashes if you run an .exe and you ARE NOT running “As adminstrator”. So, I have to run As Admin…

…and then calling picker.PickSingleFileAsync() will crash if you ARE running an .exe “As Administrator”.
Oh, yeah, endless loops – I remember learning about these 😃

I do see that I could use a tool to generate code that will call the old Windows APIs from WinUI3, but I’m in complete agreement with others who have asked “Why would I do that?”. I can more easily drop back to WPF and get my app to actually run – not only from VS on the dev machine, but on other PCs - without jumping through hoops!

I may post my experience to the WinUI3 official feedback channel but, in summary, I feel like right now WinUI3 in not a UI framework but a new sandbox framework. It’s not for serious desktop development as the design architecture seem to assume I’m ok with being shut down in the background or having resources taken away from my app – but those are not an option for my app and there is apparently no way to allow the owner of the PC to make such decisions as opposed to the Framework.

I was encountering a similar problem when trying to use the FolderPicker when running as admin. Nothing would appear. So for anyone that was searching for a solution with a problem with FolderPicker, here is how I got a folder picker working when running as admin:

[DllImport("Shell32.dll", CharSet = CharSet.Unicode)]
      public static extern IntPtr SHBrowseForFolder(ref BROWSEINFO lpbi);

      [DllImport("Shell32.dll", CharSet = CharSet.Unicode)]
      public static extern bool SHGetPathFromIDList(IntPtr pidl, IntPtr pszPath);

      [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
      public struct BROWSEINFO
      {
          public IntPtr Owner;
          public IntPtr PIDL;
          public IntPtr DisplayName;
          public string Title;
          public uint Flags;
          public IntPtr Callback;
          public IntPtr Param;
          public int Image;
      }

      public const uint BIF_NEWDIALOGSTYLE = 0x00000040;
      public const uint BIF_USENEWUI = BIF_NEWDIALOGSTYLE | 0x00000200;

      private void btnBrowse_Click(object sender, RoutedEventArgs e)
      {
          var bi = new BROWSEINFO
          {
              Title = "Select Folder",
              Flags = BIF_NEWDIALOGSTYLE | BIF_USENEWUI,
          };

          var pidl = SHBrowseForFolder(ref bi);
          if (pidl != IntPtr.Zero)
          {
              var path = Marshal.AllocHGlobal(260);
              SHGetPathFromIDList(pidl, path);
              Console.WriteLine("Selected folder: " + Marshal.PtrToStringUni(path));
              Marshal.FreeHGlobal(path);
          }
          else
          {
              Console.WriteLine("Operation cancelled.");
          }
      }

@bogdan-patraucean Can you post usings? I’m not so much experience and can’t in any way to find CoCreateInstance in PInvoke what reference I should add?

I just uploaded a small test sample (with a C# class from C++ headers that I had done in WinForms) : https://github.com/castorix/WinUI3_IFileDialog

// filter value guide: "[name]|[extension]|[name2]|[extension2]"
// name can be whatever you want but not null
public unsafe string PickFile(string filter)
    {
        try
        {
            string path = null;

            PInvoke.CoCreateInstance(typeof(FileOpenDialog).GUID, null, CLSCTX.CLSCTX_INPROC_SERVER,out IFileOpenDialog picker).ThrowOnFailure();

            List<COMDLG_FILTERSPEC> extensions = new();

            if (!string.IsNullOrEmpty(filter))
            {
                string[] tokens = filter.Split('|');

                if (0 == tokens.Length % 2)
                {
                    for (int i = 1; i < tokens.Length; i += 2)
                    {
                        COMDLG_FILTERSPEC extension;

                        extension.pszSpec = (char*)Marshal.StringToHGlobalUni(tokens[i]);
                        extension.pszName = (char*)Marshal.StringToHGlobalUni(tokens[i - 1]);
                        extensions.Add(extension);
                    }
                }
            }

            picker.SetFileTypes(extensions.ToArray());
            picker.Show((HWND)App.Window.Hwnd());
            picker.GetResult(out IShellItem item);
            item.GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out PWSTR name);

            path = name.ToString();
            Marshal.FreeCoTaskMem(new IntPtr(name.Value));

            return path;
        }
        catch (Exception)
        {
            return null;
        }
    }

I managed to do a method that kinda works, so until the issue is fixed, this ugly workaround that requires CsWin32 with PInvoke will do the job. It’s not ideal, but an ugly solution it’s better than a broken feature.