Launcher.LaunchFileAsync(…) not working

2019-08-27 11:58发布

问题:

I'm working on an App for Win8 which should include the possibility of saving contact information. The service I use offers VCard support so I decided on using them. I can succesfully download and save them, only opening them automatically doesn't work. The files are "correct", and can be opened from the explorer without any problem. Any ideas why LaunchFileAsync isn't working?

Here's a dump of the code:

    private async void SaveContactSelected()
    {
        IRandomAccessStreamReference img = RandomAccessStreamReference.CreateFromUri(SelectedItem.Image.UriSource);
        StorageFile file = await StorageFile.CreateStreamedFileFromUriAsync(SelectedItem.Title.Replace(' ', '_')+".vcf", new Uri(SelectedItem.VCardUrl), img);

        var stream = await file.OpenReadAsync();
        uint size = Convert.ToUInt32(stream.Size);
        IBuffer buffer = await stream.ReadAsync(new Windows.Storage.Streams.Buffer(size), size, InputStreamOptions.None);
        if(!stream.CanRead)
        {
            //TODO: Error handling
            return;
        }

        FileSavePicker savePicker = new FileSavePicker();
        savePicker.FileTypeChoices.Add("vcard", new List<string> { ".vcf" });
        savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
        savePicker.SuggestedFileName = SelectedItem.Title.Replace(' ', '_') + ".vcf";
        StorageFile saveDestination = await savePicker.PickSaveFileAsync();

        if (saveDestination != null)
        {
            CachedFileManager.DeferUpdates(saveDestination);
            await FileIO.WriteBufferAsync(saveDestination, buffer);
            FileUpdateStatus status = await CachedFileManager.CompleteUpdatesAsync(file);
            if (status == FileUpdateStatus.Complete)
            {
                bool succ = await Launcher.LaunchFileAsync(saveDestination, new LauncherOptions() { DisplayApplicationPicker=true });
                return;
            }
            else
            {
                //TODO: Error handling
            }
        } 
    }

An here a dump of the relevant parts of the manifest:

<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="MyApp.App">
  <VisualElements DisplayName="MyApp.com" Logo="Assets\Images\Logo.png" SmallLogo="Assets\Images\SmallLogo.png" Description="MyApp.com Description TODO" ForegroundText="dark" BackgroundColor="#464646">
    <DefaultTile ShowName="allLogos" WideLogo="Assets\Images\LogoWide.jpg" />
    <SplashScreen Image="Assets\Images\SplashScreen.png" BackgroundColor="#FFFFFF" />
    <InitialRotationPreference>
      <Rotation Preference="landscape" />
    </InitialRotationPreference>
  </VisualElements>
  <Extensions>
    <Extension Category="windows.search" />
    <Extension Category="windows.fileTypeAssociation">
      <FileTypeAssociation Name="vcard">
        <DisplayName>V-Card</DisplayName>
        <EditFlags OpenIsSafe="true" />
        <SupportedFileTypes>
          <FileType ContentType="text/x-vcard">.vcf</FileType>
        </SupportedFileTypes>
      </FileTypeAssociation>
    </Extension>
  </Extensions>
</Application>

Edit: Added manifest dump for more clarity.

回答1:

Do you have any application that handles VCard format? I think an applications Package.appxmanifest would need to include a section like this:

  <Extensions>
    <Extension Category="windows.fileTypeAssociation">
      <FileTypeAssociation Name="...">
        <DisplayName>...</DisplayName>
        <InfoTip>...</InfoTip>
        <SupportedFileTypes>
          <FileType ContentType="text/vcard">.vcf</FileType>
        </SupportedFileTypes>
      </FileTypeAssociation>
    </Extension>
  </Extensions>

If you look at the Mail app here - it does not seem to have such a section.

"c:\Program Files\WindowsApps\microsoft.windowscommunicationsapps_16.4.4206.722_x64__8wekyb3d8bbwe\AppxManifest.xml"

*EDIT

The Mail app actually has a section that mentions <SupportsAnyFileType/>, but it is in the ShareTarget section, not a FileTypeAssociation one.

*EDIT 2

It seems like there is built in support for VCF files in Windows and this works fine for me, assuming you have TestCard.vcf file in your Documents library, have the capability to open DocumentsLibrary declared in the manifest and File Type Association declared to open .vcf files (Content type: text/vcard, File type: .vcf).

var vcf = await KnownFolders.DocumentsLibrary.GetFileAsync("TestCard.vcf");
var vcfBytes = await FileIO.ReadBufferAsync(vcf);
var vcfCopy = await KnownFolders.DocumentsLibrary.CreateFileAsync("TestCard - copy.vcf");
CachedFileManager.DeferUpdates(vcfCopy);
await FileIO.WriteBufferAsync(vcfCopy, vcfBytes);
await CachedFileManager.CompleteUpdatesAsync(vcfCopy);
Launcher.LaunchFileAsync(vcfCopy, new LauncherOptions { DisplayApplicationPicker = true });


回答2:

While dealing with this error:

  • Write a file out to the temp folder of my W8.1 app
  • Double clicking on the file opens it just fine (it was pptx in this case)
  • LaunchFileAsync always returned false.

Two things I discovered. First, a reference to some odd safety check done by Windows (which wasn't what caused it for me: https://social.msdn.microsoft.com/Forums/en-US/c0625345-5d57-4e40-b446-85db4c6ef355/why-does-windowssystemlauncherlaunchfileasync-fail-with-file-from-my-local-folder?forum=winappswithhtml5).

Second, which was my problem, was that I wasn't on the UI thread! Switching so LaunchFileAsync was on the UI thread made it suddenly work just fine.