Deploy MS365 Apps via a Win32 app

Introduction

Microsoft 365 apps can be installed through the XML method provided by Microsoft via Intune. However, it has been observed that this method can sometimes be unpredictable, especially on Surface devices where many languages and versions are preinstalled.
To gain more control over the installation process and create better logging, the apps can also be installed via a Win32 app. The downside of this approach is the need to package a new version each time. The method described below eliminates this need. This script always downloads the latest version, just like the XML method, and installs it accordingly.

ℹ️

Within the script, some variables have been made global, as normal variables exhibited strange behavior in Windows 11 23H2.

This script automates the installation or uninstallation of Microsoft Office 365 by utilizing the Office Deployment Tool (ODT) package and XML configuration files. It ensures that the necessary files are downloaded, languages are specified, and the installation or uninstallation process is executed accordingly.

Just modify the script and the XML files to your liking. Package it to an IntuneWin (Win32 app) and deploy it to the devices via Intune.

ℹ️

The script can also be used for single Visio or Project on top of the Office 365 installation

  1. Function Definition: The script defines a function called Get-OfficeSource. This function is responsible for downloading the Office Deployment Tool (ODT) package if it is not already present on the system.
  2. Check if Office 365 is already installed: The script checks if Microsoft Office 365 is already installed by verifying the existence of the OfficeClickToRun.exe file in the specified path ($Office365Path). If it is installed, the script proceeds with the uninstallation process.
  3. Uninstallation Section: If Office 365 is installed, the script enters the uninstallation section. It first displays the list of installed components of Office 365 by querying the Windows registry. Then, it checks if the original setup files are present on the system. If not, it calls the Get-OfficeSource function to download the Office Deployment Tool (ODT) package. After that, it specifies the languages to uninstall in an XML file (Uninstall_[Productname]_Languages.xml) and initiates the uninstallation process using the Office Deployment Tool.
  4. Installation Section: If Office 365 is not installed, the script enters the installation section. It calls the Get-OfficeSource function to download the Office Deployment Tool (ODT) package. Then, it initiates the installation process using the Office Deployment Tool and an XML file (Install_[Productname].xml) that contains the configuration settings for the installation.
  5. Cleanup Section: After the installation or uninstallation process is complete, the script performs some cleanup tasks. It removes the downloaded Office Deployment Tool (ODT) file and stops the logging by using the Stop-Transcript cmdlet.

The scripts and the corresponding xml files can be downloaded from my github:

Install Office365
Install Visio
Install Project

<#
###################
Authors: M van Rijn - Prodicom 
Remco van Diermen - RvD IT Consulting

# --- UNINSTALL ---
# Some vendors pre-install [Productname], such as Microsoft Surface devices
# Specify all languages to uninstall in file "Uninstall_[Productname]_Languages.xml"
# If no languages need to be removed, only add the required languages to the XML file
# If the uninstall section is not required, remove it

# --- INSTALL ---
# Specify languages in "Install_[Productname].xml" for installation

1. Check if [Productname] is installed
--> YES
Remove languages specified in Uninstall_[Productname]_Languages.xml, end logging and script
--> NO
- Create download folder for Officedeploymenttool
- Download latest version of the Officedeploymenttool
- Unpack Officedeploymenttool
- Download [Productname] via Officedeploymenttool and Install_[Productname].xml to the (package) $Global:DownloadAppFolder
- Install [Productname] via Officedeploymenttool and Install_[Productname].xml

The Officedeploymenttool folder will remain on the device for uninstall
####################
#>

# Vars
$Date = (Get-Date).tostring("yyyy-MM-dd HHmm")
$Global:ProductName = "Office365"
$Global:ExtractAppFolder = "Officedeploymenttool"
$Global:ODTExe = "officedeploymenttool.exe"
$Global:DownloadAppFolder = "C:\ProgramData\Intune\Packages\$($Global:ProductName)"
$LogFile = "C:\Programdata\Microsoft\IntuneManagementExtension\Logs\Logs_$($Global:ProductName)_install_$($Date).log"
$Global:installFolder = "$PSScriptRoot"
$Office365Path = "C:\Program Files\Common Files\Microsoft Shared\ClickToRun\OfficeClickToRun.exe"
$Url = "https://www.microsoft.com/en-us/download/confirmation.aspx?id=49117"
$Response = Invoke-WebRequest -UseBasicParsing -Uri $url -ErrorAction SilentlyContinue
$Global:SetupEXEFile = "$Global:DownloadAppFolder\$Global:ExtractAppFolder\Setup.exe"
$Global:InstallXML = "Install_$Global:ProductName.xml"
$UnInstallXML = "Uninstall_$($Global:ProductName)_Languages.xml"

# Start Logging
Start-Transcript -Path $LogFile

# Functions
Function Get-OfficeSource {
    Write-host "Setup.exe for uninstall not found. Download ODT package"
    ###########################
    # FOLDER CREATION SECTION #
    ###########################
    # Check if folder exist else create
    If (!(Test-Path $Global:DownloadAppFolder)) {
        # Create directory
        Write-Host "Create ODT package folder: $Global:DownloadAppFolder"
        New-item -path "$Global:DownloadAppFolder" -ItemType "directory"
    }

    ####################
    # DOWNLOAD SECTION #
    ####################
    # Get Download URL of latest Office Deployment Tool (ODT)
    $ODTUri = $response.links | Where-Object {$_.outerHTML -like "*click here to download manually*"}
    $UrlCurrentVerODT = $ODTUri.href
    # Download latest Office Deployment Tool (ODT)
    Write-Host "Downloading latest version of Office Deployment Tool (ODT)."
    Invoke-WebRequest -UseBasicParsing -Uri $UrlCurrentVerODT -OutFile $Global:DownloadAppFolder\$Global:ODTExe
    # Get file version
    Write-Host "Get fileversion Office Deployment Tool (ODT)."
    $Version = (Get-Command $Global:DownloadAppFolder\$Global:ODTExe).FileVersionInfo.FileVersion
    Write-Host "Fileversion Office Deployment Tool (ODT): " $Version
    # Unpack ODT File
    Write-Host "Unpacking file ..."
    $arguments1 = "/quiet /extract:$Global:DownloadAppFolder\$Global:ExtractAppFolder"
    Start-Process -Wait -FilePath "$Global:DownloadAppFolder\$Global:ODTExe" -ArgumentList $arguments1
    Start-sleep -s 5
    # Download
    $arguments1 = "/download $Global:installFolder\$Global:InstallXML" 
    Write-Host "Start download via $Global:SetupEXEFile  $arguments1..."
    Start-Process -Wait -FilePath "$Global:SetupEXEFile" -ArgumentList $arguments1
}

# Check if [Productname] (64 bits) is already installed

If (Test-Path $Office365Path) {
    #####################
    # UNINSTALL SECTION #
    #####################
    Write-Host "$Global:ProductName installation found..."
    # Getting installed components   
    Write-host "Installed $Global:ProductName components..." 
    Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\O365ProPlusRetail* | Select-Object DisplayName -expandproperty Displayname

    # Check if original Setup files are present on the system, if not download ODT
    If (!(Test-Path $Global:SetupEXEFile)) {Get-OfficeSource} # Call Function

    # Specify all languages to uninstall in file "Uninstall_[Productname]_Languages.xml"
    # If the languages to uninstall need to be defined first, run the commands above (Get-ItemProperty..) on an identical device and update the file "Uninstall_[Productname]_Languages.xml"
    # Uninstall languages
    Write-Host "Uninstall $Global:ProductName languages...based on XML $Global:installFolder\$UnInstallXML"
    $arguments1 = "/configure $Global:installFolder\$UnInstallXML" 
    Start-Process -Wait -FilePath "$Global:SetupEXEFile" -ArgumentList $arguments1
    
} Else {
    Write-Host "No $Global:ProductName installation found. Download and install $Global:ProductName..."
    Get-OfficeSource # Call Function download ODT

    # Install
    Write-Host "Installing $Global:ProductName..."
    $arguments1 = "/configure $Global:installFolder\$Global:InstallXML" 
    Start-Process -Wait -FilePath "$Global:SetupEXEFile" -ArgumentList $arguments1
}

###################
# CLEANUP SECTION #
###################
Start-sleep -s 5
# Cleanup ODT file. Folder with officedeploymenttool and software will remain for uninstall. Change if needed
Write-Host "Cleanup ODT download file"
Remove-Item "$Global:DownloadAppFolder\$Global:ODTExe"

Start-sleep -s 20

# Stop Logging
Stop-Transcript

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *