How to Use PowerShell to Automate Office 365 Installations

In the fast-paced and demanding world of IT, every tool that saves time and simplifies tasks is worth its weight in gold. Today, we’re going to explore how PowerShell scripts can be utilized to automate the installation of Office 365, a critical operation that can save you countless hours in the long run. In fact, with a well-written script, you can manage installations across an entire network from your desk. This post is for IT professionals and Managed Service Providers (MSPs) who are looking to streamline their Office 365 deployments using the power of PowerShell.

Why Automate with PowerShell?

PowerShell is an advanced scripting language and shell developed by Microsoft. It’s been an integral part of the Windows ecosystem since Windows 7, and its power and flexibility have made it a vital tool for many IT professionals and MSPs. Automating Office 365 installations using PowerShell can drastically reduce the time and effort required to deploy Office 365 across multiple machines. 

Moreover, PowerShell scripts can be customized to suit your needs. For example, the script can be configured to install specific Office 365 components, apply certain settings, and even clean up after the installation. This level of customization allows IT professionals and MSPs to ensure that Office 365 is deployed consistently across all machines, aligning with the company’s IT policies and standards. 

A Deep Dive into the PowerShell Install Office 365 Script

Let’s take a closer look at an example PowerShell script for automating Office 365 installations. This script is designed to install Office 365 using either a custom configuration file or a default one. In the event that an installation fails, the script will provide an error message, making troubleshooting more straightforward.

What makes this script particularly useful is its ability to download and use the Office Deployment Tool from Microsoft’s servers. This feature ensures that the latest version of Office 365 is always used for the installation. Additionally, the script checks if the Office 365 suite was installed correctly, giving an extra layer of assurance.

Upon a successful installation, the script triggers a system reboot. This is particularly handy as some Office 365 components require a system restart to function correctly. The script is also equipped with a cleanup mechanism that can be activated to remove installation files after Office 365 has been installed.

Microsoft Office 365 Installation PowerShell Script


#Requires -Version 5.1

<#
.SYNOPSIS
    Installs Office 365 from a config file or creates a generic config file and installs.
.DESCRIPTION
    Installs Office 365 from a config file or creates a generic config file and installs.
.EXAMPLE
    No parameters need if you want to use the default config file OR change the $OfficeXML variable to use your XML config file's content.
.EXAMPLE
     -ConfigurationXMLFile https://replace.me/configuration.xml
    Install Office 365 and use a local config file.
    You can use https://config.office.com/deploymentsettings to help build the config file.
.OUTPUTS
    None
.NOTES
    This will reboot after a successful install.
    Minimum OS Architecture Supported: Windows 10, Windows Server 2016
    Release Notes: Renamed script and added Script Variable support, made restarts optional, changed default download path to %TEMP%\Office365Install, switched to downloading an xml instead of using a local path.
By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use.
    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
    Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
#>

[CmdletBinding()]
param(
    # Use a existing config file
    [Parameter()]
    [String]$ConfigurationXMLFile,
    # Path where we will store our install files and our XML file
    [Parameter()]
    [String]$OfficeInstallDownloadPath = "$env:TEMP\Office365Install",
    [Parameter()]
    [Switch]$Restart = [System.Convert]::ToBoolean($env:restartComputer)
)

begin {
    if ($env:linkToConfigurationXml -and $env:linkToConfigurationXml -notlike "null") { $ConfigurationXMLFile = $env:linkToConfigurationXml }

    $CleanUpInstallFiles = $True

    # In case 'https://' is omitted from the URL.
    if ($ConfigurationXMLFile -and $ConfigurationXMLFile -notmatch "^http(s)?://") {
        Write-Warning "http(s):// is required to download the file. Adding https:// to your input...."
        $ConfigurationXMLFile = "https://$ConfigurationXMLFile"
        Write-Warning "New Url $ConfigurationXMLFile."
    }

    # Set TLS Version
    $SupportedTLSversions = [enum]::GetValues('Net.SecurityProtocolType')
    if ( ($SupportedTLSversions -contains 'Tls13') -and ($SupportedTLSversions -contains 'Tls12') ) {
        [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol::Tls13 -bor [System.Net.SecurityProtocolType]::Tls12
    }
    elseif ( $SupportedTLSversions -contains 'Tls12' ) {
        [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
    }
    else {
        # Not everything requires TLS 1.2, but we'll try anyway.
        Write-Warning "TLS 1.2 and or TLS 1.3 are not supported on this system. This script may fail!"
        if ($PSVersionTable.PSVersion.Major -lt 3) {
            Write-Warning "PowerShell 2 / .NET 2.0 doesn't support TLS 1.2."
        }
    }

    function Set-XMLFile {
        # XML data that will be used for the download/install
        # Example config below generated from https://config.office.com/
        # To use your own config, just replace <Configuration> to </Configuration> with your xml config file content.
        # Notes:
        #  "@ can not have any character after it
        #  @" can not have any spaces or character before it.
        $OfficeXML = [XML]@"
<Configuration ID="76b3b530-54a8-44d8-9689-278ec2547592">
  <Info Description="Example O365 install" />
  <Add OfficeClientEdition="64" Channel="MonthlyEnterprise" MigrateArch="TRUE">
    <Product ID="O365BusinessRetail">
      <Language ID="MatchOS" />
      <Language ID="MatchPreviousMSI" />
      <ExcludeApp ID="Access" />
      <ExcludeApp ID="Groove" />
      <ExcludeApp ID="Lync" />
      <ExcludeApp ID="Publisher" />
    </Product>
  </Add>
  <Property Name="SharedComputerLicensing" Value="0" />
  <Property Name="FORCEAPPSHUTDOWN" Value="TRUE" />
  <Property Name="DeviceBasedLicensing" Value="0" />
  <Property Name="SCLCacheOverride" Value="0" />
  <Updates Enabled="TRUE" />
  <RemoveMSI />
  <AppSettings>
    <Setup Name="Company" Value="Ninja Example" />
    <User Key="software\microsoft\office\16.0\excel\options" Name="defaultformat" Value="51" Type="REG_DWORD" App="excel16" Id="L_SaveExcelfilesas" />
    <User Key="software\microsoft\office\16.0\powerpoint\options" Name="defaultformat" Value="27" Type="REG_DWORD" App="ppt16" Id="L_SavePowerPointfilesas" />
    <User Key="software\microsoft\office\16.0\word\options" Name="defaultformat" Value="" Type="REG_SZ" App="word16" Id="L_SaveWordfilesas" />
  </AppSettings>
  <Display Level="None" AcceptEULA="TRUE" />
  <Setting Id="SETUP_REBOOT" Value="Never" /> 
  <Setting Id="REBOOT" Value="ReallySuppress"/>
</Configuration>
"@
        #Save the XML file
        $OfficeXML.Save("$OfficeInstallDownloadPath\OfficeInstall.xml")
      
    }
    function Get-ODTURL {
    
        [String]$MSWebPage = Invoke-RestMethod 'https://www.microsoft.com/en-us/download/confirmation.aspx?id=49117'
    
        $MSWebPage | ForEach-Object {
            if ($_ -match 'url=(https://.*officedeploymenttool.*\.exe)') {
                $matches[1]
            }
        }
    
    }
    function Test-IsElevated {
        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
        $p = New-Object System.Security.Principal.WindowsPrincipal($id)
        if ($p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator))
        { Write-Output $true }
        else
        { Write-Output $false }
    }

    # Utility function for downloading files.
    function Invoke-Download {
        param(
            [Parameter()]
            [String]$URL,
            [Parameter()]
            [String]$Path,
            [Parameter()]
            [int]$Attempts = 3,
            [Parameter()]
            [Switch]$SkipSleep
        )
        Write-Host "URL given, Downloading the file..."

        $i = 1
        While ($i -le $Attempts) {
            # Some cloud services have rate-limiting
            if (-not ($SkipSleep)) {
                $SleepTime = Get-Random -Minimum 3 -Maximum 15
                Write-Host "Waiting for $SleepTime seconds."
                Start-Sleep -Seconds $SleepTime
            }
        
            if ($i -ne 1) { Write-Host "" }
            Write-Host "Download Attempt $i"

            try {
                # Invoke-WebRequest is preferred because it supports links that redirect, e.g., https://t.ly
                if ($PSVersionTable.PSVersion.Major -lt 4) {
                    # Downloads the file
                    $WebClient = New-Object System.Net.WebClient
                    $WebClient.DownloadFile($URL, $Path)
                }
                else {
                    # Standard options
                    $WebRequestArgs = @{
                        Uri                = $URL
                        OutFile            = $Path
                        MaximumRedirection = 10
                        UseBasicParsing    = $true
                    }

                    # Downloads the file
                    Invoke-WebRequest @WebRequestArgs
                }

                $File = Test-Path -Path $Path -ErrorAction SilentlyContinue
            }
            catch {
                Write-Warning "An error has occurred while downloading!"
                Write-Warning $_.Exception.Message

                if (Test-Path -Path $Path -ErrorAction SilentlyContinue) {
                    Remove-Item $Path -Force -Confirm:$false -ErrorAction SilentlyContinue
                }

                $File = $False
            }

            if ($File) {
                $i = $Attempts
            }
            else {
                Write-Warning "File failed to download."
                Write-Host ""
            }

            $i++
        }

        if (-not (Test-Path $Path)) {
            Write-Error -Message "Failed to download file!" -Category InvalidResult -Exception (New-Object System.Deployment.Application.DeploymentDownloadException)
            exit 1
        }
    }

    # Check's the two Uninstall registry keys to see if the app is installed. Needs the name as it would appear in Control Panel.
    function Find-UninstallKey {
        [CmdletBinding()]
        param (
            [Parameter(ValueFromPipeline)]
            [String]$DisplayName,
            [Parameter()]
            [Switch]$UninstallString
        )
        process {
            $UninstallList = New-Object System.Collections.Generic.List[Object]

            $Result = Get-ChildItem HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Get-ItemProperty | 
                Where-Object { $_.DisplayName -like "*$DisplayName*" }

            if ($Result) { $UninstallList.Add($Result) }

            $Result = Get-ChildItem HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Get-ItemProperty | 
                Where-Object { $_.DisplayName -like "*$DisplayName*" }

            if ($Result) { $UninstallList.Add($Result) }

            # Programs don't always have an uninstall string listed here so to account for that I made this optional.
            if ($UninstallString) {
                # 64 Bit
                $UninstallList | Select-Object -ExpandProperty UninstallString -ErrorAction Ignore
            }
            else {
                $UninstallList
            }
        }
    }
}
process {
    $VerbosePreference = 'Continue'
    $ErrorActionPreference = 'Stop'

    if (-not (Test-IsElevated)) {
        Write-Error -Message "Access Denied. Please run with Administrator privileges." -Category PermissionDenied -Exception (New-Object System.Security.SecurityException)
        exit 1
    }

    if (-not (Test-Path $OfficeInstallDownloadPath )) {
        New-Item -Path $OfficeInstallDownloadPath -ItemType Directory | Out-Null
    }

    if (-not ($ConfigurationXMLFile)) {
        Set-XMLFile
    }
    else {
        Invoke-Download -URL $ConfigurationXMLFile -Path "$OfficeInstallDownloadPath\OfficeInstall.xml"
    }

    $ConfigurationXMLFile = "$OfficeInstallDownloadPath\OfficeInstall.xml"
    $ODTInstallLink = Get-ODTURL

    #Download the Office Deployment Tool
    Write-Host 'Downloading the Office Deployment Tool...'
    Invoke-Download -URL $ODTInstallLink -Path "$OfficeInstallDownloadPath\ODTSetup.exe"

    #Run the Office Deployment Tool setup
    try {
        Write-Host 'Running the Office Deployment Tool...'
        Start-Process "$OfficeInstallDownloadPath\ODTSetup.exe" -ArgumentList "/quiet /extract:$OfficeInstallDownloadPath" -Wait -NoNewWindow
    }
    catch {
        Write-Warning 'Error running the Office Deployment Tool. The error is below:'
        Write-Warning $_
        exit 1
    }

    #Run the O365 install
    try {
        Write-Host 'Downloading and installing Microsoft 365'
        $Install = Start-Process "$OfficeInstallDownloadPath\Setup.exe" -ArgumentList "/configure $ConfigurationXMLFile" -Wait -PassThru -NoNewWindow

        if ($Install.ExitCode -ne 0) {
            Write-Error -Message "Exit Code does not indicate success!" -Category InvalidResult -Exception (New-Object System.Deployment.Application.DeploymentException)
            exit 1
        }
    }
    Catch {
        Write-Warning 'Error running the Office install. The error is below:'
        Write-Warning $_
    }

    $OfficeInstalled = Find-UninstallKey -DisplayName "Microsoft 365"

    if ($CleanUpInstallFiles) {
        Write-Host "Cleaning up install files..."
        Remove-Item -Path $OfficeInstallDownloadPath -Force -Recurse
    }

    if ($OfficeInstalled) {
        Write-Host "$($OfficeInstalled.DisplayName) installed successfully!"
        if ($Restart) { Start-Process shutdown.exe -ArgumentList "-r -t 60" -Wait -NoNewWindow }
        exit 0
    }
    else {
        Write-Error -Message 'Microsoft 365 was not detected after the install ran!' -Category InvalidResult -Exception (New-Object System.Deployment.Application.DeploymentException)
        exit 1
    }
}
end {
    
    
    
}

 

Access over 700+ scripts in the NinjaOne Dojo

Get Access

Script Example Scenarios

Scenario 1: Large Scale Deployment

Suppose you’re an IT administrator in a company that’s about to onboard a hundred new employees. Manually installing Office 365 on each computer would be a daunting task. Instead, you can use this PowerShell script to automate the process. Using NinjaOne to execute the script remotely on each device, you can standardize your Office 365 installations across the entire network. This streamlined approach not only saves valuable time but also guarantees uniformity, an essential feature for effectively managing a large IT infrastructure.

Learn more about how NinjaOne can improve your IT infrastructure’s efficiency.  

Link: https://www.ninjaone.com/efficiency/

Scenario 2: Remote Workforce 

With the rise of remote work, many companies have employees working from various locations on their own devices. Ensuring each remote worker has a correctly installed and configured version of Office 365 can be a challenge. By distributing this PowerShell script to your remote workforce, they can perform the installation themselves. The script ensures that Office 365 is installed correctly and configured based on your organization’s standards.

Scenario 3: MSP Client Management

As a Managed Service Provider (MSP), you might be managing IT for several small businesses, each with their own specific needs and configurations. With this PowerShell script, you can create multiple XML configuration files tailored to each client’s needs. When it’s time to install or update Office 365 for a client, simply run the script with the appropriate configuration file. This ensures a customized and consistent Office 365 setup for each of your clients. 

Scenario 4: Regular Updates  

Office 365 is updated regularly by Microsoft, and keeping your organization’s installations up-to-date can be a time-consuming task. With this script, you can schedule automated updates to run at a suitable time, ensuring minimal disruption to your team’s workflow. The script uses the Office Deployment Tool to download and install the latest version of Office 365, ensuring your team always has access to the latest features and security updates. 

In each of these scenarios, this PowerShell script can significantly simplify the process of installing and managing Office 365. By automating these tasks, you can save time, reduce the risk of errors, and ensure a consistent and reliable Office 365 experience for your users. 

Utilizing the Script in Your Workflow

Integrating this PowerShell script into your workflow can simplify the process of deploying Office 365. Instead of manually downloading and running the Office Deployment Tool on each machine, the script can be executed remotely from a central location. This reduces the chances of human error and ensures a standard configuration across all installations.

Moreover, by customizing the XML configuration file, you can tailor the Office 365 installation to your organization’s needs. This includes specifying the Office 365 version, the update channel, and even the individual Office components to be installed.

Final Thoughts

Automation is an IT professional’s best friend, and PowerShell offers a powerful way to automate Office 365 installations. This handy script not only streamlines the deployment process but also provides customization options and cleanup functionality.

By integrating this script into your workflow, you can significantly reduce the time and effort involved in managing Office 365 installations across your network. So, embrace the power of PowerShell and make Office 365 deployments a breeze.

NinjaOne can streamline your operations by automating repetitive and time-consuming tasks. Its user-friendly interface allows technicians of all levels to easily apply automation across endpoints, including custom scripts from an extensive library, making remediation simple and intuitive. As Crossroads Church’s Chris Hesler noted, “NinjaOne has helped us…cut back on the man hours…we are able to bring more automation with the script library to solve our recurring issues.” Discover the transformative power of automation in your IT operations with NinjaOne, a tool designed with flexibility and intuitiveness at its core. 

Add a Comment

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

Next Steps

Building an efficient and effective IT team requires a centralized solution that acts as your core service deliver tool. NinjaOne enables IT teams to monitor, manage, secure, and support all their devices, wherever they are, without the need for complex on-premises infrastructure.

Learn more about NinjaOne Remote Script Deployment, check out a live tour, or start your free trial of the NinjaOne platform.

Categories:

You might also like

Watch Demo×
×

See NinjaOne in action!

By submitting this form, I accept NinjaOne's privacy policy.

NinjaOne Terms & Conditions

By clicking the “I Accept” button below, you indicate your acceptance of the following legal terms as well as our Terms of Use:

  • Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms.
  • Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party.
  • Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library belonging to or under the control of any other software provider.
  • Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations.
  • Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks.
  • Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script.
  • EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).