Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

How to show native file picker?

Discussion in 'Windows' started by User340, Jan 24, 2016.

  1. User340

    User340

    Joined:
    Feb 28, 2007
    Posts:
    3,001
    I'm trying to show a native windows file picker. I'd like the user to select an image for use in the program. Here's what I've come up with so far:

    Code (CSharp):
    1. public static string ShowOpenPanel(bool includeFiles, bool includeDirectories)
    2. {
    3.     Application.InvokeOnUIThread(async () => {
    4.         var filePicker = new FileOpenPicker();
    5.         var file = await filePicker.PickSingleFileAsync();
    6.     }, false);
    7.     return string.Empty;
    8. }
    This code produces the following runtime error in Visual Studio: Capture.PNG
     
  2. Tomas1856

    Tomas1856

    Unity Technologies

    Joined:
    Sep 21, 2012
    Posts:
    3,514
    See the Output window for more information, but I think it should be like this:

    Code (csharp):
    1.  
    2. public static string ShowOpenPanel(bool includeFiles, bool includeDirectories)
    3. {
    4.    Application.InvokeOnUIThread(async () => {
    5.        var filePicker = new FileOpenPicker();
    6.        filePicker.FileTypeFilter.Add("*");
    7.        var file = await filePicker.PickSingleFileAsync();
    8.    }, false);
    9.    return string.Empty;
    10. }
    11.  
     
    User340 likes this.
  3. User340

    User340

    Joined:
    Feb 28, 2007
    Posts:
    3,001
    Thanks a bunch, so simple.
     
  4. LuckyHamster

    LuckyHamster

    Joined:
    Oct 28, 2014
    Posts:
    50
    Real Newb here:
    Can you use that code and run it on unity editor or do you have to create a visual studio sln and run it on there to make it work. When i copied and pasted that code, I just got errors because unity does not recognize classes like FileOpenPicker.

    Thanks.
     
  5. Tomas1856

    Tomas1856

    Unity Technologies

    Joined:
    Sep 21, 2012
    Posts:
    3,514
    No, you can't use that code in Editor, because that API comes from Windows Runtime, accessible only in Windows Store Apps. That code should be wrapped in #if NETFX_CORE ... #endif, to avoid errors in Editor.
     
    Lohoris2 and User340 like this.
  6. User340

    User340

    Joined:
    Feb 28, 2007
    Posts:
    3,001
    I've made progress, see below for what I've come up with so far. I'm currently stuck at trying to return the path that the user selected. It seems more complicated due to the asynchronous nature of the file picker. Any ideas?

    Code (CSharp):
    1.         public static string ShowOpenPanel(bool fileSelection = true, bool directorySelection = false, bool multiSelection = false, string fileType1 = "", string fileType2 = "", string fileType3 = "")
    2.         {
    3.             Application.InvokeOnUIThread(async () => {
    4.                 var filePicker = new FileOpenPicker();
    5.                 filePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
    6.                 filePicker.FileTypeFilter.Add(fileType1);
    7.                 filePicker.FileTypeFilter.Add(fileType2);
    8.                 filePicker.FileTypeFilter.Add(fileType3);
    9.                 if (multiSelection)
    10.                 {
    11.                     IReadOnlyList<StorageFile> files = await filePicker.PickMultipleFilesAsync();
    12.                     if (files.Count > 0)
    13.                     {
    14.                     }
    15.                 }
    16.                 else
    17.                 {
    18.                     StorageFile file = await filePicker.PickSingleFileAsync();
    19.                     // TODO: Return the path to the file. How?
    20.                 }
    21.             }, false);
    22.             return string.Empty;
    23.         }
    24.  
     
  7. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,504
    You are trying to make synchronous API out of asynchronous one. I think it would be better to adapt to async one.
    Have few variables in class and set then in the code you run on UI thread.
    I.e. you can have a boolean variable filePickerDone, which you would set to false initially and tahe code you run on UI thread would set it to tru as last step. You can check that variable in Update() function of your script and read others once it becomes true.
     
  8. neomarian

    neomarian

    Joined:
    May 11, 2012
    Posts:
    43
    Code (CSharp):
    1. public static string ShowOpenPanel(bool fileSelection = true, bool directorySelection = false, bool multiSelection = false, string fileType1 = "", string fileType2 = "", string fileType3 = "")
    2. {
    3.     Application.InvokeOnUIThread(async() =>
    4.     {
    5.         var filePicker = new FileOpenPicker();
    6.         filePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
    7.         filePicker.FileTypeFilter.Add(fileType1);
    8.         filePicker.FileTypeFilter.Add(fileType2);
    9.         filePicker.FileTypeFilter.Add(fileType3);
    10.         if (multiSelection)
    11.         {
    12.             IReadOnlyList<StorageFile> files = await filePicker.PickMultipleFilesAsync();
    13.             UnityEngine.WSA.Application.InvokeOnAppThread(() =>
    14.             {
    15.                 UWPFilesSelected(files);
    16.             }, true);
    17.         }
    18.         else
    19.         {
    20.             StorageFile file = await filePicker.PickSingleFileAsync();
    21.             UnityEngine.WSA.Application.InvokeOnAppThread(() =>
    22.             {
    23.                 UWPFileSelected(file);
    24.             }, true);
    25.         }
    26.     }, false);
    27.     return string.Empty;
    28. }
    29.  
    30. private void UWPFileSelected(Windows.Storage.StorageFile file)
    31. {
    32.     if (file != null)
    33.     {
    34.         // do something
    35.         // file path = file.Path
    36.     }
    37. }
    38.  
    39. private void UWPFilesSelected(IReadOnlyList<StorageFile> files)
    40. {
    41.     if (files.Count > 0)
    42.     {
    43.         // do something
    44.     }
    45. }
    46.  
     
    Last edited: Apr 5, 2018
  9. hippogames

    hippogames

    Joined:
    Feb 5, 2015
    Posts:
    192
    Hi! How do you access FileOpenPicker from Unity? Did you reference some Windows libs?
     
  10. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    @hippogames I was able to open it for Windows and OSX by adding the System.Windows.Forms dll from Mono. I only include it for standalone builds, and we use the #if UNITY_STANDALONE directive to ignore it for mobile devices.

    This dll is included with Unity. For example, I was able to find it here on my computer:
    C:\Program Files\Unity\Hub\Editor\2018.1.8f1\Editor\Data\Mono\lib\mono\2.0\System.Windows.Forms.dll

    I just dragged and dropped this into my project.

    EDIT: This is for Standalone apps. You might need something else for UWP apps.
     
  11. darkover21

    darkover21

    Joined:
    Feb 20, 2020
    Posts:
    3
    Sorry but Unity says : error CS0117: 'Application' does not contain a definition for 'InvokeOnUIThread'
     
  12. Tomas1856

    Tomas1856

    Unity Technologies

    Joined:
    Sep 21, 2012
    Posts:
    3,514
    Maybe you forgot namespace

    using UnityEngine.WSA;
     
  13. darkover21

    darkover21

    Joined:
    Feb 20, 2020
    Posts:
    3
    Sorry, but I am getting this error now... I can not find any reference for including a library for this
    error CS0246: The type or namespace name 'FileOpenPicker' could not be found (are you missing a using directive or an assembly reference?)
     
  14. darkover21

    darkover21

    Joined:
    Feb 20, 2020
    Posts:
    3
    It's working now I used :

    #if ENABLE_WINMD_SUPPORT
    using Windows.Storage;
    using Windows.Storage.Streams;
    using Windows.Storage.Pickers;
    #endif
    Thankyou