dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.04k stars 1.73k forks source link

Publish Windows, AppStore Bundle (.msixupload) missing #22445

Open epsmae opened 4 months ago

epsmae commented 4 months ago

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

github-actions[bot] commented 4 months ago

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.

jaosnz-rep commented 4 months ago

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.

baaaaif commented 4 months ago

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 (win10-x64) does not work in my case with win10-x64;win10-arm64

@mattleibow (tagging you because of your comment with workaround in [12327](https://github.com/dotnet/maui/issues/12327) 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 commented 4 months ago

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

jsuarezruiz commented 3 months ago

@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?

epsmae commented 3 months ago

@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.

sorrybomber commented 2 months ago

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

mnxamdev commented 1 month ago

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 commented 1 month ago

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.

epsmae commented 1 month ago

@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>
  2. 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

baaaaif commented 1 month ago

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

epsmae commented 1 month ago

@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.

baaaaif commented 1 month ago

@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

epsmae commented 1 month ago

@baaaaif Cool, thanks for the Feedback.

mnxamdev commented 2 weeks ago

@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.

dsl9734 commented 2 weeks ago

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...

epsmae commented 1 day ago

@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.