tis-microsoft-office-2024-professional icon

Office LTSC Professional Plus 2024

Silent install package for Office LTSC Professional Plus 2024

16.0.17932.20670-16
Office
Office

package           : tis-microsoft-office-2024-professional
version           : 16.0.17932.20670-16
architecture      : x64
section           : base
priority          : optional
name              : Office LTSC Professional Plus 2024
categories        : Office
maintainer        : WAPT Team,Tranquil IT,Jimmy PELÉ,Clément Baziret,Flavien Schelfaut
description       : Microsoft Office 2024 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,tis-microsoft-office-2021-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 2024 est une version de la suite Microsoft Office
description_pl    : Microsoft Office 2024 to wersja pakietu biurowego Microsoft Office
description_de    : Microsoft Office 2024 ist eine Version der Microsoft Office-Suite
description_es    : Microsoft Office 2024 es una versión del paquete Microsoft Office
description_pt    : O Microsoft Office 2024 é uma versão do pacote Microsoft Office
description_it    : Microsoft Office 2024 è una versione della suite Microsoft Office
description_nl    : Microsoft Office 2024 is een versie van de Microsoft Office-suite
description_ru    : Microsoft Office 2024 - это версия пакета Microsoft Office
audit_schedule    : 
editor            : Microsoft
keywords          : microsoft,office,2024,version,suite
licence           : proprietary_restricted,wapt_public
homepage          : https://www.office.com/
package_uuid      : 00a37263-06d0-43c6-9ffa-2de4f400a55b
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-11T10:02:27.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         : jirQlLxSZuTgLJnRqzwtWG6kTfLFRuzpwF1XD0lW+BpXhaLG9eSg1d/5rxGlEYCLVStiE101jEVNvVrlZVKbVjxBr3bfvPMOjBaVKcqAnYOS5I2IcKlb+MYLDdTPymx/04gZt2uNLkzldvHQnxchxvDe6EzwWB3XSdmooPGNnYeTte2WtVStfFbxmrC4dMg2GROCKuKIgiRJ7rssffX6MbtkdftUOOodVDkztFYS2N/Jdpazj0aiuHE2UAECeyKrTXxEZB/HAFRrYUYHHHPPC1E9fxz685SnjQ4yGQWYfFc7xHPB2VhOtv7pp5/ZFPKKCYzynz674aFoubaXy5CVlQ==

# -*- coding: utf-8 -*-
from setuphelpers import *
from setupdevhelpers 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

Office 2024 Deploy:
https://learn.microsoft.com/en-us/office/ltsc/2024/deploy
"""

app_uninstallkey = "ProPlus2024Volume - 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 *
from setupdevhelpers import *
import waptguihelper
import webbrowser
import os


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

5caa977cd46b5328a1dc3dff88c97f409547934c62916970f7cd338a50bd0fa5 : Office/Data/16.0.17932.20670/a640_exp.cab
b1d4be945c7d13b3ccfffa2a3cab347dd052680958f92042970519a36df92ff6 : Office/Data/16.0.17932.20670/i640.cab
8c3b977248589874a8ad266865c3d5b75fea6d89506ba10f4a768b33270e5205 : Office/Data/16.0.17932.20670/i640.cab.cat
0bb48a4cca3edd6d360227eacd7810d4515bf5e92cc27650881a44577f7cd5f0 : Office/Data/16.0.17932.20670/i641036.cab
f6fa2edba0a432f9fd8bdc6c7e4efa9db241eb851b84b357b94ebbc9f4afc1c7 : Office/Data/16.0.17932.20670/s640.cab
d911869c01a38ab13138ef02012146c2764ce26e9bcd227f885dab8bc364a6a9 : Office/Data/16.0.17932.20670/s641036.cab
11ec37bb1cede826bfe1b31c49f3b2dc7a906cab813599b06e373a5c731de7fd : Office/Data/16.0.17932.20670/sa640.cab
1ba5530eb9843cfb2f3b19b8f233092e6bd9e58d5f453129b817934692347a4e : Office/Data/16.0.17932.20670/stream.x64.fr-fr.dat
4fb4a2951c5bbf94adda4730b2eb4aff7be64937c94e841cc4b8a6d71b2ca93c : Office/Data/16.0.17932.20670/stream.x64.fr-fr.dat.cat
827b1592cd6e1258350ab941ba5eabe642ca731e86f840a688741ed8a3dcaed9 : Office/Data/16.0.17932.20670/stream.x64.x-none.arm64x.dat
ffb7b53557a91f8f5f1c43e3b875a8b41303a7e4c5abea4570255f7cda9bbe9c : Office/Data/16.0.17932.20670/stream.x64.x-none.arm64x.dat.cat
14ac5d8ce0e16596870f6f8e33be8ec5dd2d346d91d99de6c381f3ed2814d5d9 : Office/Data/16.0.17932.20670/stream.x64.x-none.dat
66f0da14759a91d9d7d618d8604297464e27ab0ae8d4df919bb1a0404498baaa : Office/Data/16.0.17932.20670/stream.x64.x-none.dat.cat
1e443bf6a8e9f23fdf15d08ebb27798579105dc993ab0ebf03f9813c5711d884 : Office/Data/v64.cab
1e443bf6a8e9f23fdf15d08ebb27798579105dc993ab0ebf03f9813c5711d884 : Office/Data/v64_16.0.17932.20670.cab
38d056ab130f7bf7c481c12636a4e9959de36561d3dfcbe54c6e3571bc0c1dc3 : WAPT/certificate.crt
4fad7ccfee5320c7aa649620a50517b89a61ba4c895ede999a2c2e4dc9ca39b1 : WAPT/control
2ac98141bf5b6777083f2bcbeab3ab034c01dff77718e108774575aaaa54a144 : WAPT/icon.png
a2cc0768f5cd836cd5952348c83b54394298d2725f344163f93cda0adfe9794d : configuration.xml
57313b0be0e313d5451934a1a9f7543043801a71e034f1d9a2f999e8f3057cd6 : luti.json
c2c04e9fe3d251292f1435abe46fa61587e13aa7805fc690cd61f39a9822e2d9 : setup.exe
8eecbef0647860ce74ffc6718b9c694ed4014d1ed8ddbe600896e9ad6937eb8a : setup.py
ff3eca9f30b2ddbc22eb722c7fa58cf21eb30c24b0676118b0e8ee87f4a04360 : update_package.py