How to use AddOptionalPackageAsync?

Brass Contributor

I'm trying to build a MSIX solution for the [Julia](https://julialang.org/) language, but I'm stuck in that I can't get AddOptionalPackageAsync to work. In general, I'm using a PackagingLayout.xml that creates a bunch of packages and upload them all to a S3 bucket. I then also upload an appinstaller file.

 

Here is what works: I can install the main app from the appinstaller file, and it also successfully installs the optional packages that I specify as optional in the appinstaller file. What doesn't work is my attempt to install additional optional packages from code with a call to AddOptionalPackageAsync.

 

The code that I'm using to call AddOptionalPackageAsync looks like this:

 

auto packageToInstall = L"Julia-1.4.2";

auto res = catalog.AddOptionalPackageAsync(packageToInstall).get();

auto err = hresult_error(res.ExtendedError());

std::wcout << err.message().c_str() << std::endl;

 

This produces an output of "Access is denied.".

 

The content of the Julia.appinstaller is

 

<?xml version="1.0" encoding="utf-8"?>
<AppInstaller
    xmlns="http://schemas.microsoft.com/appx/appinstaller/2017/2"
    Version="1.0.0.0"
    Uri="https://winjulia.s3-us-west-1.amazonaws.com/Julia.appinstaller" >

    <MainBundle
        Name="Julia"
        Publisher="CN=Julialang"
        Version="1.0.0.0"
        Uri="https://winjulia.s3-us-west-1.amazonaws.com/Julia.appxbundle" />

    <OptionalPackages>
        <Bundle
            Name="Julia-1.4.1"
            Publisher="CN=Julialang"
            Version="1.0.0.0"
            Uri="https://winjulia.s3-us-west-1.amazonaws.com/Julia-1.4.1.appxbundle" />

    </OptionalPackages>

    <RelatedPackages>
        
        <Bundle
            Name="Julia-1.4.2"
            Publisher="CN=Julialang"
            Version="1.0.0.0"
            Uri="https://winjulia.s3-us-west-1.amazonaws.com/Julia-1.4.2.appxbundle" />

    </RelatedPackages>
    
    <UpdateSettings>
    <OnLaunch HoursBetweenUpdateChecks="0"/>   
  </UpdateSettings>

</AppInstaller>

 

The package `Julia-1.4.1` (which specified as an <OptionalPackages> child) gets successfully installed with the main app, and if I swap things and put `Julia-1.4.2` into the <OptionalPackages> parent and `Julia-1.4.1` into the <RelatedPackages> element, then `Julia-1.4.2` gets installed correctly (but then I can't get AddOptionalPackageAsync  to install Julia-1.4.1.

 

I guess I'm passing the wrong string to AddOptionalPackageAsync, maybe?

 

Also, is there an API that I can call from within my main package that would essentially give me the family package ID of all the packages that I have listed in the appinstaller either in the <OptionalPackages> or in the <RelatedPackages> element?

 

Oh, and actually, I'm not even sure that putting things into the <RelatedPackages> parent is the correct move :)

 

Any help is much appreciated!

9 Replies

Hi @davidanthoff,

 

Can you try add the second package under optional packages as well in your AppInstaller file something like this:

 

 <OptionalPackages>
        <Bundle
            Name="Julia-1.4.1"
            Publisher="CN=Julialang"
            Version="1.0.0.0"
            Uri="https://winjulia.s3-us-west-1.amazonaws.com/Julia-1.4.1.appxbundle" />
        <Bundle
            Name="Julia-1.4.2"
            Publisher="CN=Julialang"
            Version="1.0.0.0"
            Uri="https://winjulia.s3-us-west-1.amazonaws.com/Julia-1.4.2.appxbundle" />
 </OptionalPackages>

 

That should install both packages, or is that not your desired workflow?

 

As another install option from your code, consider using AddPackageByAppInstallerFileAsync to install packages defined in your AppInstaller file. You can find other AppInstaller file APIs here.

 

About using AddOptionalPackageAsync from code, can you try a few things:

  1. Add the packagemanagement capability to your app doing performing the install.
    <Package>
    ...
    
      <Capabilities>
        <rescap:Capability Name="packageManagement" />
      </Capabilities>
      
    ...
    </Package>​
  2. Use the packagefamilyname when calling AddOptionalPackageAsync - you can get the specific package's packagefamilyname by running Get-AppxPackage when it's installed on a machine. So you'd have to install it and run the command to get the correct value for future use. There's an explanation here  
  3. Make sure your packages are part of a related set.

 

Cheers,

Tanaka

@Tanaka_Jimha Thanks! I tried all your suggestions, but no luck so far. Here are some more details:

 

I don't want to install all the optional dependencies at the same time when the main app is installed, so I don't think I should add all of them to the <OptionalPackages> element in the appinstaller file, right? I only want one of them installed with the main app, so I add that optional package to the <OptionalPackages> element, and then all the other optional packages I want to be able to install via an in-app option, so I add all of those packages to the <RelatedPackages> element in the appinstaller file. You can see the details of how I do this in the code that I posted with the original message.

 

I think AddPackageByAppInstallerFileAsync for the same reason is also not the right tool to implement my in-app feature add thing, right? As far as I can tell, it doesn't provide an option to install a specific optional package of the app, right? Or did I miss an option there somewhere?

 

I did add <rescap:Capability Name="packageManagement" /> to my main app now, and it shows up in the UI when I install that, but it doesn't change the error message I get.

 

When I install all the optional packages on my system, and then run the following ps code:

> $x = Get-AppxPackage Julia*
> $x.Dependencies

I get this output:

Name              : Julia-1.4.1
Publisher         : CN=Julialang
Architecture      : X64
ResourceId        :
Version           : 1.0.0.0
PackageFullName   : Julia-1.4.1_1.0.0.0_x64__87dh6scs60qg2
InstallLocation   : C:\Program Files\WindowsApps\Julia-1.4.1_1.0.0.0_x64__87dh6scs60qg2
IsFramework       : False
PackageFamilyName : Julia-1.4.1_87dh6scs60qg2
PublisherId       : 87dh6scs60qg2
IsResourcePackage : False
IsBundle          : False
IsDevelopmentMode : False
NonRemovable      : False
IsPartiallyStaged : False
SignatureKind     : Developer
Status            : Ok

Name              : Julia-1.4.2
Publisher         : CN=Julialang
Architecture      : X64
ResourceId        :
Version           : 1.0.0.0
PackageFullName   : Julia-1.4.2_1.0.0.0_x64__87dh6scs60qg2
InstallLocation   : C:\Program Files\WindowsApps\Julia-1.4.2_1.0.0.0_x64__87dh6scs60qg2
IsFramework       : False
PackageFamilyName : Julia-1.4.2_87dh6scs60qg2
PublisherId       : 87dh6scs60qg2
IsResourcePackage : False
IsBundle          : False
IsDevelopmentMode : False
NonRemovable      : False
IsPartiallyStaged : False
SignatureKind     : Developer
Status            : Ok

So from this I take it that I should use "Julia-1.4.2_87dh6scs60qg2" as the string that I pass to AddOptionalPackageAsync? I'm doing that now, but I still get the same error message "Access is denied".

 

I do think everything is in one related set, I'm creating all the packages with a PackagingLayout.xml file that looks like this:

<PackagingLayout xmlns="http://schemas.microsoft.com/appx/makeappx/2017">
  <!-- Main game -->
  <PackageFamily ID="Julia" FlatBundle="true" ManifestPath="appxmanifest.xml" ResourceManager="false">
    
    <!-- x64 code package-->
    <Package ID="Julia-x64" ProcessorArchitecture="x64">
      <Files>
        <File DestinationPath="Julia\Julia.exe" SourcePath="C:\Users\david\source\repos\WinJulia\Release\Julia.exe"/>
        <File DestinationPath="Images\*.png" SourcePath="Images\*.png"/>
      </Files>
    </Package>

    
  </PackageFamily>

  <PackageFamily ID="Julia-1.4.2" Optional="true" ManifestPath="juliaversions\julia-1.4.2-appxmanifest.xml" ResourceManager="false">
    <Package ID="Julia-1.4.2.x64" ProcessorArchitecture="x64">
      <Files>
        <File DestinationPath="Julia\**" SourcePath="C:\Users\david\source\repos\WinJulia\optionalpackages\julia-1.4.2\Julia\**"/>
        <File DestinationPath="Images\*.png" SourcePath="Images\*.png"/>
      </Files>
    </Package>
  </PackageFamily>

  <PackageFamily ID="Julia-1.4.1" Optional="true" ManifestPath="juliaversions\julia-1.4.1-appxmanifest.xml" ResourceManager="false">
    <Package ID="Julia-1.4.1.x64" ProcessorArchitecture="x64">
      <Files>
        <File DestinationPath="Julia\**" SourcePath="C:\Users\david\source\repos\WinJulia\optionalpackages\julia-1.4.1\Julia\**"/>
        <File DestinationPath="Images\*.png" SourcePath="Images\*.png"/>
      </Files>
    </Package>
  </PackageFamily>

  <PackageFamily ID="Julia-1.4.0" Optional="true" ManifestPath="juliaversions\julia-1.4.0-appxmanifest.xml" ResourceManager="false">
    <Package ID="Julia-1.4.0.x64" ProcessorArchitecture="x64">
      <Files>
        <File DestinationPath="Julia\**" SourcePath="C:\Users\david\source\repos\WinJulia\optionalpackages\julia-1.4.0\Julia\**"/>
        <File DestinationPath="Images\*.png" SourcePath="Images\*.png"/>
      </Files>
    </Package>
  </PackageFamily>
</PackagingLayout>

And I believe that should create all packages as being in one related set, right?

Hi @davidanthoff 

 

Access Denied means you're having permission issues calling the API. Our devs said the fastest way to root cause will be to get logs. Can you please make a Feedback Hub submission capturing the error in the Developer Platform > App Deployment category: 

 

DeploymentFeedbackSettings.png

 

After capturing the issue, can you also attach the appxmanifest.xml files of your main app and optional packages with the submission. Please send me a link to the issue once you're done.

 

Thanks,

Tanaka 

@Tanaka_Jimha  Here is the link https://aka.ms/AA8obl4, hope that helps.

 

I'm also preparing a GitHub repo with all the code that I use to create these msix packages, it is all open source, so no problem to share that.

@davidanthoff Actually, I just realized that it will take a little longer until I can publish that GitHub repo: right now I have a codesigning cert that includes my private address, and I don't want to use that on the public internet. I'm working with my issuer right now to remove the address, as soon as I have that, I'll post it. But the issue I submitted on the feedback hub should include the necessary files.

Thanks for submitting the files @davidanthoff. I've forwarded them to the dev team for investigation. sounds good, let me know when you have the GitHib repo available and I'll also have a look at that.

 

@Tanaka_Jimha Alright, I've got the github repo up now, it is here:

 

https://github.com/davidanthoff/winjulia

 

You won't be able to run the build steps because you also need various builds of Julia itself, and setting that up is complicated, but it should give you an idea of what scripts I'm using to build things.

 

I'm also hosting the packages that I've created online now at https://winjulia.s3-us-west-1.amazonaws.com/index.html, so you and the dev team should be able to run the installer etc. on your own system and collect logs.

 

Here are some random comments that maybe are helpful:

  • The link "Install Julia" on that S3 website that I posted links to the appinstaller file. It will install the "Julia" package, and one of the optional packages, namely Julia-1.4.1. There are two other optional packages (Julia-1.4.0 and Julia-1.4.2), and the website has links to all three optional packages.
  • Installing any of the three optional packages via the weblink from that S3 site works.
  • What I want to do is install optional packages from in-app code, though. The specific code that I'm using for that is here, and that is also the part of the code that errors. If you install the main "Julia" app from the website that I linked to and run it, you will see an error message, and the code that I linked to in this item here is where that error occurs.

Let me know if this helps or if you need any more information!

Hi @davidanthoff,

 

Thanks for all the details you sent. Based on the logs from the feedback you filed it looks like the "access denied" error is happening when we try to access the AppInstaller file on S3 to get information for downloading the optional package. I'll message you more details.

 

Tanaka

@Tanaka_Jimha Cool! Do you think there will be a fairly easy way for me to fix this, or is this a more complicated problem? I'm not tied to S3 either, would be happy to use some other hosting as well.