Forum Discussion

davidanthoff's avatar
davidanthoff
Brass Contributor
Jun 08, 2020

How to use AddOptionalPackageAsync?

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

    • davidanthoff's avatar
      davidanthoff
      Brass Contributor

      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 https://docs.microsoft.com/en-us/uwp/api/windows.management.deployment.packagemanager.addpackagebyappinstallerfileasync?view=winrt-19041 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?

      • Tanaka_Jimha's avatar
        Tanaka_Jimha
        Former Employee

        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: 

         

         

        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 

Resources