tis-microsoft-office-2021-standard icon

Office LTSC Standard 2021

Paquet d’installation silencieuse pour Office LTSC Standard 2021

16.0.14334.20522-15
Office
Office

package           : tis-microsoft-office-2021-standard
version           : 16.0.14334.20522-15
architecture      : x64
section           : base
priority          : optional
name              : Office LTSC Standard 2021
categories        : Office
maintainer        : WAPT Team,Tranquil IT,Kévin Guérineau, Jimmy PELÉ,Clément Baziret
description       : Microsoft Office 2021 is a version of the Microsoft Office suite
depends           : 
conflicts         : tis-microsoft-access-2016-runtime,tis-microsoft-office-2016,tis-microsoft-office-2013,tis-microsoft-office-365-entreprise,tis-microsoft-office-2019-professional
maturity          : PROD
locale            : all
target_os         : windows
min_wapt_version  : 2.3
sources           : https://www.microsoft.com/download/details.aspx?id=49117
installed_size    : 2362231960
impacted_process  : EXCEL,GROOVE,MSACCESS,MSPUB,ONENOTE,OUTLOOK,POWERPNT,WINWORD
description_fr    : Microsoft Office 2021 est une version de la suite Microsoft Office
description_pl    : Microsoft Office 2021 to wersja pakietu biurowego Microsoft Office
description_de    : Microsoft Office 2021 ist eine Version der Microsoft Office-Suite
description_es    : Microsoft Office 2021 es una versión del paquete Microsoft Office
description_pt    : O Microsoft Office 2021 é uma versão do pacote Microsoft Office
description_it    : Microsoft Office 2021 è una versione della suite Microsoft Office
description_nl    : Microsoft Office 2021 is een versie van de Microsoft Office-suite
description_ru    : Microsoft Office 2021 - это версия пакета Microsoft Office
audit_schedule    : 
editor            : Microsoft
keywords          : microsoft,office,2021,version,suite
licence           : proprietary_restricted,wapt_public
homepage          : https://www.office.com/
package_uuid      : d05a2d54-37a7-4223-b845-ed74197b97b7
valid_from        : 
valid_until       : 
forced_install_on : 
changelog         : 
min_os_version    : 10.0
max_os_version    : 
icon_sha256sum    : 2ac98141bf5b6777083f2bcbeab3ab034c01dff77718e108774575aaaa54a144
signer            : Tranquil IT
signer_fingerprint: 8c5127a75392be9cc9afd0dbae1222a673072c308c14d88ab246e23832e8c6bb
signature_date    : 2026-02-11T13:12:56.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         : JNKA0+jWYjPEZF/q8+TfGgEncWGU98+EpnCdgNyOXqgma8KxKjh8m/gLFNV74MQD3o0D5E4WAXeYnpeUg8nIoZIHFkBtsZL8qKpSQ5XHsfFbztiOsmflhdp/h3AjYBngeEDkc8yFo9wtdVTc/w34AXiZymmg8GXGprNB7JK3g0Ds/uMiEs0OHNgmqa1Edc8xCFs7czlHK9X3djz4rQxhfx7Mxu3/1Wsl/2jgyTLzNVHnU/cmP5HR9LngVxl9PvpHwADr8sNl/rPS5xBenNs/jvsDDoGsKltKW22pRiFtGTMlXx+JWZCds9SG2aA67iKMOz9kySGeEvX6EX4owDSrNQ==

# -*- coding: utf-8 -*-
from setuphelpers import *
import tempfile

"""
Ressources:
https://config.office.com/deploymentsettings
https://admx.help/?Category=Office2016&Policy=office16.Office.Microsoft.Policies.Windows::L_SCLCacheOverride
https://admx.help/?Category=Office2016&Policy=excel16.Office.Microsoft.Policies.Windows::L_SaveExcelfilesas

"""

app_uninstallkey = "Standard2021Volume - fr-fr"


def install():
    # Declaring local variables
    package_version = control.get_software_version()
    silentflags = "/configure configuration.xml"

    # uninstalling older versions of office if needed
    uninstall_mso2013_if_needed("Office15.STANDARD")
    uninstall_mso2016_if_needed("Office16.STANDARD")
    uninstall_other_office_edition(app_uninstallkey.split(" ")[0])

    # Installing the software
    install_exe_if_needed(
        "setup.exe",
        silentflags=silentflags,
        timeout=1200,
        accept_returncodes=[1641, 3010, 0],
        key=app_uninstallkey,
        min_version=package_version,
    )

    # TODO "setup.exe /customize configuration.xml if up-to-date"

    # Adding silent uninstall command
    quiet_uninstall = installed_softwares(uninstallkey=app_uninstallkey)[0]["uninstall_string"] + " DisplayLevel=False"
    if "OfficeClickToRun.exe" in quiet_uninstall:
        register_uninstall(
            uninstallkey=app_uninstallkey,
            quiet_uninstall_string=quiet_uninstall,
        )


def session_setup():
    print("Disabling: MSO telemetry")
    # https://admx.help/?Category=Office2016&Policy=office16.Office.Microsoft.Policies.Windows::L_OfficeOSMPreventedHostApplications
    registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\osm\preventedapplications", "wdsolution", 1)
    registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\osm\preventedapplications", "xlsolution", 1)
    registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\osm\preventedapplications", "pptsolution", 1)
    registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\osm\preventedapplications", "olksolution", 1)
    registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\osm\preventedapplications", "accesssolution", 1)
    registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\osm\preventedapplications", "projectsolution", 1)
    registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\osm\preventedapplications", "publishersolution", 1)
    registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\osm\preventedapplications", "visiosolution", 1)
    registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\osm\preventedapplications", "onenotesolution", 1)
    # https://admx.help/?Category=Office2016&Policy=office16.Office.Microsoft.Policies.Windows::L_OfficeOSMPreventedSolutionTypes
    registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\osm\preventedsolutiontypes", "documentfiles", 1)
    registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\osm\preventedsolutiontypes", "templatefiles", 1)
    registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\osm\preventedsolutiontypes", "comaddins", 1)
    registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\osm\preventedsolutiontypes", "appaddins", 1)
    registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\osm\preventedsolutiontypes", "agave", 1)
    # https://admx.help/?Category=Office2016&Policy=office16.Office.Microsoft.Policies.Windows::L_EnableLogging
    # registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\osm", "enablelogging", 0)
    registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\osm", "enableupload", 0)
    registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\osm", "enablefileobfuscation", 1)
    # # https://admx.help/?Category=Office2016&Policy=office16.Office.Microsoft.Policies.Windows::L_Onlinecontentoptions
    # registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\common\internet", "useonlinecontent", 0)
    # # https://admx.help/?Category=Office2016&Policy=office16.Office.Microsoft.Policies.Windows::L_ServiceLevelOptions
    # registry_set(HKEY_CURRENT_USER, r"software\policies\microsoft\office\16.0\common\internet", "serviceleveloptions", 0)


def uninstall_other_office_edition(edition_uninstallkey):
    # Initializing variables
    silent_uninstall_file_path = makepath(tempfile.gettempdir(), "remove_other_office.xml")
    uninstall_configuration_xml_content = r"""<Configuration>
    <Remove All="TRUE">
    </Remove>
    <Display Level="none" CompletionNotice="No" SuppressModal="Yes" AcceptEula="Yes" />
    <Setting Id="SETUP_REBOOT" Value="Never" />
    <Setting Id="REBOOT" Value="ReallySuppress"/>
</Configuration>
"""
    # Modify XML
    with open(silent_uninstall_file_path, "w") as xml_file:
        xml_file.write(uninstall_configuration_xml_content)

    # Uninstalling Office if needed
    for to_uninstall in installed_softwares():
        killalltasks(control.get_impacted_process_list())
        if ("OfficeClickToRun.exe" in to_uninstall["uninstall_string"]) and not (edition_uninstallkey in to_uninstall["key"]):
            print("Removing: %s (%s)" % (to_uninstall["name"], to_uninstall["version"]))
            app_uninstall_cmd = to_uninstall["uninstall_string"] + " DisplayLevel=False"
            run(app_uninstall_cmd)
            wait_uninstallkey_absent(to_uninstall["key"])


def uninstall_mso2016_if_needed(uninstallkey):
    # Initializing variables
    silent_uninstall_file_path = makepath(tempfile.gettempdir(), "remove_o2016.xml")
    uninstall_configuration_xml_content = r"""<Configuration>
    <Remove All="TRUE">
    </Remove>
    <Display Level="none" CompletionNotice="No" SuppressModal="Yes" AcceptEula="Yes" />
    <Setting Id="SETUP_REBOOT" Value="Never" />
    <Setting Id="REBOOT" Value="ReallySuppress"/>
</Configuration>
"""
    # Modify XML
    with open(silent_uninstall_file_path, "w") as xml_file:
        xml_file.write(uninstall_configuration_xml_content)

    # Uninstalling Office if needed
    for to_uninstall in installed_softwares(uninstallkey=uninstallkey):
        print("Removing: %s (%s)" % (to_uninstall["name"], to_uninstall["version"]))
        killalltasks(control.get_impacted_process_list())
        if "OfficeClickToRun.exe" in to_uninstall["uninstall_string"]:
            app_uninstall_cmd = to_uninstall["uninstall_string"] + " DisplayLevel=False"
            run(app_uninstall_cmd)
            wait_uninstallkey_absent(to_uninstall["key"])
        else:
            run(to_uninstall["uninstall_string"] + ' /config "%s"' % silent_uninstall_file_path)
            wait_uninstallkey_absent(to_uninstall["key"])


def uninstall_mso2013_if_needed(uninstallkey):
    # Initializing variables
    silent_uninstall_file_path = makepath(tempfile.gettempdir(), "remove_o2013.xml")
    uninstall_configuration_xml_content = r"""<Configuration>
    <Remove All="TRUE">
    </Remove>
    <Display Level="none" CompletionNotice="No" SuppressModal="Yes" AcceptEula="Yes" />
    <Setting Id="SETUP_REBOOT" Value="Never" />
    <Setting Id="REBOOT" Value="ReallySuppress"/>
</Configuration>
"""
    # Modify XML
    with open(silent_uninstall_file_path, "w") as xml_file:
        xml_file.write(uninstall_configuration_xml_content)

    # Uninstalling Office if needed
    for to_uninstall in installed_softwares(uninstallkey=uninstallkey):
        print("Removing: %s (%s)" % (to_uninstall["name"], to_uninstall["version"]))
        killalltasks(control.get_impacted_process_list())
        run(to_uninstall["uninstall_string"] + ' /config "%s"' % silent_uninstall_file_path)
        wait_uninstallkey_absent(to_uninstall["key"])

# -*- coding: utf-8 -*-
from setuphelpers import *
import waptguihelper
import webbrowser
import os
import sys

if "__file__" in locals():
    sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
from setupdevhelpers import *


def update_package():
    # Declaring local variables
    package_updated = False
    proxies = get_proxies()
    if not proxies:
        proxies = get_proxies_from_wapt_console()
    extract_path = "extract"

    # if not the first run it will use the last setup downloaded if you want to get an updated one you can remove setup.exe and relaunch the update package
    if not isfile("setup.exe") and not params.get("running_as_luti"):
        waptguihelper.message_dialog(
            "You browser will open",
            "Please download Office Deployment Tool by clicking the download button",
        )
        webbrowser.open("https://www.microsoft.com/download/details.aspx?id=49117")
        waptguihelper.message_dialog("Waiting for download", "Click OK when the download is complete", waptguihelper.ID_OK)
        # Copy to pkg
        latest_bin = waptguihelper.filename_dialog(
            "Please provide downloaded Office Deployment Tool to copy in this package",
            makepath(user_home_directory, "Downloads"),
            "",
            "EXE Files|*.exe",
        )

        # Extract Office Deployment Tool
        print("Copying: " + latest_bin)
        run(rf'"{latest_bin}" /extract:"{extract_path}" /quiet"')

        print("Extract Office Deployment Tool")
        filecopyto(".\\extract\\setup.exe", basedir)
        remove_file(latest_bin)
        if isdir("extract"):
            remove_tree("extract")

    elif params.get("running_as_luti"):
        user_agent =  'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/88.0'
        data = [ u for u in json.loads(wgets('https://www.microsoft.com/en-us/download/details.aspx?id=49117',user_agent=user_agent,proxies=proxies).split('<script>window.__DLCDetails__=',1)[1].split('</script>')[0])["dlcDetailsView"]['downloadFile'] if u['name'].endswith('.exe')][0]
        download_url = data['url']
        latest_bin = download_url.split("/")[-1]
        wget(download_url, latest_bin, proxies=proxies)

        # Extract Office Deployment Tool
        print("Copying: " + latest_bin)
        run(rf'"{latest_bin}" /extract:"{extract_path}" /quiet"')

        print("Extract Office Deployment Tool")
        filecopyto(".\\extract\\setup.exe", basedir)
        remove_file(latest_bin)
        if isdir("extract"):
            remove_tree("extract")

    # if not the first run it will use the last XML used if you want to get a new one you can remove configuration.xml and relaunch the update package
    if not isfile("configuration.xml"):
        waptguihelper.message_dialog(
            "Your browser will open",
            "Please complete your deployment settings with the online Office Customization Tool and download it by clicking Export.\nNote that you can go back anytime on the online tool to edit your configuration (by clicking Import)",
        )
        webbrowser.open("https://config.office.com/deploymentsettings")
        waptguihelper.message_dialog("Waiting for download", "Click OK when the XML is completed and downloaded", waptguihelper.ID_OK)
        xml_configuration = waptguihelper.filename_dialog(
            "Please select your XML configuration file", basedir, "configuration.xml", "XML Files|*.xml"
        )  # makepath(user_home_directory, "Downloads")
        if not isfile("configuration.xml"):
            filecopyto(
                xml_configuration,
                basedir + "\\configuration.xml",
            )

    # Asking to remove the last downloaded sources
    if isdir("Office"):
        if not params.get("running_as_luti"):
            response = ask_message(control.package, "Do you want to remove the last downloaded sources?", 35)
            if response == 6:
                print("Removing last sources folder downloaded")
                remove_tree("Office")
        else:
            print("Removing last sources folder downloaded")
            remove_tree("Office")
    else:
        # Download Office with XML configuration
        print("Downloading Office with XML configuration")
        if windows_version() >= WindowsVersions.Windows10:
            run("setup.exe /download configuration.xml", timeout=2400)  # DisplayLevel=Full # not working
        else:
            error("MSO setup.exe can no longer be run on this OS")

    # Getting version from source dir
    version = glob.glob("Office/Data/**/")[0].split(os.sep)[1]

    # Changing version of the package
    if Version(version, 4) > Version(control.get_software_version(), 4):
        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()

    # Getting Product ID and Language ID from configuration.xml parsing file
    with open("configuration.xml", "r", encoding="utf8") as f:
        for line in f:
            if "OfficeClientEdition" in line:
                architecture = line.split('"')[1]
                print("OfficeClientEdition: %s" % architecture)
                if architecture == "64":
                    architecture = "x64"
                else:
                    architecture = "all"
            if "Product ID" in line:
                product_id = line.split('"')[1]
                print("Product ID: %s" % product_id)
            if "Language ID" in line:
                language_id = line.split('"')[1]
                print("Language ID: %s" % language_id)
                break

    if control.architecture != architecture:
        control.architecture = architecture
        control.save_control_to_wapt()

    # Asking pkg infos if needed
    if control.locale not in language_id and "-template" in control.package:
        control.locale = waptguihelper.input_dialog(control.package, "You may wanna change locale to: %s" % language_id.split("-")[0], "all")
        print("Changing locale to: %s in WAPT\\control" % control.locale)
        control.save_control_to_wapt()

    complete_control_categories(control)
    complete_control_name(control, control.name, params.get("running_as_luti"))
    complete_control_package(control, control.package, params.get("running_as_luti"), False)
    complete_control_description(control, control.description, params.get("running_as_luti"), "update_package")

    # changing uninstallkey:
    new_lines = []
    with open("setup.py", "r", encoding="utf8") as f:
        for line in f.readlines():
            if line.startswith("app_uninstallkey"):
                line = f'app_uninstallkey = "{product_id} - {language_id}"\n'
                print(f'uninstallkey in setup updated to app_uninstallkey = "{product_id} - {language_id}"\n')
            new_lines.append(line)
    with open("setup.py", "w", encoding="utf8", newline="\n") as f:
        f.writelines(new_lines)

    # Validating or not update-package-sources
    return package_updated

32fd5c70eff61c4bfd7ad096a697d932b33ddeb1cc71b9fe4f0bae2e1410b74e : Office/Data/16.0.14334.20522/i640.cab
f6f62533b7d49c01b1530a2db9e009b946fb049736d63b46df54acf3e8ee6b9b : Office/Data/16.0.14334.20522/i640.cab.cat
6a13a1e368a592d7bcb338f76ced9836d4ad69f3da89826e5b8471f1d9dc9e54 : Office/Data/16.0.14334.20522/i641036.cab
a79fe38befe890e3244ed877c9d20a84bac0ff22337249dd5c86e9ff67b24944 : Office/Data/16.0.14334.20522/s640.cab
22f33c1128c51d6bb530f6bc19c58631e0297ae9f0575ab980dbe32498064315 : Office/Data/16.0.14334.20522/s641036.cab
bc1d2b0b7c1dcfaa78892a0a26eee256fc5943c3e93f90fa8b81db32c7d123e5 : Office/Data/16.0.14334.20522/sa640.cab
43b76f98455b8677fd226534906558f6ac009930c04a4aac7c1839cca5e4a8a8 : Office/Data/16.0.14334.20522/stream.x64.fr-fr.dat
b50dda517e91f82b0add7897ec96171b722fe6bd04c3b72220baa902b3472842 : Office/Data/16.0.14334.20522/stream.x64.fr-fr.dat.cat
8719f8563d0919dd1eb35a46bb045f089531151e9bcfce216ecdaee70f3aff2d : Office/Data/16.0.14334.20522/stream.x64.x-none.arm64x.dat
07854bd740cb52622186de06d5576ec1b2ffd55083e6c4d6ae67483eca63096a : Office/Data/16.0.14334.20522/stream.x64.x-none.arm64x.dat.cat
0f7af98b042468a5093932911764c217bf5d97acc3bc40a0076324eecb676164 : Office/Data/16.0.14334.20522/stream.x64.x-none.dat
81a6c2243a375b4be3854c0fe5b0952134b8676997922d338b69c66de41d6e42 : Office/Data/16.0.14334.20522/stream.x64.x-none.dat.cat
3a2b5bf2ee48260675a181b8d5b47ea97d82e5fd74cff57e349e764245f1efca : Office/Data/v64.cab
3a2b5bf2ee48260675a181b8d5b47ea97d82e5fd74cff57e349e764245f1efca : Office/Data/v64_16.0.14334.20522.cab
38d056ab130f7bf7c481c12636a4e9959de36561d3dfcbe54c6e3571bc0c1dc3 : WAPT/certificate.crt
7b59635c7e98fdc68632762f45c33307515a8a9f48d63f1142c3ed8ce78fc034 : WAPT/control
2ac98141bf5b6777083f2bcbeab3ab034c01dff77718e108774575aaaa54a144 : WAPT/icon.png
2dde629629fc6edbb04f24cc5dc1ef550a9313399bb9dc75cb1181bf19d1b872 : configuration.xml
cb2e9847e83ba655f685504a09fd78cce2068b6b60e441262fa7a68061741e36 : luti.json
c2c04e9fe3d251292f1435abe46fa61587e13aa7805fc690cd61f39a9822e2d9 : setup.exe
2aee81c583fd3ed7324e3d7606b78e502eeaf8c3dd9da0e215d8e5e5a53aadaa : setup.py
253f0ac3ab3e7dac7aa743a436b5f0cf5c85ec36c26125796490880642c6a82a : setupdevhelpers.py
06551c84bc512b415697d9d201e2d37a0af50694e02e117d2dbadc8c89e3e5a9 : update_package.py