fyne-io / fyne

Cross platform GUI toolkit in Go inspired by Material Design
https://fyne.io/
Other
24.66k stars 1.37k forks source link

Failed to uplaod .appx packaged file to Microsoft Store #3742

Open milkcoke opened 1 year ago

milkcoke commented 1 year ago

Checklist

Describe the bug

appxmanifest.xml

I made .appx package using fyne release CLI

This is example generated appxmanifest.xml on packaging processing

<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest">
    <Identity Name="{{.AppID}}"
              Version="{{.Version}}"
              Publisher="{{.Developer}}" />
    <Properties>
        <DisplayName>{{.Name}}</DisplayName>
        <PublisherDisplayName>{{.DeveloperName}}</PublisherDisplayName>  <!-- ⚠️ 1. Error occurs here -->
        <Logo>Icon.png</Logo>
    </Properties>
    <Prerequisites>
        <OSMinVersion>6.0</OSMinVersion> <!-- ⚠️ 2. Error occurs here -->
        <OSMaxVersionTested>10.0</OSMaxVersionTested>
    </Prerequisites>
    <Resources>
        <Resource Language="en-us" />
    </Resources>

    <!-- <Applications>  ⚠️ 3. Error occurs-->
</Package>

1. PublisherDisplayName is not correct

In appxmanifest.xml is generated on release processing and which is deleted after .appx file is generated. However, PublisherDisplayName is determined on this code This format is forced to "CN={value}" but we just only input CLI the -developer CN=${value}, value is not the same of PublisherName in taht Microsoft store defined.

release.go

func (r *Releaser) nameFromCertInfo(info string) string {
    // format should be "CN=Company, O=Company, L=City, S=State, C=Country"
    parts := strings.Split(info, ",")
    cn := parts[0]
    pos := strings.Index(strings.ToUpper(cn), "CN=") // Just parse CN={value} but value is not the same in microsoft store defined. So error occurs.
    if pos == -1 {
        return cn // not what we were expecting, but should be OK
    }

    return cn[pos+3:]
}

2. OS Minversion is always 6.0

This is not changed on CLI, hardcoded as 6.0

3. tag is not defined

How to modify the tag information? that tag is required.

How to reproduce

CLI command

I try to packaging with the command

$ fyne release --target windows \
--appVersion 1.0.0 --appBuild 1 \
--appID [My-App-ID] \
--name [My-App-Name]
--icon [My-App-Icon-Path]
--developer "CN=[MyProductPublisherID]"  // ⚠️ Error occurs here too
--certificate [My-pfx-file]
-password [My-Password]

From this, generated .xml file is not appropriate to register on Microsoft Store as app package file

Screenshots

Product identity

Name, Publisher, PublisherDisplayName are already defiend , this is guided on Microsoft Partner Center > Apps and games > MyProduct image

Screenshots to upload .appx file

package_error_log

Example code

Refer to this code

There's no processing about <Application> tag And it seems that microsoft store .appx, .msix package just allow program entrypoint as C#, VisualBasic..

// ..
manifestData := struct{ AppID, Developer, DeveloperName, Name, Version string }{
  AppID: r.AppID,
  Developer:     r.developer,
  DeveloperName: r.nameFromCertInfo(r.developer), // ⚠️ here is problem
  Name:          r.Name,
  Version:       r.combinedVersion(),
}
err = templates.AppxManifestWindows.Execute(manifest, manifestData)
manifest.Close()
if err != nil {
  return errors.New("failed to write application manifest template")
}

// ..
util.CopyFile(r.icon, filepath.Join(payload, "Icon.png"))
util.CopyFile(r.Name, filepath.Join(payload, r.Name))

Fyne version

2.3.1

Go compiler version

1.20.1

Operating system and version

Windows 10

Additional Information

I tried many ways for publish my app on Microsoft store. However It seems that just C# , Visua basic program can be registerd succesfully on there.

This is the sample of AppxManifest.xml provided by Visual Studio.

<?xml version="1.0" encoding="utf-8"?>

<Package
  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
  xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
  IgnorableNamespaces="uap rescap">

  <Identity
    Name="[My App Name]"
    Publisher="CN=[My Publisher ID]"
    Version="1.0.0.0" />

  <Properties>
    <DisplayName>My App</DisplayName>
    <PublisherDisplayName>My Name</PublisherDisplayName>
    <Logo>Images\app_icon.png</Logo>
  </Properties>

    <Dependencies>
                <!-- also, MinVersion is just hard coded as 6.0.0.0 -->
        <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.0.0" MaxVersionTested="10.0.14393.0" />
    </Dependencies>

  <Resources>
    <Resource Language="x-generate" />
  </Resources>

  <Applications>
    <Application Id="App"
      Executable="$targetnametoken$.exe"
      EntryPoint="MyApp.App"> <!-- ⚠️ Here is also problem since EntryPoint is just allowed 'Main' method of C# -->
      <uap:VisualElements
        DisplayName="[My App]"
        Description="[My App Description]"
        BackgroundColor="transparent"
        Square150x150Logo="Images\Square150x150Logo.png"
        Square44x44Logo="Images\Square44x44Logo.png">
        <uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png" >
          <uap:ShowNameOnTiles>
            <uap:ShowOn Tile="square150x150Logo"/>
          </uap:ShowNameOnTiles>
        </uap:DefaultTile >
        <uap:SplashScreen Image="Images\SplashScreen.png" />
        <uap:LockScreen BadgeLogo="Images\BadgeLogo.png" Notification="badge"/>
      </uap:VisualElements>
    </Application>
  </Applications>

  <Capabilities>
    <Capability Name="internetClient" />
    <rescap:Capability Name="runFullTrust" />
  </Capabilities>
</Package>

I tried input main (go program) but it failed. Visual studio logging error as shown below image

It should be Main of C# (I guess)

Please confirm this process. That must be outdated. And is there any other solution? for packaging file for uploading microsoft store?

Bluebugs commented 1 year ago

Thanks for all the details. I was just wondering if you had tried to modify the AppxManifest.xml that is bundled in Fyne to match the more up to date one from Visual Studio? I would expect that we should be able to have things working if we add the tag and specify main as the EntryPoint along with fixing the parsing of the developers info.

milkcoke commented 1 year ago

@Bluebugs

Respond your question

I guess you ask me if would I modify the appxmanifest.xml file and re-package it using MakeApp.exe? No, I didn't modify appmanifest.xml file from generated .appx by fyne release. When I unpackage the .appx file , there's a appxmanifest.xml file in ProgramFiles/WindowsApps the first appxmanifest.xml example is it.

Microsoft store requires upload .appx or .msix file.

Describe What I tried

I tried to modify AppxManifest.xml manually in my visual studio which refer to fyne application as executable file and entrypoint

last AppxManifest.xml example provided by Visual Studio is mine I stuck on this issue image

My Idea

If there's no way set entrypoint main of golang instead of C#, Visual Basic I'm thinking about making simple C# program including Main to execute MyApplication.exe file generated by fyne package. It seems not good approach though.

Bluebugs commented 1 year ago

If you can manage to get a working xml file, I will be able to quickly make a patch for fyne. So helping on figuring out what work would be great.

My idea is that you should update Executable="$targetnametoken$.exe" with the name of your executable and should likely just be EntryPoint="main" (notice all lower case). I would expect that the store does handle C and C++ application which use also main as the entry point.

milkcoke commented 1 year ago

I'm using Visual Studio 2022 (Community)

File > New > Project from Existing code as shown below image

So I could do import (references) wrapping go fyne project as C# project. I set Executable=MyExeFileName.exe in my application project root. But CS5001 : Program does not contain a static 'Main' method suitable for an entry point

Package.appxmanifest.xml

image

Program.cs

public class Program
{
// Nothing to do, just for providing EntryPoint
    static void Main() { }
}

I tried to execute the file , It succeed to execute but there's problem. MyApp.exe generated by go + fyne build is not executed. instead, just static void Main(){} code is executed not doing anything. It seems allowing just Executable file is mapped Generated by EntryPoint Main of C#. So I failed to execute my fyne application file. Please refer to this docs

I'm finding any other way in the static Main of C# executing MyApp.exe . Thank your fast response.

andydotxyz commented 1 year ago

I'm not sure why this is so broken - it did work in the past when I wrote the packager and the docs for the book. I wonder if the wrong tag is being used, C apps won't allow a custom entry point and by adding a C# app all you're doing is providing a no-op main function so the app packages, but it won't run the code from the other executable.

I can't figure out what has changed.

andydotxyz commented 1 year ago

It seems allowing just Executable file is mapped Generated by EntryPoint Main of C#. So I failed to execute my fyne application file. Please refer to this docs

That error / doc refers to the C# compiler, not the packaging format...

andydotxyz commented 1 year ago

Yup, the Application manifest requirement of Executable+EntryPoint (or StartPage) is a UWP thing. We need to refer to docs for the C/C++ app manifests.

milkcoke commented 1 year ago

OK, I'm going to try packaging with C++/WinRT application this weekend.

I succeed to execute my fyne application file (.exe) in my C# project UWP configuration as shown below.

using System;
using System.IO;
using System.Diagnostics;

public class Program
{
    static void Main() {
        string currentDirectory = Directory.GetCurrentDirectory();
        Console.WriteLine("Current directory: " + currentDirectory);

        string exePath = Path.Combine(currentDirectory, "MyFyneApp.exe");

        Console.WriteLine("exe path: " + exePath);
        // Start a new process using the specified .exe file
        ProcessStartInfo startInfo = new ProcessStartInfo(exePath);
        Process process = new Process();
        process.StartInfo = startInfo;
        process.Start();

        //Wait for the process to exit

        process.WaitForExit();

        //Display the exit code of the process
        Console.WriteLine("Exit code: " + process.ExitCode);
    }
}

This is not good approach though, We must find anyway!

andydotxyz commented 1 year ago

Thanks for looking into this, but you're right we need to find the metadata that will run the app without a runner app included.

andydotxyz commented 1 year ago

It seems Microsoft provided a response (fairly basic) - which confirms it should be possible with just the .exe file.

https://learn.microsoft.com/en-us/answers/questions/1194907/how-to-packaging-windows-app-for-submitting-micros?cid=kerryherger

They link to doc page https://learn.microsoft.com/en-us/windows/apps/publish/publish-your-app/create-app-submission?pivots=store-installer-msi-exe

milkcoke commented 1 year ago

Hello @andydotxyz , Your link is mine.. that was my question you suggest linked.

I succeed publish my app on microsoft store as .exe package. However it's not good solution.

I've tried many ways for packaging this app on microsoft store. I describe what's the problem and What I've tired resolving this problem.

Youtube link

https://youtu.be/UOBjJCvV_X4

Toolbox Dev beta version

https://apps.microsoft.com/store/detail/XP99Z5LSQPTS2F

I'll wait your response. I need your help.

andydotxyz commented 1 year ago

Your link is mine.. that was my question you suggest linked.

Yes indeed, but as it was not linked to this issue I wanted to mention it for whoever works on this ticket.

milkcoke commented 1 year ago

I succeed packaging my golang + fyne.io application as .msix and .appx both. And publishing on Microsoft Store. There's 5 points we need packaging using fyne.io application for windows desktop application. I didn't try any other device or platform.

1. Packaging Format

I recommend .appx or .msix. index msix appx
Platform Multiplatform
(xbox, VR device, desktop, windows mobile)
Only for Windows 10 newer
Running on Container Container
Install Folder %ProgramFiles%\WindowsApps %ProgramFiles%\WindowsApps

Tips for choice

Format conclusion.

If you want to support your app for other devices use .msix or just for windows desktop? choose .appx

2. tag

Current fyne release command doesn't support making Applications tag . This tag is for providing entrypoint of your application after installation is complete. If you doesn't Set <Application> tag on appxmanifest.xml, Even if install completes, app is not searched on your computer because it doesn't know what's the entry point. In fact, without application tag, your package should be installed on %ProgramFiles%\WindowsApps with .exe file build by fyne.io but it can't be accessed without entrypoint although you have administrator

image Without this tag, Can't be launched since application file is not found on your computer.

How to figure Application tag on appxmanifest.xml?

In current version (fyne 2.3.x), You should configure appxmanifest.xml. It doesn't make Application tag for you.

Example appxmanifest.xml

<?xml version="1.0" encoding="utf-8"?>
<Package
        xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
        xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
        xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
        IgnorableNamespaces="rescap uap">

    <Identity
            Name="<MicrosoftStore Developer  Product ID>"
            Publisher="<Microsoft Developer Publisher ID>"
            Version="<Your version>"
            ProcessorArchitecture="x64"/>

    <Properties>
        <DisplayName>Dev Toolbox</DisplayName>
        <PublisherDisplayName><Microsoft Developer Publisher DisplayName></PublisherDisplayName>
        <Logo>{Your logo file}</Logo>
    </Properties>

    <Dependencies>
        <!-- if package type is .msix MinVersion must be > 10.17134.0 (October 2018) -->
        <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.22621.0" />
    </Dependencies>

    <Resources>
        <Resource Language="en-us"/>
    </Resources>

    <Applications>
        <Application Id="<AppID> (Don't use spacebar)" Executable="<.exe file build on golang + fyne io in package directory>" EntryPoint="Windows.FullTrustApplication">
<!-- VisualElements tag is also required -->
            <uap:VisualElements DisplayName="<Shown on your application on desktop>" Description="<Your description>" BackgroundColor="#000000"
                                Square44x44Logo="images\app_icon_44.png" Square150x150Logo="images\app_icon_150.png">
                <uap:DefaultTile Square71x71Logo="images\app_icon_71.png">
                    <uap:ShowNameOnTiles>
                        <uap:ShowOn Tile="square150x150Logo"/>
                    </uap:ShowNameOnTiles>
                </uap:DefaultTile>
            </uap:VisualElements >
        </Application>
    </Applications>

    <Capabilities>
<!-- This is optional tag, I'm using internet client (download) -->
        <Capability Name="internetClient" />
<!-- This is required tag for supporting win32 app , fyne io is win32 app default.-->
        <rescap:Capability Name="runFullTrust" />
    </Capabilities>
</Package>

Check on you microsoft > app and games > Product ID

image

3. Certificate

You should get developer certificate from microsoft . I recommend get it from Visual Studio. When you install visual studio it maybe install windows 10 SDK, and 11 SDK with MakeAppx and signtool for packaging, signing.

Package.appxmanifest

image

  1. Connect on your developer account on visual studio. It automatically show self-signed certificate for you.
  2. Choose from store
  3. Click View full certificate
  4. Export as file (.pfx) for input command line of fyne
  5. Install on Trusted Root Certificate Authorities

image

Also, there's many guide for CLI for getting certificates. refer to this docs

4. Packaging and Sigining

It seems that current fyne release command has error for makeappx path finding. I executed manually makeappx and signtool command.

At first, prepare your package directory like as shown below image

# you can also packaging with .appx
$ makeappx pack -d [your package directory] /p [package-name].msix
# signing with your certificate (.pfx or .cer)
$ signtool sign /a /v /fd SHA256 /f [certificate file] /p [Certificate Password] [Package file path created above]

Done! You can upload your .appx or .msix for submitting on Microsoft Store!

Conclusion.

In current, users should configure package directory with appxmanifest.xml and icon, exe file build on golang and fyne.io

image

I got this helping @andydotxyz . Thanks.

I expect developing fyne release and package process according to required feature of microsoft store. I'll be the first man of publisher using this fyne.io!!!