maui icon indicating copy to clipboard operation
maui copied to clipboard

Publish Windows, AppStore Bundle (.msixupload) missing

Open epsmae opened this issue 1 year ago • 1 comments

Description

Publishing a .Net Maui App to Windows store is quite a challenging task. There is documentation but it seems like the visual studio maui integration is not yet completed as AppBundle can not be selected anymore in the wizzard compared to uwp (Publish UWP to Store).

The docs only mention sideloading: https://learn.microsoft.com/en-us/dotnet/maui/windows/deployment/publish-visual-studio-folder?view=net-maui-8.0

I tried also over the dotnet publish command but this has the same effect I was not able to get the .msixupload file. https://learn.microsoft.com/en-us/dotnet/maui/windows/deployment/publish-unpackaged-cli?view=net-maui-8.0

There are many obstacles to publish the windows app independent of this issue: https://github.com/dotnet/maui/issues/8304 https://github.com/dotnet/maui/issues/13869 https://github.com/dotnet/maui/issues/9547 https://github.com/dotnet/maui/issues/9879 https://github.com/microsoft/WindowsAppSDK/issues/3337 https://github.com/dotnet/maui/issues/10564

Steps to Reproduce

  1. Create a dotnet new maui project
  2. Select Windows as Target
  3. Right click Publish
  4. Select MicrosoftStore as or Microsoft Store under new app if you have not yet selected
  5. Select publish profile for Release x64
  6. Select generate artifacts to validate...
  7. Select create
  8. Optional run test after successful publish
  9. Observe in publish directory that the .msixupload is missing

Link to public reproduction project repository

No response

Version with bug

8.0.40 SR5

Is this a regression from previous behavior?

Yes, this used to work in Xamarin.Forms

Last version that worked well

Unknown/Other

Affected platforms

Windows

Affected platform versions

windows10.0.19041.0

Did you find any workaround?

There is one but I don't think it is acceptable: https://github.com/dotnet/maui/discussions/11446

Relevant log output

No response

epsmae avatar May 16 '24 09:05 epsmae

Hi I'm an AI powered bot that finds similar issues based off the issue title.

Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one and thumbs upping the other issue to help us prioritize it. Thank you!

Closed similar issues:

Note: You can give me feedback by thumbs upping or thumbs downing this comment.

github-actions[bot] avatar May 16 '24 09:05 github-actions[bot]

I tried on .NET MAUI App (8.0.40/8.0.21) and can repro this issue, after publish Windows to Microsoft Store, the bundle.upload file could not be generated. But on Xamarin.Forms it worked fine.

jaosnz-rep avatar May 28 '24 09:05 jaosnz-rep

here's another related issue/workaround worth to mention: https://github.com/dotnet/maui/issues/12327

this works great in my case when using a single rid (<RuntimeIdentifiers>win10-x64</RuntimeIdentifiers>) does not work in my case with <RuntimeIdentifiers>win10-x64;win10-arm64</RuntimeIdentifiers>

@mattleibow (tagging you because of your comment with workaround in [12327](https://github.com/dotnet/maui/issues/12327#issuecomment-1382620354) Now that the Copilot+ devices with ARM64 processors are about to be released, it would be great if there was a better way out of the box, without any workaround/hack

baaaaif avatar May 28 '24 15:05 baaaaif

... my path got too long for win10-x64;win10-arm64 -.- 12327 contains a working solution :)

baaaaif avatar May 29 '24 06:05 baaaaif

@epsmae Could you check your path?

... my path got too long for win10-x64;win10-arm64 -.- 12327 contains a working solution :)

@epsmae Could you check your path?

jsuarezruiz avatar Jun 13 '24 13:06 jsuarezruiz

@jsuarezruiz yes I got it working with the workaround but as mentioned in this ticket I don't think this is acceptable. There are many guys porting the Xamarin.UWP Apps to Maui and Maui states it supports windows so at least publish from visual studio and dotnet publish should work. There is also nothing like that mentioned in the docs.

epsmae avatar Jun 13 '24 15:06 epsmae

I am able to successfully create a '.msixbundle' file from dotnet but I am still having issues producing a '.msixupload' file despite following @mattleibow instructions. Can someone who has successfully produced a '.msixupload' file, on MAUI, please elaborate? Thanks

sorrybomber avatar Jul 23 '24 16:07 sorrybomber

So we are almost ready to ship our Windows UWP Xamarin.Forms app to .Net MAUI conversion. Am I correct in understanding that even through the CLI we don't have the ability still to create a package to upload to the Microsoft Store? I just tried and all I get is an MSIX under the _Test folder. Is there something with what I'm doing here?

dotnet.exe publish MyCompany.MAUI\MyCompany.MAUI.MyApp\MyCompany.MAUI.MyApp.csproj --framework net8.0-windows10.0.22621.0 --configuration Release --self-contained -nologo -nr:false -nologo -nr:false -p:AppxBundle=Always;UapAppxPackageBuildMode=StoreUpload;AppxBundlePlatforms="x86|x64";

mnxamdev avatar Aug 26 '24 16:08 mnxamdev

I am able to successfully create a '.msixbundle' file from dotnet but I am still having issues producing a '.msixupload' file despite following @mattleibow instructions. Can someone who has successfully produced a '.msixupload' file, on MAUI, please elaborate? Thanks

@sorrybomber were you able to find a way to generate a '.msixupload' file to be able upload to the Microsoft Store? We're getting to release and I feel like I'm about to tell management that after all our work to start on this endeavor we won't be able to release.

mnxamdev avatar Aug 27 '24 19:08 mnxamdev

@mnxamdev I got it working with the proposed workaround from @mattleibow However, I am still unable to submit it to the store due to the fulltrust requirement of webview2 on windows: Webview2 cannot be created when a WinUI3.0 desktop app is built as partialTrust](https://github.com/microsoft/microsoft-ui-xaml/issues/7982)

I really hope you have better luck than me, these are the steps I took to get the .msixupload

  1. You have to create a file names "Microsoft.Build.Msix.Packaging.MsixBundle.targets" next to your maui .csproj with the following content:
<Project>

  <!--
    =======================================================================
    Microsoft.Build.Msix.Packaging.MsixBundle.targets
    =======================================================================
    
    This targets file can be imported at the bottom of the main app project file (.csproj):
    
      <Import Project="Microsoft.Build.Msix.Packaging.MsixBundle.targets" />
    
    In order to build a .msix bundle, you can use `dotnet build`:
    
      dotnet build /t:GenerateMsixBundle -f net7.0-windows10.0.19041.0 <path/to/app.csproj>
    
    In order to control the RIDs in the app bundle, you can override them using the $(RuntimeIdentifiers)
    propertyin your .csproj. Make sure to condition on the Windows TargetFramework:
    
      <PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">
        <RuntimeIdentifiers>win10-x64;win10-x86;win10-arm64</RuntimeIdentifiers>
      </PropertyGroup>
  -->

  <!-- Make sure all the available RIDs are specified -->
  <PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows' and '$(RuntimeIdentifiers)' == ''">
    <RuntimeIdentifiers>win10-x64;win10-x86;win10-arm64</RuntimeIdentifiers>
  </PropertyGroup>

  <!-- Make at least one RID is specified for the IDE -->
  <PropertyGroup Condition=" '$([MSBuild]::GetTargetPlatformIdentifier($(TargetFramework)))' == 'windows' and '$(RuntimeIdentifier)' == '' ">
    <_SingleProjectHostArchitecture>$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)</_SingleProjectHostArchitecture>
    <_SingleProjectHostArchitecture>$(_SingleProjectHostArchitecture.ToLower())</_SingleProjectHostArchitecture>
    <RuntimeIdentifier>win10-$(_SingleProjectHostArchitecture)</RuntimeIdentifier>
  </PropertyGroup>

  <!-- Workaround for https://github.com/microsoft/WindowsAppSDK/issues/3337 -->
  <PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows' and '$(RuntimeIdentifierOverride)' != ''">
    <RuntimeIdentifier>$(RuntimeIdentifierOverride)</RuntimeIdentifier>
  </PropertyGroup>

  <!-- This runs inside each publish to determine the output path of the generated .msix -->
  <Target
    Name="_GenerateMsixBundlePublish"
    Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'"
    DependsOnTargets="Publish"
    Returns="@(_MsixPackageOutput)">

    <ItemGroup>
      <_MsixPackageOutput
        Include="$(AppxPackageOutput)"
        AppxPackageNameNeutral="$(AppxPackageNameNeutral)"
        AppxBundleExtension="$(AppxBundleExtension)"
        AppxPackageConfiguration="$(_AppxPackageConfiguration)" />
    </ItemGroup>

  </Target>

  <!-- This runs once to build the .msixbundle -->
  <Target
    Name="GenerateMsixBundle"
    Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">

    <!-- build up the matrix of the project to RID -->
    <ItemGroup>
      <_MsixBundleRID Include="$(RuntimeIdentifiers)" />
      <_MsixBundleProject Include="$(MSBuildProjectFile)" AdditionalProperties="RuntimeIdentifierOverride=%(_MsixBundleRID.Identity)" />
    </ItemGroup>

    <!-- publish the project for each RID -->
    <MSBuild
      Projects="@(_MsixBundleProject)"
      Targets="_GenerateMsixBundlePublish"
      BuildInParallel="$(BuildInParallel)">
      <Output
        TaskParameter="TargetOutputs"
        ItemName="_MsixPackageOutput" />
    </MSBuild>

    <!-- determine all the properties of the .msixbundle -->
    <PropertyGroup>
      <AppxPackageNameNeutral>%(_MsixPackageOutput.AppxPackageNameNeutral)</AppxPackageNameNeutral>
      <AppxBundleExtension>%(_MsixPackageOutput.AppxBundleExtension)</AppxBundleExtension>
      <AppxPackageConfiguration>%(_MsixPackageOutput.AppxPackageConfiguration)</AppxPackageConfiguration>
      <_MsixBundlePath>$(PackageOutputPath)$(TargetFramework)\$(AppxPackageNameNeutral)$(AppxPackageConfiguration)$(AppxBundleExtension)</_MsixBundlePath>
      <_MsixBundleFilesPath>$(IntermediateOutputPath)msixbundle.files</_MsixBundleFilesPath>
    </PropertyGroup>

    <!-- determine all the files of the .msixbundle -->
    <ItemGroup>
      <_MsixBundleFilesLines Include="[Files]" />
      <_MsixBundleFilesLines Include="@(_MsixPackageOutput->'&quot;%(FullPath)&quot; &quot;%(Filename)%(Extension)&quot;')" />
    </ItemGroup>

    <!-- write out the files -->
    <WriteLinesToFile
      File="$(_MsixBundleFilesPath)"
      Lines="@(_MsixBundleFilesLines)"
      Overwrite="True"
      WriteOnlyWhenDifferent="True" />
    <ItemGroup>
      <FileWrites Include="$(_MsixBundleFilesPath)" />
    </ItemGroup>

    <!-- generate the .msix bundle -->
    <Exec Command="&quot;$(MakeAppxExeFullPath)&quot; bundle /v /o /f &quot;$(_MsixBundleFilesPath)&quot; /p &quot;$(_MsixBundlePath)&quot;" />

    <!-- sign the .msix bundle -->
    <WinAppSdkSignAppxPackage
      Condition="'$(AppxPackageSigningEnabled)' == 'true'"
      AppxPackageToSign="$(_MsixBundlePath)"
      CertificateThumbprint="$(PackageCertificateThumbprint)"
      CertificateFile="$(PackageCertificateKeyFile)"
      HashAlgorithmId="$(AppxHashAlgorithmId)"
      EnableSigningChecks="$(EnableSigningChecks)"
      SignAppxPackageExeFullPath="$(SignAppxPackageExeFullPath)"
      TempCertificateFilePath="$(TempCertificateFilePath)"
      ExportCertificate="true">
      <Output TaskParameter="ResolvedThumbprint" PropertyName="ResolvedThumbPrint"/>
      <Output TaskParameter="AppxPackagePublicKeyFile" PropertyName="AppxPackagePublicKeyFile" />
    </WinAppSdkSignAppxPackage>

  </Target>

</Project>
  1. Then Add this line to your maui csproj
<Project Sdk="Microsoft.NET.Sdk">
  ...
  <Import Project="Microsoft.Build.Msix.Packaging.MsixBundle.targets" />
</Project>
  1. Finally you can run the build command: dotnet build YourProject.csproj --configuration Release --framework net8.0-windows10.0.19041.0 /property:Version=2.3.22.9999 /t:GenerateMsixBundle

epsmae avatar Aug 28 '24 04:08 epsmae

@epsmae Have you tried a submission? We declare fullTrust and the app is not rejected / gets into the store without any problems

baaaaif avatar Aug 28 '24 06:08 baaaaif

@baaaaif no I have not yet submitted it, as I have read that this will be declined (don't find the link right now). It is also a bit strange that the app shows the "Warning" requires full trust on installation. This probably will make the users curious why the app from one day to the other requires that.

epsmae avatar Aug 28 '24 08:08 epsmae

@baaaaif no I have not yet submitted it, as I have read that this will be declined (don't find the link right now). It is also a bit strange that the app shows the "Warning" requires full trust on installation. This probably will make the users curious why the app from one day to the other requires that.

yes, in the past that was a problem and apps were rejected. But not necessarily, you just had to state why you were using fullTrust and the apps could then be approved. But it shouldn't be a problem anymore, as I said, we use it without any problems

baaaaif avatar Aug 28 '24 08:08 baaaaif

@baaaaif Cool, thanks for the Feedback.

epsmae avatar Aug 29 '24 05:08 epsmae

@epsmae thanks so much for the reply. Unfortunately when I use dotnet publish or dotnet build I still get a .msixbundle instead of a .msixupload. Also, the package is 4 times the size at 240MB of our Xamarin.Forms package. I was using --self-contained but tried without and it only decrease by 80MB. We used to use the following to build Xamarin.Forms Windows UWP:

-nologo -nr:false -p:AppxBundle=Always;UapAppxPackageBuildMode=StoreUpload;AppxBundlePlatforms="x86|x64";AppxPackageDir=".\AppPackages";platform="x86";configuration="QATest";VisualStudioVersion="16.0"

If we're delivering this to the Microsoft store do we need to use --self-contained? We did that for internal builds because we got some message upon install that they needed to download .Net runtime or something to that effect.

mnxamdev avatar Sep 13 '24 22:09 mnxamdev

I am able to successfully create a '.msixbundle' file from dotnet but I am still having issues producing a '.msixupload' file despite following @mattleibow instructions. Can someone who has successfully produced a '.msixupload' file, on MAUI, please elaborate? Thanks

@sorrybomber were you able to find a way to generate a '.msixupload' file to be able upload to the Microsoft Store? We're getting to release and I feel like I'm about to tell management that after all our work to start on this endeavor we won't be able to release.

I just had to do this myself. Is there any update if they will introduce bundle generation in MAUI? We can't update our App if it isn't a bundle...

dsl9734 avatar Sep 16 '24 15:09 dsl9734

@mnxamdev you need to use self contained otherwise it gets rejected something like "requires an external dependency to .net". The size for me is also quite high around 260MB, I did also not do any attempt to strip it down.

I also get an .msixbundle but this is fine, you can use that to upload to the store.

epsmae avatar Oct 01 '24 05:10 epsmae

I just recently successfully got a .NET MAUI Blazor Hybrid app approved through the Microsoft Store.

I had to publish as self-contained and bundle the Windows App SDK.

Here is the publish command I used that successfully created an .msix file that produced a self-contained app (includes the .NET runtime) and bundled the Windows App SDK:

dotnet publish -f net8.0-windows10.0.19041.0 -c Release --self-contained -p:RuntimeIdentifierOverride=win10-x64 -p:WindowsAppSDKSelfContained=true -p:WindowsPackageType=MSIX

Upon submission it did request why I am using Full Trust and I used the following as my explanation:

  • The app is written as a .NET MAUI Blazor Hybrid app and requires full trust to integrate Blazor UI with native Windows APIs and WebView2.

randyburden avatar Oct 17 '24 19:10 randyburden

.msixupload is just a zip archive of .msixbundle + .appxsym (optional).

You can use this PowerShell command to create .msixupload:

Compress-Archive -Path "pathToProject/bin/Release/*windows*/*.msixbundle" -DestinationPath "StoreUpload.msixupload" -CompressionLevel "NoCompression" -Force

If you also need .appxsym file for crash analytics, read here https://stackoverflow.com/a/79323816/7874032

alexlogvin avatar Jan 02 '25 13:01 alexlogvin