tis-microsoft-desktopappinstaller

2021.1207.203.0-64
Microsoft App Installer for Windows 10 makes sideloading Windows 10 apps easy: Just double-click the app package, and you won't have to run PowerShell to install apps
5166 téléchargements
Télécharger
Voir le résultat de la construction Voir l'analyse de VirusTotal
tis-microsoft-desktopappinstaller icon
  • package : tis-microsoft-desktopappinstaller
  • name : App Installer
  • version : 2021.1207.203.0-64
  • categories : System and network
  • maintainer : WAPT Team,Tranquil IT,Jimmy PELÉ
  • editor :
  • licence : opensource_free,cpe:/a:mit:x11_license,wapt_public
  • locale : all
  • target_os : windows
  • impacted_process : AppInstaller,winget
  • architecture : all
  • signature_date : 2025-07-29 13:03
  • size : 26.16 Mo
  • installed_size : 149.58 Mo
  • homepage : https://github.com/microsoft/winget-cli#installing-the-client
package           : tis-microsoft-desktopappinstaller
version           : 2021.1207.203.0-64
architecture      : all
section           : base
priority          : optional
name              : App Installer
categories        : System and network
maintainer        : WAPT Team,Tranquil IT,Jimmy PELÉ
description       : Microsoft App Installer for Windows 10 makes sideloading Windows 10 apps easy: Just double-click the app package, and you won't have to run PowerShell to install apps
depends           : 
conflicts         : 
maturity          : PROD
locale            : all
target_os         : windows
min_wapt_version  : 2.3
sources           : https://apps.microsoft.com/store/detail/9NBLGGH4NNS1
installed_size    : 149576976
impacted_process  : AppInstaller,winget
description_fr    : 
description_pl    : 
description_de    : 
description_es    : 
description_pt    : 
description_it    : 
description_nl    : 
description_ru    : 
audit_schedule    : 
editor            : 
keywords          : winget,microsoft,easy,app,apps,installer,windows,sideloading,windows10,windows11
licence           : opensource_free,cpe:/a:mit:x11_license,wapt_public
homepage          : https://github.com/microsoft/winget-cli#installing-the-client
package_uuid      : 841b3d08-30f2-4169-ba0e-90bc9ff0d060
valid_from        : 
valid_until       : 
forced_install_on : 
changelog         : 
min_os_version    : 10.0.17763
max_os_version    : 
icon_sha256sum    : fb211ca16725f640fc2e7454304f2c4da34edb3483d3065ea8c08758828ba9e7
signer            : Tranquil IT
signer_fingerprint: 8c5127a75392be9cc9afd0dbae1222a673072c308c14d88ab246e23832e8c6bb
signature_date    : 2025-07-29T13:03:07.000000
signed_attributes : package,version,architecture,section,priority,name,categories,maintainer,description,depends,conflicts,maturity,locale,target_os,min_wapt_version,sources,installed_size,impacted_process,description_fr,description_pl,description_de,description_es,description_pt,description_it,description_nl,description_ru,audit_schedule,editor,keywords,licence,homepage,package_uuid,valid_from,valid_until,forced_install_on,changelog,min_os_version,max_os_version,icon_sha256sum,signer,signer_fingerprint,signature_date,signed_attributes
signature         : BN0Rhx9guJyUGWymfnysn2c7rAs1yqre0ROspwCN1Iluz1pAoKtT2SjIFOt2oHmDKNdW3oqK1IF3zl462YxDc2ZbbX8T+pEjbmuv7q4Zk88X3ZiKvTwmsmrkaJl3plJCsWEpimyQxaRKUI5CjkERk42XrDEiuIBQ6ECa9xHE9gUrc4KfhdHsMHshcbbMgdxnM+zL8M4Z48fsmb8901FdZUqXDxAP4uU9I6vJAh3weZddllMHC8sSQhxYxXHt7a+JswCNRKfvhWJnzurRteJJJHIQ83fiWxt1LE76SoOseNZI31ZrJjlNvT2JkRMDAX5OiQvKw6TkS+aCO9z5xYk3+A==
# -*- coding: utf-8 -*-
from setuphelpers import *


appx_package_name = "Microsoft.DesktopAppInstaller"
appx_dir = makepath(programfiles, "WindowsAppsInstallers")


def install():
    # Declare local variables
    bins_dir = control.package.split("-", 1)[1]
    old_appx_bins_dir = makepath(appx_dir, bins_dir)
    appx_bins_dir = makepath(os.getcwd(), bins_dir)

    # Removing sources because they are no longer needed
    if isdir(old_appx_bins_dir):
        print("Removing: %s" % (old_appx_bins_dir))
        remove_tree(old_appx_bins_dir)
    if dir_is_empty(appx_dir):
        print("Removing: %s since it is empty" % (appx_dir))
        remove_tree(appx_dir)

    # Removing binaries of different architectures
    for f in glob.glob(appx_bins_dir + "/*"):
        fname = f.split(os.sep)[-1]
        if control.architecture == "all":
            if "x86" in glob.glob(makepath(appx_bins_dir, f"{appx_package_name}_*"))[0].split(os.sep)[-1]:
                if not "x86" in fname and not "neutral" in fname:
                    remove_file(f)
            else:
                if not get_host_architecture() in fname and not "neutral" in fname:
                    remove_file(f)
        else:
            if not get_host_architecture() in fname and not "neutral" in fname:
                remove_file(f)
    bin_path = glob.glob(makepath(appx_bins_dir, f"{appx_package_name}_*"))[0]
    dependencies_pathes = ",".join([f'"{a}"' for a in glob.glob(makepath(appx_bins_dir, "*")) if not appx_package_name in a])
    add_appx_cmd = f'Add-AppxProvisionedPackage -Online -PackagePath "{bin_path}" -SkipLicense'
    if dependencies_pathes:
        add_appx_cmd += f" -DependencyPackagePath {dependencies_pathes}"

    # Installing the UWP application if needed
    appxprovisionedpackage = run_powershell(f'Get-AppXProvisionedPackage -Online | Where-Object DisplayName -Like "{appx_package_name}"')
    if appxprovisionedpackage is None:
        remove_appx(appx_package_name, False)
        appxprovisionedpackage = {"Version": "0"}
    elif force:
        uninstall()
    if Version(appxprovisionedpackage["Version"], 4) < Version(control.get_software_version(), 4):
        print(f"Installing: {bin_path.split(os.sep)[-1]} ({control.get_software_version()})")
        killalltasks(ensure_list(control.impacted_process))
        run_powershell(add_appx_cmd, output_format="text")
    else:
        print(f'{appxprovisionedpackage["PackageName"]} is already installed and up-to-date.')


def uninstall():
    if windows_version() < WindowsVersions.Windows11:  # seems not removable on W11
        print(f"Removing AppX: {appx_package_name}")
        remove_appx(appx_package_name)


def audit():
    # Declaring local variables
    audit_result = "OK"
    audit_version = True
    appxprovisionedpackage = run_powershell(f'Get-AppXProvisionedPackage -Online | Where-Object DisplayName -Like "{appx_package_name}"')

    # Auditing software
    if appxprovisionedpackage is None:
        print(f"{appx_package_name} is not installed.")
        audit_result = "ERROR"
    elif audit_version:
        if Version(appxprovisionedpackage.get("Version", "0"), 4) < Version(control.get_software_version(), 4):
            print(
                f'{appxprovisionedpackage["PackageName"]} is installed in version: {appxprovisionedpackage["Version"]} instead of: {control.get_software_version()}.'
            )
            audit_result = "WARNING"
        else:
            print(f'{appxprovisionedpackage["PackageName"]} is installed and up-to-date.')
    else:
        print(f'{appxprovisionedpackage["PackageName"]} is installed.')

    return audit_result


def remove_appx(package, default_user=True):
    """Remove Windows AppX package from the computer environment, excluding NonRemovable packages.

    Args:
        package (str): AppX package name. You can use an asterisk (*) as a wildcard.
        default_user (bool): Remove AppX package from the Windows image to prevent installation for new users.

    .. versionchanged:: 2.5
        No longer try to remove NonRemovable AppX package

    .. versionchanger:: 2.6
        No longer use run_powershell for uninstall
    """
    
    if running_as_admin() or running_as_system():
        if default_user:
            ps_script = f'Get-AppXProvisionedPackage -Online | Where-Object DisplayName -Like ""{package}"" | Remove-AppxProvisionedPackage -Online -AllUsers'
            run_powershell_script(ps_script, output_format="text")

        ps_script = f'Get-AppxPackage -Name ""{package}"" -AllUsers | Where-Object -property NonRemovable -notlike True | Remove-AppxPackage -AllUsers'
        run_powershell_script(ps_script, output_format="text")

    else:
        ps_script = f'Get-AppxPackage -Name ""{package}"" | Where-Object -property NonRemovable -notlike True | Remove-AppxPackage'
        run_powershell_script(ps_script, output_format="text")
# -*- coding: utf-8 -*-
from setuphelpers import *
import requests

try:
    from setupdevhelpers import *
except:
    from bs4 import BeautifulSoup
import json
import waptguihelper
import html
from xml.dom import minidom
from requests import Session
import requests
import json
import re

release_name_map = {"retail": "Retail", "RP": "Release Preview", "WIS": "Insider Slow", "WIF": "Insider Fast"}
release_type = "retail"
release_name = release_name_map[release_type]
arch = "x64"
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
import xmltodict


def update_package():
    # Declaring local variables
    package_updated = False
    proxies = get_proxies()
    if not proxies:
        proxies = get_proxies_from_wapt_console()
    store_url = control.sources
    if not store_url:
        store_id = waptguihelper.input_dialog(
            "Choice of app", "Enter the windows store app id (foundable in package url: https://apps.microsoft.com/store/apps)", store_url
        ).split("/")[-1]
    else:
        store_id = store_url.split("/")[-1]
    store_id = store_id.split("?")[0]
    url_ms = "https://apps.microsoft.com/store/detail/%s" % store_id
    control.sources = url_ms
    control.save_control_to_wapt()
    package_prefix = control.package.split("-")[0]
    package_json = get_json(store_id)
    
    all_files_dict = get_all_files(store_id)
    
	# check setup.py incase the package name doesnt match the installer file
    with open("setup.py", "r") as f:
        for line in f.readlines():
            if line.startswith("appx_package"):
                store_package_name = line.split("=")[1].split('"')[1]
                break
    
    bin_selected_dict = ask_app_filename(all_files_dict, store_package_name)
    appx_package = bin_selected_dict[0]["bin_name"].split("_")[0]
    bin_selected = bin_selected_dict[0]
    latest_bin = bin_selected["bin_name"]
    version = bin_selected["version"]
    download_url = bin_selected["download_url"]
    package_name = bin_selected["package_name"]
    software_name = bin_selected["software_name"]
    package_arch = bin_selected["package_arch"]
    if download_url.split("/")[2].endswith("microsoft.com"):
        if not isfile(latest_bin):
            print("Downloading: %s" % latest_bin)
            wget(download_url, latest_bin, proxies=proxies)
        else:
            print("Binary file version corresponds to online version")
    else:
        print("ERROR: The retrieved url will not download from microsoft's servers")

    # # Adding dependencies
    # control.depends = ""
    # for dependency in list(set(d["package_name"] for d in all_files)):
    #     if dependency not in control.depends and package_name != dependency:
    #         control.add_depends(dependency)

    # Warn end-user that depencies are required
    # missing_depends = []
    # for d in control.depends.split(","):
    #     if not WAPT.is_available(d) and d != "":
    #         missing_depends.append(d)
    # if missing_depends and "template" in control.package:
    #     waptguihelper.message_dialog(
    #         control.package,
    #         'The following packages are not found in your repo, you must import them or use "template-microsoft-store-dependency" to create them with the same Store ID as this package\n\n%s'
    #         % "\n".join(a for a in missing_depends),
    #     )

    # Asking pkg infos if needed
    ask_control_categories()
    control.architecture = package_arch
    ask_control_package(package_name, "template-microsoft-store", remove_base_files=True)
    ask_control_name(software_name, "Template Microsoft Store")
    # description from microsoft website
    ask_control_description("update_package", get_description(package_json))

    # Changing setup.py appx_package variable
    new_lines = []
    with open("setup.py", "r") as f:
        for line in f.readlines():
            if line.startswith("appx_package"):
                line = 'appx_package_name = "%s"\n' % latest_bin.split("_")[0]
            new_lines.append(line)
    with open("setup.py", "w") as f:
        f.writelines(new_lines)

	# Keep app files
    uwp_app_dict = make_uwp_app_dict(appx_package)
    if not uwp_app_dict:
        # error(f'{appx_package_name} not found in "uwp_app_dict".\n\n{list(set([ua["bin_name"].split("_")[0] for ua in all_files]))}')
        error(f'"{appx_package}" not found in "uwp_app_dict". This is probably caused by "package_json" filters:\n{package_json}')
    newer_uwp_app = get_newer_uwp_app(uwp_app_dict)
    version = newer_uwp_app["Version"]

    # Downloading dependency files
    dependencies_to_download = []
    if newer_uwp_app["Dependencies"]:
        for dependency in newer_uwp_app["Dependencies"]:
            dependencies_to_download.append(get_newer_uwp_depency(dependency, all_files_dict, min_version=dependency["MinVersion"]))
    if dependencies_to_download:
        for dependency_file in all_files_dict:
            latest_bin = dependency_file["bin_name"]
            if False in [d in latest_bin for d in dependencies_to_download]:  # ignore unecessary dependencies
                continue
            if not "all" in ensure_list(control.architecture):
                if not get_uwp_filename_arch(latest_bin) in ensure_list(control.architecture) and not "neutral" in latest_bin:
                    if isfile(latest_bin):
                        remove_file(latest_bin)
                    continue
            if latest_bin.split(".")[-1].lower().startswith("e"):  # ignore encrypted uwp apps
                continue
            download_url = dependency_file["download_url"]
            if download_url.split("/")[2].endswith("microsoft.com"):
                if not isfile(latest_bin):
                    print("Downloading: %s" % latest_bin)
                    wget(download_url, latest_bin, proxies=proxies)
                else:
                    print("Binary is present: %s" % latest_bin)
            else:
                error("ERROR: The retrieved URL will not download from microsoft's servers")

    # Changing version of the package
    if Version(version) > Version(control.get_software_version()):
        print("Software version updated (from: %s to: %s)" % (control.get_software_version(), Version(version)))
        package_updated = True
    else:
        print("Software version up-to-date (%s)" % Version(version))
    control.set_software_version(version)
    control.save_control_to_wapt()

    # Placing binaries in a dir ["appxbundle", "msixbundle", "appx", "msix]
    for f in glob.glob("*.part"):
        remove_file(f)
    bins_dir = control.package.split("-", 1)[1]
    if isdir(bins_dir):
        remove_tree(bins_dir)
    mkdirs(bins_dir)
    for uwp_file in glob.glob(f'{newer_uwp_app["Name"]}*{newer_uwp_app["Version"]}*.*'):
        if not isfile(makepath(bins_dir, uwp_file)):
            shutil.move(uwp_file, bins_dir)
    if uwp_app_dict[newer_uwp_app["FileName"]]["Dependencies"] is not None:
        for l in [glob.glob(a["Name"] + "_*") for a in uwp_app_dict[newer_uwp_app["FileName"]]["Dependencies"]]:
            for f in l:
                if not isfile(makepath(bins_dir, f)):
                    shutil.move(f, bins_dir)

    # Deleting outdated binaries
    remove_outdated_binaries(version, ["appxbundle", "msixbundle", "appx", "msix", "part"], latest_bin)

    # Validating or not update-package-sources
    return package_updated


def ask_control_description(blank_str=None, description_from_store=""):
    """Requesting that the user supply package description for the control.description field

    Args:
        blank_str   (str): The description will be cleared if it includes the specified string to avoid using the template description (default: do not clear description)
    """
    if not control.description:
        control.description = ask_dialog("Description", "Please fill the description", description_from_store)
        control.save_control_to_wapt()
    if blank_str is not None and blank_str in control.description:
        control.description = ""
        control.save_control_to_wapt()
    return control.description


def ask_control_categories():
    """Requesting that the user supply package categories for the control.categories field if empty or Template is selected"""

    if control.categories == "" or control.categories == "Template":
        categories = waptguihelper.grid_dialog(
            "Select package categories",
            [
                "Internet",
                "Utilities",
                "Messaging",
                "Security",
                "System and network",
                "Media",
                "Development",
                "Office",
                "Drivers",
                "Education",
                "Configuration",
                "CAD",
                "Template",
                "Dependencies",
                "Extensions",
            ],
            waptguihelper.GRT_SELECTED,
        )
        if categories:
            control.categories = ",".join([a["unknown"] for a in categories])
        else:
            control.categories = ""
        control.save_control_to_wapt()
    return control.categories


def ask_control_package(control_package, conditionnal_package_name=None, remove_base_files=False):
    """Requesting that the user provide a package name to be entered into the control.package field, and offering the possibility of removing the base files (icon.png and changelog.txt) for template package usage

    Args:
        control_package             (str)   : prefilled control_package (default: actual control_package)
        conditionnal_package_name   (str)   : only ask when the control.package contains conditionnal_package_name (default: always ask for control_package)
        remove_base_files           (bool)  : removes base files if parameter is True and conditionnal_package_name is provided (default: False)
    """
    if conditionnal_package_name is None or conditionnal_package_name in control.package:
        control.package = waptguihelper.input_dialog(control.package, "You can redefine the package name", control_package)
        control.save_control_to_wapt()

    # Removing template files
    if conditionnal_package_name in control.package and remove_base_files:
        if isfile("WAPT\\changelog.txt"):
            remove_file("WAPT\\changelog.txt")
        if isfile("WAPT\\icon.png"):
            remove_file("WAPT\\icon.png")
    return control.package


def ask_control_name(control_name, conditionnal_package_name=None):
    """Requesting that the user provide a package name to be entered into control.name field

    Args:
        control_name                (str)   : prefilled control_name (default: control.name)
        conditionnal_package_name   (str)   : only ask when the control.name contains conditionnal_package_name (default: always ask for control_name)
    """
    if conditionnal_package_name is None or conditionnal_package_name in control.name:
        control.name = waptguihelper.input_dialog(control.name, "You can redefine the name for the self-service", control_name)
        control.save_control_to_wapt()
    return control.name


def get_json(app_id):
    # download json from url and return it as dict
    url = "https://storeedgefd.dsx.mp.microsoft.com/v9.0/products/%s?market=US&locale=en-us&deviceFamily=Windows.Desktop" % app_id
    print(f"url used is {url}")
    dict = json.loads(requests.get(url).text)
    print(dict)
    return dict


def get_cat_id(dict):
    # get the category id from the dict, the ca_id is used to retrieve files names and url
    fullfillment_data_string = dict["Payload"]["Skus"][0]["FulfillmentData"]
    # transform fullfillment data to dict
    fullfillment_data_dict = json.loads(fullfillment_data_string)
    cat_id = fullfillment_data_dict["WuCategoryId"]
    return cat_id


def get_description(dict):
    # get the description from the dict
    return dict["Payload"]["Skus"][0]["Description"]


def get_min_os_version(dict):
    # get the min os version from the dict
    return dict["Payload"]["Skus"][0]["PackageRequirements"][0]["PlatformDependencies"][0]["MinVersion"]


def get_file_dict(app_id, user=""):
    # input app_id and user, return a dict with file names and url
    app_dict = get_json(app_id)
    cat_id = get_cat_id(app_dict)
    user = ""
    session = Session()

    print(f"Generating WSA download link: arch={arch} release_type={release_name}", flush=True)
    # get cookie from GetCookie.xml
    cookie_content = f"""
    <Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns="http://www.w3.org/2003/05/soap-envelope">
	<Header>
		<Action d3p1:mustUnderstand="1"
			xmlns:d3p1="http://www.w3.org/2003/05/soap-envelope"
			xmlns="http://www.w3.org/2005/08/addressing">http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService/GetCookie</Action>
		<MessageID xmlns="http://www.w3.org/2005/08/addressing">urn:uuid:b9b43757-2247-4d7b-ae8f-a71ba8a22386</MessageID>
		<To d3p1:mustUnderstand="1"
			xmlns:d3p1="http://www.w3.org/2003/05/soap-envelope"
			xmlns="http://www.w3.org/2005/08/addressing">https://fe3.delivery.mp.microsoft.com/ClientWebService/client.asmx</To>
		<Security d3p1:mustUnderstand="1"
			xmlns:d3p1="http://www.w3.org/2003/05/soap-envelope"
			xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
			<Timestamp xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
				<Created>2017-12-02T00:16:15.210Z</Created>
				<Expires>2017-12-29T06:25:43.943Z</Expires>
			</Timestamp>
			<WindowsUpdateTicketsToken d4p1:id="ClientMSA"
				xmlns:d4p1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
				xmlns="http://schemas.microsoft.com/msus/2014/10/WindowsUpdateAuthorization">
				<TicketType Name="MSA" Version="1.0" Policy="MBI_SSL">
					<user>{user}</user>
				</TicketType>
			</WindowsUpdateTicketsToken>
		</Security>
        </Header>
        <Body>
            <GetCookie xmlns="http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService">
                <oldCookie>
                </oldCookie>
                <lastChange>2015-10-21T17:01:07.1472913Z</lastChange>
                <currentTime>2017-12-02T00:16:15.217Z</currentTime>
                <protocolVersion>1.40</protocolVersion>
            </GetCookie>
        </Body>
    </Envelope>
    """

    out = session.post(
        "https://fe3.delivery.mp.microsoft.com/ClientWebService/client.asmx",
        data=cookie_content,
        headers={"Content-Type": "application/soap+xml; charset=utf-8"},
        verify=False,
    )
    doc = minidom.parseString(out.text)
    cookie = doc.getElementsByTagName("EncryptedData")[0].firstChild.nodeValue
    # get WUID from WUIDRequest.xml
    cat_id_content = f"""
    <s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing"
	xmlns:s="http://www.w3.org/2003/05/soap-envelope">
	<s:Header>
		<a:Action s:mustUnderstand="1">http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService/SyncUpdates</a:Action>
		<a:MessageID>urn:uuid:175df68c-4b91-41ee-b70b-f2208c65438e</a:MessageID>
		<a:To s:mustUnderstand="1">https://fe3.delivery.mp.microsoft.com/ClientWebService/client.asmx</a:To>
		<o:Security s:mustUnderstand="1"
			xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
			<Timestamp xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
				<Created>2017-08-05T02:03:05.038Z</Created>
				<Expires>2017-08-05T02:08:05.038Z</Expires>
			</Timestamp>
			<wuws:WindowsUpdateTicketsToken wsu:id="ClientMSA"
				xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
				xmlns:wuws="http://schemas.microsoft.com/msus/2014/10/WindowsUpdateAuthorization">
				<TicketType Name="MSA" Version="1.0" Policy="MBI_SSL">
					<user>{user}</user>
				</TicketType>
			</wuws:WindowsUpdateTicketsToken>
		</o:Security>
	</s:Header>
	<s:Body>
		<SyncUpdates xmlns="http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService">
			<cookie>
				<Expiration>2045-03-11T02:02:48Z</Expiration>
				<EncryptedData>{cookie}</EncryptedData>
			</cookie>
			<parameters>
				<ExpressQuery>false</ExpressQuery>
				<InstalledNonLeafUpdateIDs>
					<int>1</int>
					<int>2</int>
					<int>3</int>
					<int>11</int>
					<int>19</int>
					<int>544</int>
					<int>549</int>
					<int>2359974</int>
					<int>2359977</int>
					<int>5169044</int>
					<int>8788830</int>
					<int>23110993</int>
					<int>23110994</int>
					<int>54341900</int>
					<int>54343656</int>
					<int>59830006</int>
					<int>59830007</int>
					<int>59830008</int>
					<int>60484010</int>
					<int>62450018</int>
					<int>62450019</int>
					<int>62450020</int>
					<int>66027979</int>
					<int>66053150</int>
					<int>97657898</int>
					<int>98822896</int>
					<int>98959022</int>
					<int>98959023</int>
					<int>98959024</int>
					<int>98959025</int>
					<int>98959026</int>
					<int>104433538</int>
					<int>104900364</int>
					<int>105489019</int>
					<int>117765322</int>
					<int>129905029</int>
					<int>130040031</int>
					<int>132387090</int>
					<int>132393049</int>
					<int>133399034</int>
					<int>138537048</int>
					<int>140377312</int>
					<int>143747671</int>
					<int>158941041</int>
					<int>158941042</int>
					<int>158941043</int>
					<int>158941044</int>
					<int>159123858</int>
					<int>159130928</int>
					<int>164836897</int>
					<int>164847386</int>
					<int>164848327</int>
					<int>164852241</int>
					<int>164852246</int>
					<int>164852252</int>
					<int>164852253</int>
				</InstalledNonLeafUpdateIDs>
				<OtherCachedUpdateIDs>
					<int>10</int>
					<int>17</int>
					<int>2359977</int>
					<int>5143990</int>
					<int>5169043</int>
					<int>5169047</int>
					<int>8806526</int>
					<int>9125350</int>
					<int>9154769</int>
					<int>10809856</int>
					<int>23110995</int>
					<int>23110996</int>
					<int>23110999</int>
					<int>23111000</int>
					<int>23111001</int>
					<int>23111002</int>
					<int>23111003</int>
					<int>23111004</int>
					<int>24513870</int>
					<int>28880263</int>
					<int>30077688</int>
					<int>30486944</int>
					<int>30526991</int>
					<int>30528442</int>
					<int>30530496</int>
					<int>30530501</int>
					<int>30530504</int>
					<int>30530962</int>
					<int>30535326</int>
					<int>30536242</int>
					<int>30539913</int>
					<int>30545142</int>
					<int>30545145</int>
					<int>30545488</int>
					<int>30546212</int>
					<int>30547779</int>
					<int>30548797</int>
					<int>30548860</int>
					<int>30549262</int>
					<int>30551160</int>
					<int>30551161</int>
					<int>30551164</int>
					<int>30553016</int>
					<int>30553744</int>
					<int>30554014</int>
					<int>30559008</int>
					<int>30559011</int>
					<int>30560006</int>
					<int>30560011</int>
					<int>30561006</int>
					<int>30563261</int>
					<int>30565215</int>
					<int>30578059</int>
					<int>30664998</int>
					<int>30677904</int>
					<int>30681618</int>
					<int>30682195</int>
					<int>30685055</int>
					<int>30702579</int>
					<int>30708772</int>
					<int>30709591</int>
					<int>30711304</int>
					<int>30715418</int>
					<int>30720106</int>
					<int>30720273</int>
					<int>30732075</int>
					<int>30866952</int>
					<int>30866964</int>
					<int>30870749</int>
					<int>30877852</int>
					<int>30878437</int>
					<int>30890151</int>
					<int>30892149</int>
					<int>30990917</int>
					<int>31049444</int>
					<int>31190936</int>
					<int>31196961</int>
					<int>31197811</int>
					<int>31198836</int>
					<int>31202713</int>
					<int>31203522</int>
					<int>31205442</int>
					<int>31205557</int>
					<int>31207585</int>
					<int>31208440</int>
					<int>31208451</int>
					<int>31209591</int>
					<int>31210536</int>
					<int>31211625</int>
					<int>31212713</int>
					<int>31213588</int>
					<int>31218518</int>
					<int>31219420</int>
					<int>31220279</int>
					<int>31220302</int>
					<int>31222086</int>
					<int>31227080</int>
					<int>31229030</int>
					<int>31238236</int>
					<int>31254198</int>
					<int>31258008</int>
					<int>36436779</int>
					<int>36437850</int>
					<int>36464012</int>
					<int>41916569</int>
					<int>47249982</int>
					<int>47283134</int>
					<int>58577027</int>
					<int>58578040</int>
					<int>58578041</int>
					<int>58628920</int>
					<int>59107045</int>
					<int>59125697</int>
					<int>59142249</int>
					<int>60466586</int>
					<int>60478936</int>
					<int>66450441</int>
					<int>66467021</int>
					<int>66479051</int>
					<int>75202978</int>
					<int>77436021</int>
					<int>77449129</int>
					<int>85159569</int>
					<int>90199702</int>
					<int>90212090</int>
					<int>96911147</int>
					<int>97110308</int>
					<int>98528428</int>
					<int>98665206</int>
					<int>98837995</int>
					<int>98842922</int>
					<int>98842977</int>
					<int>98846632</int>
					<int>98866485</int>
					<int>98874250</int>
					<int>98879075</int>
					<int>98904649</int>
					<int>98918872</int>
					<int>98945691</int>
					<int>98959458</int>
					<int>98984707</int>
					<int>100220125</int>
					<int>100238731</int>
					<int>100662329</int>
					<int>100795834</int>
					<int>100862457</int>
					<int>103124811</int>
					<int>103348671</int>
					<int>104369981</int>
					<int>104372472</int>
					<int>104385324</int>
					<int>104465831</int>
					<int>104465834</int>
					<int>104467697</int>
					<int>104473368</int>
					<int>104482267</int>
					<int>104505005</int>
					<int>104523840</int>
					<int>104550085</int>
					<int>104558084</int>
					<int>104659441</int>
					<int>104659675</int>
					<int>104664678</int>
					<int>104668274</int>
					<int>104671092</int>
					<int>104673242</int>
					<int>104674239</int>
					<int>104679268</int>
					<int>104686047</int>
					<int>104698649</int>
					<int>104751469</int>
					<int>104752478</int>
					<int>104755145</int>
					<int>104761158</int>
					<int>104762266</int>
					<int>104786484</int>
					<int>104853747</int>
					<int>104873258</int>
					<int>104983051</int>
					<int>105063056</int>
					<int>105116588</int>
					<int>105178523</int>
					<int>105318602</int>
					<int>105362613</int>
					<int>105364552</int>
					<int>105368563</int>
					<int>105369591</int>
					<int>105370746</int>
					<int>105373503</int>
					<int>105373615</int>
					<int>105376634</int>
					<int>105377546</int>
					<int>105378752</int>
					<int>105379574</int>
					<int>105381626</int>
					<int>105382587</int>
					<int>105425313</int>
					<int>105495146</int>
					<int>105862607</int>
					<int>105939029</int>
					<int>105995585</int>
					<int>106017178</int>
					<int>106129726</int>
					<int>106768485</int>
					<int>107825194</int>
					<int>111906429</int>
					<int>115121473</int>
					<int>115578654</int>
					<int>116630363</int>
					<int>117835105</int>
					<int>117850671</int>
					<int>118638500</int>
					<int>118662027</int>
					<int>118872681</int>
					<int>118873829</int>
					<int>118879289</int>
					<int>118889092</int>
					<int>119501720</int>
					<int>119551648</int>
					<int>119569538</int>
					<int>119640702</int>
					<int>119667998</int>
					<int>119674103</int>
					<int>119697201</int>
					<int>119706266</int>
					<int>119744627</int>
					<int>119773746</int>
					<int>120072697</int>
					<int>120144309</int>
					<int>120214154</int>
					<int>120357027</int>
					<int>120392612</int>
					<int>120399120</int>
					<int>120553945</int>
					<int>120783545</int>
					<int>120797092</int>
					<int>120881676</int>
					<int>120889689</int>
					<int>120999554</int>
					<int>121168608</int>
					<int>121268830</int>
					<int>121341838</int>
					<int>121729951</int>
					<int>121803677</int>
					<int>122165810</int>
					<int>125408034</int>
					<int>127293130</int>
					<int>127566683</int>
					<int>127762067</int>
					<int>127861893</int>
					<int>128571722</int>
					<int>128647535</int>
					<int>128698922</int>
					<int>128701748</int>
					<int>128771507</int>
					<int>129037212</int>
					<int>129079800</int>
					<int>129175415</int>
					<int>129317272</int>
					<int>129319665</int>
					<int>129365668</int>
					<int>129378095</int>
					<int>129424803</int>
					<int>129590730</int>
					<int>129603714</int>
					<int>129625954</int>
					<int>129692391</int>
					<int>129714980</int>
					<int>129721097</int>
					<int>129886397</int>
					<int>129968371</int>
					<int>129972243</int>
					<int>130009862</int>
					<int>130033651</int>
					<int>130040030</int>
					<int>130040032</int>
					<int>130040033</int>
					<int>130091954</int>
					<int>130100640</int>
					<int>130131267</int>
					<int>130131921</int>
					<int>130144837</int>
					<int>130171030</int>
					<int>130172071</int>
					<int>130197218</int>
					<int>130212435</int>
					<int>130291076</int>
					<int>130402427</int>
					<int>130405166</int>
					<int>130676169</int>
					<int>130698471</int>
					<int>130713390</int>
					<int>130785217</int>
					<int>131396908</int>
					<int>131455115</int>
					<int>131682095</int>
					<int>131689473</int>
					<int>131701956</int>
					<int>132142800</int>
					<int>132525441</int>
					<int>132765492</int>
					<int>132801275</int>
					<int>133399034</int>
					<int>134522926</int>
					<int>134524022</int>
					<int>134528994</int>
					<int>134532942</int>
					<int>134536993</int>
					<int>134538001</int>
					<int>134547533</int>
					<int>134549216</int>
					<int>134549317</int>
					<int>134550159</int>
					<int>134550214</int>
					<int>134550232</int>
					<int>134551154</int>
					<int>134551207</int>
					<int>134551390</int>
					<int>134553171</int>
					<int>134553237</int>
					<int>134554199</int>
					<int>134554227</int>
					<int>134555229</int>
					<int>134555240</int>
					<int>134556118</int>
					<int>134557078</int>
					<int>134560099</int>
					<int>134560287</int>
					<int>134562084</int>
					<int>134562180</int>
					<int>134563287</int>
					<int>134565083</int>
					<int>134566130</int>
					<int>134568111</int>
					<int>134624737</int>
					<int>134666461</int>
					<int>134672998</int>
					<int>134684008</int>
					<int>134916523</int>
					<int>135100527</int>
					<int>135219410</int>
					<int>135222083</int>
					<int>135306997</int>
					<int>135463054</int>
					<int>135779456</int>
					<int>135812968</int>
					<int>136097030</int>
					<int>136131333</int>
					<int>136146907</int>
					<int>136157556</int>
					<int>136320962</int>
					<int>136450641</int>
					<int>136466000</int>
					<int>136745792</int>
					<int>136761546</int>
					<int>136840245</int>
					<int>138160034</int>
					<int>138181244</int>
					<int>138210071</int>
					<int>138210107</int>
					<int>138232200</int>
					<int>138237088</int>
					<int>138277547</int>
					<int>138287133</int>
					<int>138306991</int>
					<int>138324625</int>
					<int>138341916</int>
					<int>138372035</int>
					<int>138372036</int>
					<int>138375118</int>
					<int>138378071</int>
					<int>138380128</int>
					<int>138380194</int>
					<int>138534411</int>
					<int>138618294</int>
					<int>138931764</int>
					<int>139536037</int>
					<int>139536038</int>
					<int>139536039</int>
					<int>139536040</int>
					<int>140367832</int>
					<int>140406050</int>
					<int>140421668</int>
					<int>140422973</int>
					<int>140423713</int>
					<int>140436348</int>
					<int>140483470</int>
					<int>140615715</int>
					<int>140802803</int>
					<int>140896470</int>
					<int>141189437</int>
					<int>141192744</int>
					<int>141382548</int>
					<int>141461680</int>
					<int>141624996</int>
					<int>141627135</int>
					<int>141659139</int>
					<int>141872038</int>
					<int>141993721</int>
					<int>142006413</int>
					<int>142045136</int>
					<int>142095667</int>
					<int>142227273</int>
					<int>142250480</int>
					<int>142518788</int>
					<int>142544931</int>
					<int>142546314</int>
					<int>142555433</int>
					<int>142653044</int>
					<int>143191852</int>
					<int>143258496</int>
					<int>143299722</int>
					<int>143331253</int>
					<int>143432462</int>
					<int>143632431</int>
					<int>143695326</int>
					<int>144219522</int>
					<int>144590916</int>
					<int>145410436</int>
					<int>146720405</int>
					<int>150810438</int>
					<int>151258773</int>
					<int>151315554</int>
					<int>151400090</int>
					<int>151429441</int>
					<int>151439617</int>
					<int>151453617</int>
					<int>151466296</int>
					<int>151511132</int>
					<int>151636561</int>
					<int>151823192</int>
					<int>151827116</int>
					<int>151850642</int>
					<int>152016572</int>
					<int>153111675</int>
					<int>153114652</int>
					<int>153123147</int>
					<int>153267108</int>
					<int>153389799</int>
					<int>153395366</int>
					<int>153718608</int>
					<int>154171028</int>
					<int>154315227</int>
					<int>154559688</int>
					<int>154978771</int>
					<int>154979742</int>
					<int>154985773</int>
					<int>154989370</int>
					<int>155044852</int>
					<int>155065458</int>
					<int>155578573</int>
					<int>156403304</int>
					<int>159085959</int>
					<int>159776047</int>
					<int>159816630</int>
					<int>160733048</int>
					<int>160733049</int>
					<int>160733050</int>
					<int>160733051</int>
					<int>160733056</int>
					<int>164824922</int>
					<int>164824924</int>
					<int>164824926</int>
					<int>164824930</int>
					<int>164831646</int>
					<int>164831647</int>
					<int>164831648</int>
					<int>164831650</int>
					<int>164835050</int>
					<int>164835051</int>
					<int>164835052</int>
					<int>164835056</int>
					<int>164835057</int>
					<int>164835059</int>
					<int>164836898</int>
					<int>164836899</int>
					<int>164836900</int>
					<int>164845333</int>
					<int>164845334</int>
					<int>164845336</int>
					<int>164845337</int>
					<int>164845341</int>
					<int>164845342</int>
					<int>164845345</int>
					<int>164845346</int>
					<int>164845349</int>
					<int>164845350</int>
					<int>164845353</int>
					<int>164845355</int>
					<int>164845358</int>
					<int>164845361</int>
					<int>164845364</int>
					<int>164847387</int>
					<int>164847388</int>
					<int>164847389</int>
					<int>164847390</int>
					<int>164848328</int>
					<int>164848329</int>
					<int>164848330</int>
					<int>164849448</int>
					<int>164849449</int>
					<int>164849451</int>
					<int>164849452</int>
					<int>164849454</int>
					<int>164849455</int>
					<int>164849457</int>
					<int>164849461</int>
					<int>164850219</int>
					<int>164850220</int>
					<int>164850222</int>
					<int>164850223</int>
					<int>164850224</int>
					<int>164850226</int>
					<int>164850227</int>
					<int>164850228</int>
					<int>164850229</int>
					<int>164850231</int>
					<int>164850236</int>
					<int>164850237</int>
					<int>164850240</int>
					<int>164850242</int>
					<int>164850243</int>
					<int>164852242</int>
					<int>164852243</int>
					<int>164852244</int>
					<int>164852247</int>
					<int>164852248</int>
					<int>164852249</int>
					<int>164852250</int>
					<int>164852251</int>
					<int>164852254</int>
					<int>164852256</int>
					<int>164852257</int>
					<int>164852258</int>
					<int>164852259</int>
					<int>164852260</int>
					<int>164852261</int>
					<int>164852262</int>
					<int>164853061</int>
					<int>164853063</int>
					<int>164853071</int>
					<int>164853072</int>
					<int>164853075</int>
					<int>168118980</int>
					<int>168118981</int>
					<int>168118983</int>
					<int>168118984</int>
					<int>168180375</int>
					<int>168180376</int>
					<int>168180378</int>
					<int>168180379</int>
					<int>168270830</int>
					<int>168270831</int>
					<int>168270833</int>
					<int>168270834</int>
					<int>168270835</int>
				</OtherCachedUpdateIDs>
				<SkipSoftwareSync>false</SkipSoftwareSync>
				<NeedTwoGroupOutOfScopeUpdates>true</NeedTwoGroupOutOfScopeUpdates>
				<FilterAppCategoryIds>
					<CategoryIdentifier>
						<Id>{cat_id}</Id>
					</CategoryIdentifier>
				</FilterAppCategoryIds>
				<TreatAppCategoryIdsAsInstalled>true</TreatAppCategoryIdsAsInstalled>
				<AlsoPerformRegularSync>false</AlsoPerformRegularSync>
				<ComputerSpec/>
				<ExtendedUpdateInfoParameters>
					<XmlUpdateFragmentTypes>
						<XmlUpdateFragmentType>Extended</XmlUpdateFragmentType>
					</XmlUpdateFragmentTypes>
					<Locales>
						<string>en-US</string>
						<string>en</string>
					</Locales>
				</ExtendedUpdateInfoParameters>
				<ClientPreferredLanguages>
					<string>en-US</string>
				</ClientPreferredLanguages>
				<ProductsParameters>
					<SyncCurrentVersionOnly>false</SyncCurrentVersionOnly>
					<DeviceAttributes>BranchReadinessLevel=CB;CurrentBranch=rs_prerelease;OEMModel=Virtual Machine;FlightRing={release_type};AttrDataVer=21;SystemManufacturer=Microsoft Corporation;InstallLanguage=en-US;OSUILocale=en-US;InstallationType=Client;FlightingBranchName=external;FirmwareVersion=Hyper-V UEFI Release v2.5;SystemProductName=Virtual Machine;OSSkuId=48;FlightContent=Branch;App=WU;OEMName_Uncleaned=Microsoft Corporation;AppVer=10.0.22621.900;OSArchitecture=AMD64;SystemSKU=None;UpdateManagementGroup=2;IsFlightingEnabled=1;IsDeviceRetailDemo=0;TelemetryLevel=3;OSVersion=10.0.22621.900;DeviceFamily=Windows.Desktop;</DeviceAttributes>
					<CallerAttributes>Interactive=1;IsSeeker=0;</CallerAttributes>
					<Products/>
				</ProductsParameters>
			</parameters>
		</SyncUpdates>
	</s:Body>
    </s:Envelope> 
    """

    out = session.post(
        "https://fe3.delivery.mp.microsoft.com/ClientWebService/client.asmx",
        data=cat_id_content,
        headers={"Content-Type": "application/soap+xml; charset=utf-8"},
        verify=False,
    )

    doc = minidom.parseString(html.unescape(out.text))

    filenames = {}
    for node in doc.getElementsByTagName("Files"):
        filenames[
            node.parentNode.parentNode.getElementsByTagName("ID")[0].firstChild.nodeValue
        ] = f"{node.firstChild.attributes['InstallerSpecificIdentifier'].value}_{node.firstChild.attributes['FileName'].value}"
        pass

    identities = []
    identitis_dict = {}
    for node in doc.getElementsByTagName("SecuredFragment"):
        filename = filenames[node.parentNode.parentNode.parentNode.getElementsByTagName("ID")[0].firstChild.nodeValue]
        update_identity = node.parentNode.parentNode.firstChild
        identities += [(update_identity.attributes["UpdateID"].value, update_identity.attributes["RevisionNumber"].value, filename)]
        identitis_dict.update({update_identity.attributes["UpdateID"].value: filename})
    FE3_file_content = """<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing"
	xmlns:s="http://www.w3.org/2003/05/soap-envelope">
	<s:Header>
		<a:Action s:mustUnderstand="1">http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService/GetExtendedUpdateInfo2</a:Action>
		<a:MessageID>urn:uuid:2cc99c2e-3b3e-4fb1-9e31-0cd30e6f43a0</a:MessageID>
		<a:To s:mustUnderstand="1">https://fe3.delivery.mp.microsoft.com/ClientWebService/client.asmx/secured</a:To>
		<o:Security s:mustUnderstand="1"
			xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
			<Timestamp xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
				<Created>2017-08-01T00:29:01.868Z</Created>
				<Expires>2017-08-01T00:34:01.868Z</Expires>
			</Timestamp>
			<wuws:WindowsUpdateTicketsToken wsu:id="ClientMSA"
				xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
				xmlns:wuws="http://schemas.microsoft.com/msus/2014/10/WindowsUpdateAuthorization">
				<TicketType Name="MSA" Version="1.0" Policy="MBI_SSL">
					<user>{}</user>
				</TicketType>
			</wuws:WindowsUpdateTicketsToken>
		</o:Security>
	</s:Header>
	<s:Body>
		<GetExtendedUpdateInfo2 xmlns="http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService">
			<updateIDs>
				<UpdateIdentity>
					<UpdateID>{}</UpdateID>
					<RevisionNumber>{}</RevisionNumber>
				</UpdateIdentity>
			</updateIDs>
			<infoTypes>
				<XmlUpdateFragmentType>FileUrl</XmlUpdateFragmentType>
				<XmlUpdateFragmentType>FileDecryption</XmlUpdateFragmentType>
			</infoTypes>
			<deviceAttributes>BranchReadinessLevel=CB;CurrentBranch=rs_prerelease;OEMModel=Virtual Machine;FlightRing={};AttrDataVer=21;SystemManufacturer=Microsoft Corporation;InstallLanguage=en-US;OSUILocale=en-US;InstallationType=Client;FlightingBranchName=external;FirmwareVersion=Hyper-V UEFI Release v2.5;SystemProductName=Virtual Machine;OSSkuId=48;FlightContent=Branch;App=WU;OEMName_Uncleaned=Microsoft Corporation;AppVer=10.0.22621.900;OSArchitecture=AMD64;SystemSKU=None;UpdateManagementGroup=2;IsFlightingEnabled=1;IsDeviceRetailDemo=0;TelemetryLevel=3;OSVersion=10.0.22621.900;DeviceFamily=Windows.Desktop;</deviceAttributes>
            </GetExtendedUpdateInfo2>
        </s:Body>
    </s:Envelope>
    """

    def send_req(i, v):
        out = session.post(
            "https://fe3.delivery.mp.microsoft.com/ClientWebService/client.asmx/secured",
            data=FE3_file_content.format(user, i, v, release_type),
            headers={"Content-Type": "application/soap+xml; charset=utf-8"},
            verify=False,
        )
        doc = minidom.parseString(out.text)
        for url in doc.getElementsByTagName("FileLocation"):
            for child in url.childNodes:
                if child.nodeName =="Url":
                    if len(child.firstChild.nodeValue) != 99:
                        download_url = child.firstChild.nodeValue
        
        print(download_url)
        return download_url

    last_dict = {}
    for i, v, f in identities:
        url = send_req(i, v)
        last_dict.update({identitis_dict[i]: url})
    return last_dict


def get_all_files(store_id):
    all_files = get_file_dict(store_id)
    all_files_dict = []
    # parse every file name and url in all_files:

    for i in all_files:
        version = i.split("_")[1]
        bin_name = i.replace("~", "_")
        download_url = all_files[i]
        pkg_splitted = re.split(r"_\d+\.", bin_name)[0]
        package_prefix = control.package.split("-")[0]
        package_name = package_prefix + "-" + pkg_splitted.split("_")[0].replace(".", "-").lower()
        software_name = bin_name.split("_")[0].replace("-", " ").replace(".", " ")
        if "arm64" in bin_name:
            package_arch = "arm64"
        elif "arm" in bin_name:
            package_arch = "arm"
        elif "x64" in bin_name:
            package_arch = "x64"
        # elif "x86" in bin_name:
        #     package_arch = "all"  # not x86 since it may be required for x64
        else:
            package_arch = "all"

        file_dict = {
            "version": version,
            "bin_name": bin_name,
            "package_name": package_name,
            "software_name": software_name,
            "package_arch": control.architecture,
            "package_arch": package_arch,
            "download_url": download_url,
        }
        all_files_dict.append(file_dict)
    return all_files_dict


def ask_dialog(title, text, default="", stay_on_top=False):
    """This function opens a dialog box with a action input"""
    # - Title: the title for the dialog
    # - Text: indicates which value the user should type
    # - Default: the default value, if the user do not want to type any
    # Optional:
    # - StayOnTop: indicates if the form will always stay on top - default is False
    return waptguihelper.input_dialog(title, text, default, stay_on_top)


def ask_app_filename(all_files_dict, store_package_name):
    # input files dict and a  store packa_name if it exist, if empty selct automatically the proper file if not ask user to select it
    if "template-microsoft-store" in control.package:
        selected = waptguihelper.grid_dialog(
            "Please select the proper file",
            json.dumps(all_files_dict),
            waptguihelper.GRT_SELECTED,
            '{"columns":[{"propertyname":"version","datatype":"String","required":false,"readonly":false,"width":130},{"propertyname":"bin_name","datatype":"String","required":false,"readonly":false,"width":420},{"propertyname":"package_name","datatype":"String","required":false,"readonly":false,"width":190},{"propertyname":"software_name","datatype":"String","required":false,"readonly":false,"width":172},{"propertyname":"package_arch","datatype":"String","required":false,"readonly":false,"width":88},{"propertyname":"download_url","datatype":"String","required":false,"readonly":false,"width":1472}]}',
        )
    else:
        selected = [a for a in all_files_dict if (a["package_arch"] in ensure_list(control.architecture) or control.architecture == "all" or a["package_arch"] == "all")]
        if len(selected) != 1:
            higer_version = "0"
            for a in all_files_dict:
                if Version(higer_version) < Version(a["version"]) and store_package_name in a["bin_name"]:
                    higer_version = a["version"]
                    break
            selected = [a for a in selected if higer_version == a["version"] and store_package_name in a["bin_name"]]

    print(selected)
    return selected

def make_uwp_app_dict(appx_package_name):

    ms_app_db = {}
    # for ms_app_file in (
    #     glob.glob("*.appxbundle")
    #     + glob.glob("*.msixbundle")
    #     + glob.glob("*.appx")
    #     + glob.glob("*.msix")
    # ):
    for ms_app_file in (
        glob.glob(f"{appx_package_name}*.appxbundle")
        + glob.glob(f"{appx_package_name}*.msixbundle")
        + glob.glob(f"{appx_package_name}*.appx")
        + glob.glob(f"{appx_package_name}*.msix")
    ):
        data_dict = {}
        before_dependencies = []
        sub_dependencies = []
        dependency_data_dict = None

        manifest = None
        bundle_manifest = None

        manifest_path = makepath(basedir,"AppxManifest.xml")
        unzip_with_7zip(ms_app_file, ".", "AppxManifest.xml", False)
        if isfile(manifest_path):
            manifest = manifest_path
        bundle_manifest_path = makepath(basedir,"AppxBundleManifest.xml")
        unzip_with_7zip(ms_app_file, ".", "AppxMetadata\\AppxBundleManifest.xml", False)
        if isfile(bundle_manifest_path):
            bundle_manifest = bundle_manifest_path
        ms_app_info = {
            "FileName": ms_app_file,
        }

        if not manifest:
            if bundle_manifest:
                with open(bundle_manifest, encoding="utf8") as xml_file:
                    data_dict = xmltodict.parse(xml_file.read(), attr_prefix="")

                if type(data_dict["Bundle"]["Packages"]["Package"]) == dict:
                    data_dict["Bundle"]["Packages"]["Package"] = [dict(data_dict["Bundle"]["Packages"]["Package"])]

                for app_pkg in list(data_dict["Bundle"]["Packages"]["Package"]):
                    if app_pkg["Type"] == "application":
                        before_dependency_info = {
                            "FileName": app_pkg["FileName"],
                            "Version": app_pkg["Version"],
                            "Architecture": app_pkg["Architecture"],
                        }
                        before_dependencies.append(before_dependency_info)

                if before_dependencies:
                    for dependency in before_dependencies:
                        unzip(
                            ms_app_file,
                            ".",
                            makepath(
                                dependency["FileName"],
                            ),
                            False,
                        )
                        unzip(dependency["FileName"], ".", makepath("AppxManifest.xml"), False)
                        manifest = manifest_path = makepath(basedir,"AppxManifest.xml")
                        if isfile(dependency["FileName"]):
                            remove_file(dependency["FileName"])
                        with open(manifest, encoding="utf8") as xml_file:
                            dependency_data_dict = xmltodict.parse(xml_file.read(), attr_prefix="")

                    if dependency_data_dict["Package"].get("Dependencies"):
                        if dependency_data_dict["Package"]["Dependencies"].get("PackageDependency"):
                            sub_dependencies = list(dependency_data_dict["Package"]["Dependencies"]["PackageDependency"])
                            if type(dependency_data_dict["Package"]["Dependencies"]["PackageDependency"]) == dict:
                                sub_dependencies = [dict(dependency_data_dict["Package"]["Dependencies"]["PackageDependency"])]
                            if type(dependency_data_dict["Package"]["Dependencies"]["PackageDependency"]) == list:
                                sub_dependencies = dependency_data_dict["Package"]["Dependencies"]["PackageDependency"]
                        if dependency_data_dict["Package"]["Dependencies"].get("TargetDeviceFamily"):
                            if not "TargetDeviceFamily" in ms_app_info:
                                if type(dependency_data_dict["Package"]["Dependencies"]["TargetDeviceFamily"]) == dict:
                                    ms_app_info["TargetDeviceFamily"] = [dict(dependency_data_dict["Package"]["Dependencies"]["TargetDeviceFamily"])]
                                if type(dependency_data_dict["Package"]["Dependencies"]["TargetDeviceFamily"]) == list:
                                    ms_app_info["TargetDeviceFamily"] = dependency_data_dict["Package"]["Dependencies"]["TargetDeviceFamily"]
            else:
                error("nothing to parse")
        else:
            unzip_with_7zip(ms_app_file, ".", makepath("AppxManifest.xml"), False)
            manifest = manifest_path = makepath(basedir,"AppxManifest.xml")
            with open(manifest, encoding="utf8") as xml_file:
                dependency_data_dict = xmltodict.parse(xml_file.read(), attr_prefix="")

        if dependency_data_dict["Package"].get("Dependencies"):
            if "PackageDependency" in dependency_data_dict["Package"]["Dependencies"]:
                sub_dependencies = list(dependency_data_dict["Package"]["Dependencies"]["PackageDependency"])
                if type(dependency_data_dict["Package"]["Dependencies"]["PackageDependency"]) == dict:
                    sub_dependencies = [dict(dependency_data_dict["Package"]["Dependencies"]["PackageDependency"])]
                if type(dependency_data_dict["Package"]["Dependencies"]["PackageDependency"]) == list:
                    sub_dependencies = dependency_data_dict["Package"]["Dependencies"]["PackageDependency"]
            if "TargetDeviceFamily" in dependency_data_dict["Package"]["Dependencies"]:
                if not "TargetDeviceFamily" in ms_app_info:
                    if type(dependency_data_dict["Package"]["Dependencies"]["TargetDeviceFamily"]) == dict:
                        ms_app_info["TargetDeviceFamily"] = [dict(dependency_data_dict["Package"]["Dependencies"]["TargetDeviceFamily"])]
                    if type(dependency_data_dict["Package"]["Dependencies"]["TargetDeviceFamily"]) == list:
                        ms_app_info["TargetDeviceFamily"] = dependency_data_dict["Package"]["Dependencies"]["TargetDeviceFamily"]
        else:
            ms_app_info.update({"Dependencies": None})

        if ms_app_info.get("TargetDeviceFamily"):
            ms_app_info.update(
                {
                    "MinVersion": ms_app_info["TargetDeviceFamily"][0]["MinVersion"],
                    "MaxVersionTested": ms_app_info["TargetDeviceFamily"][0]["MaxVersionTested"],
                }
            )
        elif dependency_data_dict is not None and dependency_data_dict["Package"].get("Prerequisites"):
            ms_app_info.update(
                {
                    "MinVersion": dependency_data_dict["Package"]["Prerequisites"]["OSMinVersion"],
                    "MaxVersionTested": dependency_data_dict["Package"]["Prerequisites"]["OSMaxVersionTested"],
                }
            )
        else:
            ms_app_info.update({"TargetDeviceFamily": None})

        if data_dict:
            ms_app_info.update(data_dict["Bundle"]["Identity"])
        else:
            ms_app_info.update(dependency_data_dict["Package"]["Identity"])
        if "ProcessorArchitecture" in ms_app_info:
            ms_app_info.update({"Architecture": ms_app_info["ProcessorArchitecture"]})
        if before_dependencies:
            ms_app_info["b4:Dependencies"] = before_dependencies
        else:
            ms_app_info.update({"b4:Dependencies": None})

        if sub_dependencies:
            ms_app_info["Dependencies"] = sub_dependencies
        else:
            ms_app_info.update({"Dependencies": None})

        ms_app_db[ms_app_file] = ms_app_info

        for xml_file in glob.glob("AppxManifest.xml") + glob.glob("AppxBundleManifest.xml"):
            remove_file(xml_file)

    return ms_app_db

def get_newer_uwp_app(uwp_app_dict, version_prefix=None, min_version=None, max_version=None, tdf_list=["Windows.Universal", "Windows.Desktop"]):
    """Get the newer Universal Windows Platform (UWP) app from a dictionary of UWP apps based on specified criteria.

    Args:
        uwp_app_dict (dict): A dictionary containing UWP app information with app IDs as keys and app details as values.
        version_prefix (str, optional): The prefix of the version number to filter the apps. Defaults to None.
        min_version (str, optional): The minimum version of the UWP app. Defaults to None.
        max_version (str, optional): The maximum version of the UWP app. Defaults to None.
        tdf_list (list, optional): A list of target device families to filter the apps. Defaults to ["Windows.Universal", "Windows.Desktop"].

    Returns:
        dict or None: The dictionary containing the details of the newer UWP app that matches the specified criteria, or None if no app is found.

    """
    newer_uwp_app = None
    newer_version = "0"

    for uwp_app in uwp_app_dict.values():
        to_skip = False  # Initialize to_skip as False and set to True only if any condition fails

        # Check version prefix
        if version_prefix is not None and not Version(uwp_app["Version"], len(version_prefix.split("."))) == Version(
            version_prefix, len(version_prefix.split("."))
        ):
            to_skip = True
            continue

        # Check target device family
        try:
            if tdf_list is not None and uwp_app["TargetDeviceFamily"]:
                for tdf in tdf_list:
                    for uwp_app_tdf in uwp_app["TargetDeviceFamily"]:
                        if (
                            tdf == uwp_app_tdf["Name"]
                            and (min_version is None or Version(min_version, 3) == Version(uwp_app_tdf["MinVersion"], 3))
                            and (max_version is None or Version(max_version, 3) == Version(uwp_app_tdf["MaxVersionTested"], 3))
                        ):
                            break
                    else:
                        continue
                    break
        except:
            pass

        # Check max OS version
        if control.max_os_version and not Version(uwp_app["MinVersion"], 3) < Version(control.max_os_version, 3):
            to_skip = True

        if to_skip:
            continue

        # Update the newer UWP app if the current app has a higher version
        if Version(newer_version) < Version(uwp_app["Version"]):
            newer_uwp_app = uwp_app
            newer_version = newer_uwp_app["Version"]

    return newer_uwp_app

def get_newer_uwp_depency(dependency_dict, all_files_dict, version_prefix=None, min_version=None):
    """Returns a list of the bin_name of the latest required dependencies"""
    newer_version = "0"

    for uwp_app in all_files_dict:
        if not uwp_app["bin_name"].startswith(f'{dependency_dict["Name"]}_'):
            continue
        if version_prefix is not None and Version(uwp_app["version"], len(version_prefix.split("."))) != Version(
            version_prefix, len(version_prefix.split("."))
        ):
            continue

        if Version(newer_version) < Version(uwp_app["version"]):
            newer_uwp_depency = uwp_app
            newer_version = uwp_app["version"]

    return newer_uwp_depency["bin_name"]

def get_uwp_filename_arch(appx_filename, appx_package_name=None):
    """
    Returns the architecture of a Universal Windows Platform (UWP) app based on the provided 'appx_filename'
    and optionally, the 'appx_package_name'.

    Args:
        appx_filename (str): The filename of the UWP app package.
        appx_package_name (str, optional): The package name of the UWP app. Defaults to None.

    Returns:
        str: The architecture of the UWP app, which can be "x64", "arm64", "x86", or "all" (if no specific
        architecture is detected).
    """
    if not appx_package_name:
        appx_package_name = None
    if len(glob.glob(f'{appx_package_name}*{appx_filename.split("_")[1]}*')) > 1:
        pass
    elif "arm64" in appx_filename:
        return "arm64"
    elif "arm" in appx_filename:
        return "arm"
    elif "x64" in appx_filename:
        return "x64"
    if appx_filename is not None and "x86" in appx_filename and (appx_package_name is None or not appx_package_name in appx_filename):
        return "x86"

    return "all"
38d056ab130f7bf7c481c12636a4e9959de36561d3dfcbe54c6e3571bc0c1dc3 : WAPT/certificate.crt
7825337608843dd710efbf1cc5c9567fcc49158b1f02412068d3d7c86079ec42 : WAPT/control
fb211ca16725f640fc2e7454304f2c4da34edb3483d3065ea8c08758828ba9e7 : WAPT/icon.png
77f7d1a0e1addbf419e317b64ab81fda0ee79459391478e404bed4da5976f6fa : luti.json
24f36cbb1a376aaff136caa66ff423b52f252cb9b15d01dcba681f1491b3e219 : microsoft-desktopappinstaller/Microsoft.DesktopAppInstaller_2021.1207.203.0_neutral___8wekyb3d8bbwe_17022c2f-1a0a-4762-9ffb-f1e2e7512eee.appxbundle
831118f2f5cac8e29284e4ecc23bf4236436ccc2ea4a7c225c4946f8cfd29dd3 : microsoft-desktopappinstaller/Microsoft.VCLibs.140.00.UWPDesktop_14.0.33728.0_arm64__8wekyb3d8bbwe_8b19ae8f-1fe9-45e1-aed3-1672ee33bf71.appx
acaca717c932f2dc1f9a6e7095085e19f56afb1f9303a04baeaae146d3b987b8 : package.json
dd40f4f8541d386253ae5a8c906f36a9c4b7d10644a43be56192bfed8d443e8d : setup.py
c802d056a635d7c09e516c827ce4f49551b98844183adf0aa5896ea5bdfd2a03 : setupdevhelpers.py
7ca3da8e1e279b85ccb4088d071686458fcc294fc0553577767da2c66e81fe5f : update_package.py
364e01205533a0c6907fb9e8a8f70353985ae81ead35b71aade9a4253184f847 : xmltodict.py