import os
import sys
install_office = itsm.getParameter('Install_Office')
install_editions = ",".join(itsm.getParameter('Install_Office_Edition'))
Install_Office_Channel = ",".join(itsm.getParameter('Install_Office_Channel'))
install_download_path = itsm.getParameter('Install_Office_Download_Path')
install_with_odt = itsm.getParameter('Install_Office_WITH_XML')
install_with_odt_path = itsm.getParameter('Install_Office_WITH_XML_PATH')
remove_office_only = itsm.getParameter('Remove_Office365_Only')
remove_office_only_edition = ",".join(itsm.getParameter('Remove_Office_Only_Edition'))
excluded_apps = ",".join(itsm.getParameter('Install_Office_Exclude_Apps'))
ps_content=r'''
<#
.Name
EZT-DeployO365
.Version
0.5
.SYNOPSIS
Automates silent install or removal of Office 365 editions using the Office Deployment Tookit, allowing custom config XML generation and removal of existing/older Office installs
.DESCRIPTION
.Configurable Variables
.Requirements
- Powershell v3.0 or higher
.Function Get-Something
Function description
.EXAMPLE
.\EZT-DeployO365.ps1
.OUTPUTS
System.Management.Automation.PSObject
.Credits
Install-Office365Suite - https://github.com/mallockey/Install-Office365Suite
Get-OfficeVersion - https://github.com/OfficeDev/Office-IT-Pro-Deployment-Scripts/tree/master/Office-ProPlus-Deployment/Remove-PreviousOfficeInstalls
Write-Color - https://github.com/EvotecIT/PSWriteColor
.NOTES
Author: EZTechhelp
Site : https://www.eztechhelp.com
#>
#############################################################################
#region Configurable Script Parameters
#############################################################################
#----------------------------------------------
#region Function Select Variables
#----------------------------------------------
$Install_Office = ''' + install_office + ''' #installs Office 365 using config values set in this script
$Install_Office_Edition = "''' + install_editions + '''" #Office edition to be installed
$Install_Office_Edition = $Install_Office_Edition.split(',') | Select -First 1
$Install_Office_Download_Path = "''' + install_download_path + '''" #directory where the Office 365 setup and ODT files should be downloaded
$Remove_Install_Office_Download_Path = 0 #enable to remove the folder and all downloaded files from the path defined in Install_Office_Download_Path after execution completes
$Install_Office_WITH_ODT = ''' + install_with_odt + ''' #installs Office using an existing Office 365 ODT configuration XML file
$Install_Office_WITH_ODT_XMLFILE = "''' + install_with_odt_path + '''" #Full path to an existing Office365 ODT Configuration XML file to use with deployment.To config or create a configuration file, recommend visiting https://config.office.com
$Remove_Office_Only = ''' + remove_office_only + ''' #removes any detected office installations without installing another
$Remove_Office_Only_Edition = "''' + remove_office_only_edition + '''" #optionally removes only this edition of office
#The following variables are ignored if $Install_Office_WITH_ODT_XMLFILE is configured
$Install_Office_Channel = "''' + Install_Office_Channel + '''" #Defines which channel to use for installing Office
$Install_Office_Channel = $Install_Office_Channel.split(',') | Select -First 1
$Install_Office_Source_Path = "''' + itsm.getParameter('Install_Office_Source_Path') + '''" #Path where Office installation files will be saved and deployed from.
$Install_Office_Exclude_Apps = "''' + excluded_apps + '''"
$Install_Office_Exclude_Apps = $Install_Office_Exclude_Apps.split(',')
$Install_Office_Org_Name = "''' + itsm.getParameter('Install_Office_Org_Name') + '''"
$Install_Office_Shared_Computer_Licensing = ''' + itsm.getParameter('Install_Office_Shared_Computer_Licensing') + '''
$Install_Office_Remove_Previous_Intalls = ''' + itsm.getParameter('Install_Office_Remove_Previous_Installs') + '''
$Install_Office_Accept_EULA = ''' + itsm.getParameter('Install_Office_Accept_EULA') + '''
$Install_Office_Enable_Updates = ''' + itsm.getParameter('Install_Office_Enable_Updates') + '''
$Install_Office_Display_Install = ''' + itsm.getParameter('Install_Office_Display_Install') + '''
$Install_Office_AUTO_ACTIVATE = ''' + itsm.getParameter('Install_Office_AUTO_ACTIVATE') + '''
$Install_Office_FORCE_APPSHUTDOWN = ''' + itsm.getParameter('Install_Office_FORCE_APPSHUTDOWN') + '''
#----------------------------------------------
#endregion Function Select Variables
#----------------------------------------------
#----------------------------------------------
#region Global Variables - DO NOT CHANGE UNLESS YOU KNOW WHAT YOU'R DOING
#----------------------------------------------
$script:stopwatch = [system.diagnostics.stopwatch]::StartNew() #starts stopwatch timer
$Required_modules = 'PSWriteColor' #these modules are automatically installed and imported if not already
$enablelogs = 1
$logfile_directory = "''' + itsm.getParameter('LogFile_Directory') + '''"
$Copy_SetupLog = ''' + itsm.getParameter('Copy_SetupLog') + '''
$LogFileAppend = $true #enables appending to existing log file. Disabled overwrites previous log file content
$logtime = $true
$logdateformat = 'MM/dd/yyyy h:mm:ss tt' # sets the date/time appearance format for log file and console messages
$update_modules = $false # enables checking for and updating all required modules for this script. Potentially adds a few seconds to total runtime but ensures all modules are the latest
$force_modules = $false # enables installing and importing of a module even if it is already. Should not be used unless troubleshooting module issues
#----------------------------------------------
#endregion Global Variables - DO NOT CHANGE UNLESS YOU KNOW WHAT YOU'R DOING
#----------------------------------------------
#############################################################################
#endregion Configurable Script Parameters
#############################################################################
#############################################################################
#region global functions - Functions that are commonly used across scripts and must be run first
#############################################################################
#----------------------------------------------
#region Get-ThisScriptInfo Function
#----------------------------------------------
function Get-ThisScriptInfo
{
$Invocation = (Get-Variable MyInvocation -Scope 1).Value
$ScriptPath = $PSCommandPath
if(!$ScriptPath)
{
$ScriptPath = Split-Path -Parent -Path $MyInvocation.MyCommand
$thisScript = @{File = Get-ChildItem $ScriptPath; Contents = $Invocation.MyCommand}
}
else
{$thisScript = @{File = Get-ChildItem $ScriptPath; Contents = $Invocation.MyCommand.ScriptContents}}
If ($thisScript.Contents -Match '^\s*\<#([\s\S]*?)#\>')
{$thisScript.Help = $Matches[1].Trim()}
[RegEx]::Matches($thisScript.Help, "(^|[`r`n])\s*\.(.+)\s*[`r`n]|$") | ForEach-Object {
If ($Caption)
{$thisScript.$Caption = $thisScript.Help.SubString($Start, $_.Index - $Start)}
$Caption = $_.Groups[2].ToString().Trim()
$Start = $_.Index + $_.Length
}
$thisScript.Version = $thisScript.Version.Trim()
$thisScript.Name = $thisScript.Name.Trim()
$thisScript.credits = $thisScript.credits -split("`n") | ForEach-Object {$_.trim()}
$thisScript.SYNOPSIS = $thisScript.SYNOPSIS -split("`n") | ForEach-Object {$_.trim()}
$thisScript.Description = $thisScript.Description -split("`n") | ForEach-Object {$_.trim()}
$thisScript.Notes = $thisScript.Notes -split("`n") | ForEach-Object {$_.trim()}
$thisScript.Path = $thisScript.File.FullName; $thisScript.Folder = $thisScript.File.DirectoryName; $thisScript.BaseName = $thisScript.File.BaseName
$thisScript.Arguments = (($Invocation.Line + ' ') -Replace ('^.*\\\\' + $thisScript.File.Name.Replace('.', '\.') + "['"" ]"), '').Trim()
[System.Collections.Generic.List[String]]$FX_NAMES = New-Object System.Collections.Generic.List[String]
if(!([System.String]::IsNullOrWhiteSpace($thisScript.file)))
{
Select-String -Path $thisScript.file -Pattern "function" |
ForEach-Object {
[System.Text.RegularExpressions.Regex] $regexp = New-Object Regex("(function)( +)([\w-]+)")
[System.Text.RegularExpressions.Match] $match = $regexp.Match("$_")
if($match.Success)
{
$FX_NAMES.Add("$($match.Groups[3])")
}
}
$thisScript.functions = $FX_NAMES.ToArray()
}
$Script_Temp_Folder = "$env:TEMP\$($thisScript.Name)"
if(!(Test-Path $Script_Temp_Folder))
{
try
{$null = New-Item $Script_Temp_Folder -ItemType Directory -Force}
catch
{Write-EZLogs "[ERROR] Exception creating script temp directory $Script_Temp_Folder - $_" -ShowTime -color Red}
}
Write-Host "#### Executing $($thisScript.Name) - v$($thisScript.Version) ####" -ForegroundColor Black -BackGroundColor yellow
Write-Host " | $($thisScript.SYNOPSIS)"
return $thisScript
}
$thisScript = Get-ThisScriptInfo
#----------------------------------------------
#endregion Get-ThisScriptInfo Function
#----------------------------------------------
#----------------------------------------------
#region Begin Logging
#----------------------------------------------
function Start-EZLogs
{
param (
[switch]$VerboseDebug,
[switch]$Enablelogs,
[switch]$LogFileAppend = $LogFileAppend,
[string]$logfile_directory,
[switch]$Start_Timer
)
$logfile = [System.IO.Path]::Combine($logfile_directory, "$($thisScript.Name)-$($thisScript.Version).log")
if (!(Test-Path -LiteralPath $logfile 2> $null))
{$null = New-Item -Path $logfile_directory -ItemType directory -Force}
$OriginalPref = $ProgressPreference
$ProgressPreference = 'SilentlyContinue'
$Computer_Info = Get-WmiObject Win32_ComputerSystem | Select-Object *
$OS_Info = Get-CimInstance Win32_OperatingSystem | Select-Object *
$CPU_Name = (Get-WmiObject Win32_Processor -Property 'Name').name
$ProgressPreference = $OriginalPref
$logheader = @"
`n###################### Logging Enabled ######################
Script Name : $($thisScript.Name)
Synopsis : $($thisScript.SYNOPSIS)
Log File : $logfile
Version : $($thisScript.Version)
Current Username : $env:username
Powershell : $($PSVersionTable.psversion)($($PSVersionTable.psedition))
Computer Name : $env:computername
Operating System : $($OS_Info.Caption)($($OS_Info.Version))
CPU : $($CPU_Name)
RAM : $([Math]::Round([int64]($computer_info.TotalPhysicalMemory)/1MB,2)) GB (Available: $([Math]::Round([int64]($OS_Info.FreePhysicalMemory)/1MB,2)) GB)
Manufacturer : $($computer_info.Manufacturer)
Model : $($computer_info.Model)
Serial Number : $((Get-WmiObject Win32_BIOS | Select-Object SerialNumber).SerialNumber)
Domain : $($computer_info.Domain)
Install Date : $($OS_Info.InstallDate)
Last Boot Up Time : $($OS_Info.LastBootUpTime)
Local Date/Time : $($OS_Info.LocalDateTime)
Windows Directory : $($OS_Info.WindowsDirectory)
###################### Logging Started - [$(Get-Date)] ##########################
"@
Write-Output $logheader | Out-File -FilePath $logfile -Encoding unicode -Append:$LogFileAppend
Write-Host " | Logging is enabled. Log file: $logfile"
return $logfile
}
$script:logfile = Start-EZLogs -logfile_directory $logfile_directory -Enablelogs:([System.Convert]::ToBoolean($enablelogs)) -LogFileAppend:$LogFileAppend
#----------------------------------------------
#endregion Begin Logging
#----------------------------------------------
#----------------------------------------------
#region Load-Modules Function
#----------------------------------------------
function Load-Modules ($modules,$force,$update,$enablelogs)
{
#Make sure we can download and install modules through NuGet
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
if (Get-PackageProvider | Where-Object {$_.Name -eq 'Nuget'})
{Write-Output ' | Required PackageProvider Nuget is installed.' -OutVariable message;if($enablelogs){$message | Out-File -FilePath $logfile -Encoding unicode -Append}}
else
{
try
{
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
Register-PackageSource -Name nuget.org -Location https://www.nuget.org/api/v2 -ProviderName NuGet
}
catch
{Write-Error "[Load-Module ERROR] $_`n" -ErrorVariable messageerror;if($enablelogs){$messageerror | Out-File -FilePath $logfile -Encoding unicode -Append}}
}
#Install latest version of PowerShellGet
if (Get-Module 'PowershellGet' | Where-Object {$_.Version -lt '2.2.5'})
{
Write-Output ' | PowershellGet version too low, updating to 2.2.5' -OutVariable message;if($enablelogs){$message | Out-File -FilePath $logfile -Encoding unicode -Append}
Install-Module -Name 'PowershellGet' -MinimumVersion '2.2.5' -Force
}
foreach ($m in $modules)
{
if (Get-Module | Where-Object {$_.Name -eq $m})
{
Write-Output " | Required Module $m is imported." -OutVariable message;if($enablelogs){$message | Out-File -FilePath $logfile -Encoding unicode -Append}
if ($force)
{
Write-Output " | Force parameter applied - Installing $m" -OutVariable message;if($enablelogs){$message | Out-File -FilePath $logfile -Encoding unicode -Append}
Install-Module -Name $m -Scope AllUsers -Force -Verbose
}
}
else
{
#If module is not imported, but available on disk set module autoloading when needed/called
if (Get-Module -ListAvailable | Where-Object {$_.Name -eq $m})
{
Write-Output " | Required Module $m is available on disk." -OutVariable message;if($enablelogs){$message | Out-File -FilePath $logfile -Encoding unicode -Append}
$PSModuleAutoLoadingPreference = 'ModuleQualified'
if($update)
{
Write-Output " | Updating module: $m" -OutVariable message;if($enablelogs){$message | Out-File -FilePath $logfile -Encoding unicode -Append}
Update-Module -Name $m -Force -ErrorAction Continue
}
if($force)
{
if($enablelogs){Write-Output " | Force parameter applied - Importing $m" | Out-File -FilePath $logfile -Encoding unicode -Append}
Import-Module $m -Verbose -force -Scope Global
}
}
else
{
#If module is not imported, not available on disk, but is in online gallery then install and import
if (Find-Module -Name $m | Where-Object {$_.Name -eq $m})
{
try
{
Install-Module -Name $m -Force -Verbose -Scope AllUsers -AllowClobber
Import-Module $m -Verbose -force -Scope Global
}
catch
{Write-Error "[Load-Module ERROR] $_" -ErrorVariable messageerror;if($enablelogs){$messageerror | Out-File -FilePath $logfile -Encoding unicode -Append}}
}
else
{
#If module is not imported, not available and not in online gallery then abort
Write-Error "[Load-Module ERROR] Required module $m not imported, not available and not in online gallery, exiting." -ErrorVariable messageerror;if($enablelogs){$messageerror | Out-File -FilePath $logfile -Encoding unicode -Append}
EXIT 1
}
}
}
}
}
Load-Modules -modules $Required_modules -force:$force_modules -update:$update_modules -enablelogs:([System.Convert]::ToBoolean($enablelogs))
#----------------------------------------------
#endregion Load-Modules Function
#----------------------------------------------
#----------------------------------------------
#region Write-EZLogs Function
#----------------------------------------------
function Write-EZLogs
{
[CmdletBinding(DefaultParameterSetName = 'text')]
param (
[string]$text,
[switch]$VerboseDebug,
[switch]$enablelogs = ([System.Convert]::ToBoolean($enablelogs)),
[switch]$LogFileOnly,
[string]$logfile = $logfile,
[switch]$Warning,
[string]$DateTimeFormat = $logdateformat,
[ValidateSet('Black','Blue','Cyan','Gray','Green','Magenta','Red','White','Yellow','DarkBlue','DarkCyan','DarkGreen','DarkMagenta','DarkRed','DarkYellow')]
[string]$color = 'white',
[switch]$showtime,
[switch]$logtime = $logtime,
[switch]$NoNewLine,
[ValidateSet('Black','Blue','Cyan','Gray','Green','Magenta','Red','White','Yellow','DarkBlue','DarkCyan','DarkGreen','DarkMagenta','DarkRed','DarkYellow')]
[string]$BackgroundColor,
[int]$linesbefore,
[int]$linesafter
)
if($showtime){$logtime = $true}else{$logtime = $false}
if($logtime){$logdatetime = "[$(Get-Date -Format $DateTimeFormat)] "}
if($BackgroundColor){$BackgroundColor_param = $BackgroundColor}else{$BackgroundColor_param = $null}
if($linesBefore){$text = "`n$text"}
if($linesAfter){$text = "$text`n"}
if($enablelogs)
{
if($VerboseDebug -and $warning)
{
$tmp = [System.IO.Path]::GetTempFileName();
Write-Color -showtime -NoNewLine -DateTimeFormat:$DateTimeFormat;Write-Warning ($wrn = "$text");Write-Output "$logdatetime[WARNING] $wrn" | Out-File -FilePath $logfile -Encoding unicode -Append -Verbose:$VerboseDebug 4>$tmp
$result = "[DEBUG] $(Get-Content $tmp)" | Out-File $logfile -Encoding unicode -Append;Remove-Item $tmp
}
elseif($Warning)
{
if($LogfileOnly)
{
Write-Output "$logdatetime[WARNING] $text" | Out-File -FilePath $logfile -Encoding unicode -Append
}
else
{
Write-Color -showtime -NoNewLine -DateTimeFormat:$DateTimeFormat;Write-Warning ($wrn = "$text");Write-Output "$logdatetime[WARNING] $wrn" | Out-File -FilePath $logfile -Encoding unicode -Append
}
}
else
{
if($LogfileOnly)
{
Write-Output "$logdatetime$text" | Out-File -FilePath $logfile -Encoding unicode -Append
}
else
{
Write-Color $text -color:$color -showtime:$showtime -LogTime:$logtime -LogFile:$logfile -NoNewLine:$NoNewLine -DateTimeFormat:$DateTimeFormat -BackGroundColor $BackgroundColor_param
}
}
}
else
{
if($warning)
{Write-Color -showtime -NoNewLine -DateTimeFormat:$DateTimeFormat;Write-Warning ($wrn = "$text")}
else
{Write-Color $text -color:$color -showtime:$showtime -logtime:$logtime -NoNewLine:$NoNewLine -DateTimeFormat:$DateTimeFormat -BackGroundColor $BackgroundColor_param}
}
}
#----------------------------------------------
#endregion Write-EZLogs Function
#----------------------------------------------
#----------------------------------------------
#region Stop Logging
#----------------------------------------------
function Stop-EZLogs
{
param (
[switch]$ErrorSummary,
[string]$logfile = $logfile,
[switch]$logOnly,
[switch]$enablelogs = ([System.Convert]::ToBoolean($enablelogs)),
[switch]$stoptimer,
[switch]$clearErrors
)
if($Error -and $ErrorSummary)
{
Write-Output "`n`n[-----ALL ERRORS------]" | Out-File -FilePath $logfile -Encoding unicode -Append
$e_index = 0
foreach ($e in $error)
{
$e_index++
Write-Output "[ERROR $e_index Message] =========================================================================`n$($e.exception.message)`n$($e.InvocationInfo.positionmessage)`n$($e.ScriptStackTrace)`n`n" | Out-File -FilePath $logfile -Encoding unicode -Append
}
Write-Output '-----------------' | Out-File -FilePath $logfile -Encoding unicode -Append
if($clearErrors)
{
$error.Clear()
}
}
if($logOnly){Write-Output "`n======== Total Script Execution Time ========" | Out-File -FilePath $logfile -Encoding unicode -Append}else{Write-EZLogs "`n======== Total Script Execution Time ========" -enablelogs:$enablelogs -LogTime:$false}
if($logOnly){Write-Output "Minutes : $($stopwatch.elapsed.Minutes)`nSeconds : $($stopwatch.elapsed.Seconds)`nMilliseconds : $($stopwatch.elapsed.Milliseconds)" | Out-File -FilePath $logfile -Encoding unicode -Append}else{Write-EZLogs "Minutes : $($stopwatch.elapsed.Minutes)`nSeconds : $($stopwatch.elapsed.Seconds)`nMilliseconds : $($stopwatch.elapsed.Milliseconds)" -enablelogs:$enablelogs -LogTime:$false}
if($stoptimer)
{
$($stopwatch.stop())
$($stopwatch.reset())
}
Write-Output "###################### Logging Finished - [$(Get-Date -Format $logdateformat)] ######################`n" | Out-File -FilePath $logfile -Encoding unicode -Append
}
#----------------------------------------------
#endregion Stop Logging
#----------------------------------------------
#----------------------------------------------
#region Use Run-As Function
#----------------------------------------------
function Use-RunAs
{
# Check if script is running as Adminstrator and if not use RunAs
# Use Check Switch to check if admin
# http://gallery.technet.microsoft.com/scriptcenter/63fd1c0d-da57-4fb4-9645-ea52fc4f1dfb
param([Switch]$Check)
$IsAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')
if ($Check) { return $IsAdmin }
if ($MyInvocation.ScriptName -ne '')
{
if (-not $IsAdmin)
{
write-ezlogs "Script is not running as administrator, attempting to re-run with RunAs" -showtime -Warning
try
{
$arg = "-file `"$($thisScript.File)`""
Start-Process "$psHome\powershell.exe" -Verb Runas -ArgumentList $arg -ErrorAction 'stop'
}
catch
{
write-ezlogs 'Failed to restart script with runas' -showtime -Warning
break
}
exit # Quit this session of powershell
}
}
else
{
Write-EZLogs 'Script must be saved as a .ps1 file first' -showtime -LogFile $logfile -LinesAfter 1 -Warning
break
}
}
#----------------------------------------------
#endregion Use Run-As Function
#----------------------------------------------
#############################################################################
#endregion global functions
#############################################################################
#############################################################################
#region Core functions - The primary functions specific to this script
#############################################################################
#----------------------------------------------
#region Get-OfficeVersion Function
#----------------------------------------------
Function Get-OfficeVersion
{
<#
.Synopsis
Gets the Office Version installed on the computer
.DESCRIPTION
This function will query the local or a remote computer and return the information about Office Products installed on the computer
.NOTES
Name: Get-OfficeVersion
Version: 1.0.5
DateCreated: 2015-07-01
DateUpdated: 2016-10-14
.LINK
https://github.com/OfficeDev/Office-IT-Pro-Deployment-Scripts
.PARAMETER ComputerName
The computer or list of computers from which to query
.PARAMETER ShowAllInstalledProducts
Will expand the output to include all installed Office products
.EXAMPLE
Get-OfficeVersion
Will return the locally installed Office product
.EXAMPLE
Get-OfficeVersion -ComputerName client01,client02
Will return the installed Office product on the remote computers
.EXAMPLE
Get-OfficeVersion | select *
Will return the locally installed Office product with all of the available properties
#>
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true, Position=0)]
[string[]]$ComputerName = $env:COMPUTERNAME,
[switch]$ShowAllInstalledProducts,
[System.Management.Automation.PSCredential]$Credentials
)
begin {
$HKLM = [UInt32] "0x80000002"
$HKCR = [UInt32] "0x80000000"
$excelKeyPath = "Excel\DefaultIcon"
$wordKeyPath = "Word\DefaultIcon"
$installKeys = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall',
'SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall'
$officeKeys = 'SOFTWARE\\Microsoft\\Office',
'SOFTWARE\\Wow6432Node\\Microsoft\\Office'
$defaultDisplaySet = 'DisplayName','Version', 'ComputerName'
$defaultDisplayPropertySet = New-Object System.Management.Automation.PSPropertySet('DefaultDisplayPropertySet',[string[]]$defaultDisplaySet)
$PSStandardMembers = [System.Management.Automation.PSMemberInfo[]]@($defaultDisplayPropertySet)
}
process {
$results = new-object PSObject[] 0;
$MSexceptionList = "mui","visio","project","proofing","visual"
foreach ($computer in $ComputerName) {
if ($Credentials) {
$os=Get-WMIObject win32_operatingsystem -computername $computer -Credential $Credentials
} else {
$os=Get-WMIObject win32_operatingsystem -computername $computer
}
$osArchitecture = $os.OSArchitecture
if ($Credentials) {
$regProv = Get-Wmiobject -list "StdRegProv" -namespace root\default -computername $computer -Credential $Credentials
} else {
$regProv = Get-Wmiobject -list "StdRegProv" -namespace root\default -computername $computer
}
[System.Collections.ArrayList]$VersionList = New-Object -TypeName System.Collections.ArrayList
[System.Collections.ArrayList]$PathList = New-Object -TypeName System.Collections.ArrayList
[System.Collections.ArrayList]$PackageList = New-Object -TypeName System.Collections.ArrayList
[System.Collections.ArrayList]$ClickToRunPathList = New-Object -TypeName System.Collections.ArrayList
[System.Collections.ArrayList]$ConfigItemList = New-Object -TypeName System.Collections.ArrayList
$ClickToRunList = new-object PSObject[] 0;
foreach ($regKey in $officeKeys) {
$officeVersion = $regProv.EnumKey($HKLM, $regKey)
foreach ($key in $officeVersion.sNames) {
if ($key -match "\\d{2}\\.\\d") {
if (!$VersionList.Contains($key)) {
$AddItem = $VersionList.Add($key)
}
$path = join-path $regKey $key
$configPath = join-path $path "Common\Config"
$configItems = $regProv.EnumKey($HKLM, $configPath)
if ($configItems) {
foreach ($configId in $configItems.sNames) {
if ($configId) {
$Add = $ConfigItemList.Add($configId.ToUpper())
}
}
}
$cltr = New-Object -TypeName PSObject
$cltr | Add-Member -MemberType NoteProperty -Name InstallPath -Value ""
$cltr | Add-Member -MemberType NoteProperty -Name UpdatesEnabled -Value $false
$cltr | Add-Member -MemberType NoteProperty -Name UpdateUrl -Value ""
$cltr | Add-Member -MemberType NoteProperty -Name ExcludedApps -Value ""
$cltr | Add-Member -MemberType NoteProperty -Name TeamsAddon -Value ""
$cltr | Add-Member -MemberType NoteProperty -Name Activate -Value ""
$cltr | Add-Member -MemberType NoteProperty -Name SharedComputerLicensing -Value ""
$cltr | Add-Member -MemberType NoteProperty -Name DeviceBasedLicensing -Value ""
$cltr | Add-Member -MemberType NoteProperty -Name StreamingFinished -Value $false
$cltr | Add-Member -MemberType NoteProperty -Name Platform -Value ""
$cltr | Add-Member -MemberType NoteProperty -Name ClientCulture -Value ""
$packagePath = join-path $path "Common\\InstalledPackages"
$clickToRunPath = join-path $path "ClickToRun\\Configuration"
$virtualInstallPath = $regProv.GetStringValue($HKLM, $clickToRunPath, "InstallationPath").sValue
[string]$officeLangResourcePath = join-path $path "Common\\LanguageResources"
$mainLangId = $regProv.GetDWORDValue($HKLM, $officeLangResourcePath, "SKULanguage").uValue
if ($mainLangId) {
$mainlangCulture = [globalization.cultureinfo]::GetCultures("allCultures") | where {$_.LCID -eq $mainLangId}
if ($mainlangCulture) {
$cltr.ClientCulture = $mainlangCulture.Name
}
}
[string]$officeLangPath = join-path $path "Common\\LanguageResources\\InstalledUIs"
$langValues = $regProv.EnumValues($HKLM, $officeLangPath);
if ($langValues) {
foreach ($langValue in $langValues) {
$langCulture = [globalization.cultureinfo]::GetCultures("allCultures") | where {$_.LCID -eq $langValue}
}
}
if ($virtualInstallPath) {
} else {
$clickToRunPath = join-path $regKey "ClickToRun\\Configuration"
$virtualInstallPath = $regProv.GetStringValue($HKLM, $clickToRunPath, "InstallationPath").sValue
}
if ($virtualInstallPath) {
if (!$ClickToRunPathList.Contains($virtualInstallPath.ToUpper())) {
$AddItem = $ClickToRunPathList.Add($virtualInstallPath.ToUpper())
}
$cltr.InstallPath = $virtualInstallPath
$cltr.StreamingFinished = $regProv.GetStringValue($HKLM, $clickToRunPath, "StreamingFinished").sValue
$cltr.UpdatesEnabled = $regProv.GetStringValue($HKLM, $clickToRunPath, "UpdatesEnabled").sValue
$cltr.UpdateUrl = $regProv.GetStringValue($HKLM, $clickToRunPath, "UpdateChannel").sValue
$cltr.Platform = $regProv.GetStringValue($HKLM, $clickToRunPath, "Platform").sValue
$cltr.ClientCulture = $regProv.GetStringValue($HKLM, $clickToRunPath, "ClientCulture").sValue
$cltr.TeamsAddon = $regProv.GetStringValue($HKLM, $clickToRunPath, "TeamsAddon").sValue
$cltr.ExcludedApps = $regProv.GetStringValue($HKLM, $clickToRunPath, "O365BusinessRetail.ExcludedApps").sValue
$cltr.DeviceBasedLicensing = $regProv.GetStringValue($HKLM, $clickToRunPath, "O365ProPlusRetail.DeviceBasedLicensing").sValue
if(!$cltr.ExcludedApps)
{
$cltr.ExcludedApps = $regProv.GetStringValue($HKLM, $clickToRunPath, "O365ProPlusRetail.ExcludedApps").sValue
}
if(!$cltr.DeviceBasedLicensing)
{
$cltr.DeviceBasedLicensing = $regProv.GetStringValue($HKLM, $clickToRunPath, "O365BusinessRetail.DeviceBasedLicensing").sValue
}
$cltr.SharedComputerLicensing = $regProv.GetStringValue($HKLM, $clickToRunPath, "SharedComputerLicensing").sValue
$cltr.Activate = $regProv.GetStringValue($HKLM, $clickToRunPath, "Activate").sValue
$ClickToRunList += $cltr
}
$packageItems = $regProv.EnumKey($HKLM, $packagePath)
$officeItems = $regProv.EnumKey($HKLM, $path)
foreach ($itemKey in $officeItems.sNames) {
$itemPath = join-path $path $itemKey
$installRootPath = join-path $itemPath "InstallRoot"
$filePath = $regProv.GetStringValue($HKLM, $installRootPath, "Path").sValue
if (!$PathList.Contains($filePath)) {
$AddItem = $PathList.Add($filePath)
}
}
foreach ($packageGuid in $packageItems.sNames) {
$packageItemPath = join-path $packagePath $packageGuid
$packageName = $regProv.GetStringValue($HKLM, $packageItemPath, "").sValue
if (!$PackageList.Contains($packageName)) {
if ($packageName) {
$AddItem = $PackageList.Add($packageName.Replace(' ', '').ToLower())
}
}
}
}
}
}
foreach ($regKey in $installKeys) {
$keyList = new-object System.Collections.ArrayList
$keys = $regProv.EnumKey($HKLM, $regKey)
foreach ($key in $keys.sNames) {
$path = join-path $regKey $key
$installPath = $regProv.GetStringValue($HKLM, $path, "InstallLocation").sValue
if (!($installPath)) { continue }
if ($installPath.Length -eq 0) { continue }
$buildType = "64-Bit"
if ($osArchitecture -eq "32-bit") {
$buildType = "32-Bit"
}
if ($regKey.ToUpper().Contains("Wow6432Node".ToUpper())) {
$buildType = "32-Bit"
}
if ($key -match "{.{8}-.{4}-.{4}-1000-0000000FF1CE}") {
$buildType = "64-Bit"
}
if ($key -match "{.{8}-.{4}-.{4}-0000-0000000FF1CE}") {
$buildType = "32-Bit"
}
if ($modifyPath) {
if ($modifyPath.ToLower().Contains("platform=x86")) {
$buildType = "32-Bit"
}
if ($modifyPath.ToLower().Contains("platform=x64")) {
$buildType = "64-Bit"
}
}
$primaryOfficeProduct = $false
$officeProduct = $false
foreach ($officeInstallPath in $PathList) {
if ($officeInstallPath) {
try{
$installReg = "^" + $installPath.Replace('\\', '\\\\')
$installReg = $installReg.Replace('(', '\\(')
$installReg = $installReg.Replace(')', '\\)')
if ($officeInstallPath -match $installReg) { $officeProduct = $true }
} catch {}
}
}
if (!$officeProduct) { continue };
$name = $regProv.GetStringValue($HKLM, $path, "DisplayName").sValue
$primaryOfficeProduct = $true
if ($ConfigItemList.Contains($key.ToUpper()) -and $name.ToUpper().Contains("MICROSOFT OFFICE")) {
foreach($exception in $MSexceptionList){
if($name.ToLower() -match $exception.ToLower()){
$primaryOfficeProduct = $false
}
}
} else {
$primaryOfficeProduct = $false
}
$clickToRunComponent = $regProv.GetDWORDValue($HKLM, $path, "ClickToRunComponent").uValue
$uninstallString = $regProv.GetStringValue($HKLM, $path, "UninstallString").sValue
if (!($clickToRunComponent)) {
if ($uninstallString) {
if ($uninstallString.Contains("OfficeClickToRun")) {
$clickToRunComponent = $true
}
}
}
$modifyPath = $regProv.GetStringValue($HKLM, $path, "ModifyPath").sValue
$version = $regProv.GetStringValue($HKLM, $path, "DisplayVersion").sValue
$cltrUpdatedEnabled = $NULL
$cltrUpdateUrl = $NULL
$clientCulture = $NULL;
[string]$clickToRun = $false
if ($clickToRunComponent) {
$clickToRun = $true
if ($name.ToUpper().Contains("MICROSOFT OFFICE")) {
$primaryOfficeProduct = $true
}
foreach ($cltr in $ClickToRunList) {
if ($cltr.InstallPath) {
if ($cltr.InstallPath.ToUpper() -eq $installPath.ToUpper()) {
$cltrUpdatedEnabled = $cltr.UpdatesEnabled
$cltrUpdateUrl = $cltr.UpdateUrl
$cltrExcludedApps = $cltr.ExcludedApps
$cltrSharedComputerLicensing = $cltr.SharedComputerLicensing
$cltrActivate = $cltr.Activate
$cltrDeviceBasedLicensing = $cltr.DeviceBasedLicensing
$cltrTeamsAddon = $cltr.TeamsAddon
if ($cltr.Platform -eq 'x64') {
$buildType = "64-Bit"
}
if ($cltr.Platform -eq 'x86') {
$buildType = "32-Bit"
}
$clientCulture = $cltr.ClientCulture
}
}
}
}
if (!$primaryOfficeProduct) {
if (!$ShowAllInstalledProducts) {
continue
}
}
$object = New-Object PSObject -Property @{DisplayName = $name; Version = $version; InstallPath = $installPath; ClickToRun = $clickToRun;
Bitness=$buildType; ComputerName=$computer; ClickToRunUpdatesEnabled=$cltrUpdatedEnabled; ClickToRunUpdateUrl=$cltrUpdateUrl;
ClientCulture=$clientCulture; KeyName = $key;ExcludedApps=$cltrExcludedApps;SharedComputerLicensing = $cltrSharedComputerLicensing;DeviceBasedLicensing=$cltrDeviceBasedLicensing ;Activate=$cltrActivate;TeamsAddon=$cltrTeamsAddon }
$object | Add-Member MemberSet PSStandardMembers $PSStandardMembers
$results += $object
}
}
}
$results = Get-Unique -InputObject $results
return $results;
}
}
#----------------------------------------------
#endregion Get-OfficeVersion Function
#----------------------------------------------
#----------------------------------------------
#region Test-URL Function
#----------------------------------------------
function Test-URL
{
Param(
$address,
[switch]$TestConnection
)
$uri = $address -as [System.URI]
if($uri.AbsoluteURI -ne $null -and $uri.Scheme -match 'http|https')
{
if($TestConnection)
{
Try
{
$HTTPRequest = [System.Net.WebRequest]::Create($address)
$HTTPResponse = $HTTPRequest.GetResponse()
$HTTPStatus = [Int]$HTTPResponse.StatusCode
If($HTTPStatus -ne 200) {
Return $False
}
$HTTPResponse.Close()
}
Catch
{
Return $False
}
Return $True
}
else
{
Return $true
}
}
else
{
return $false
}
}
#----------------------------------------------
#endregion Test-URL Function
#----------------------------------------------
function Invoke-FileDownload
{
Param(
[uri]$DownloadURL,
[string]$Download_file_name,
[string]$Destination_File_Path,
[string]$Download_Directory,
[switch]$Overwrite
)
Try
{
write-ezlogs ">> Initializing Download from: $DownloadURL" -showtime -color Cyan
if($DownloadURL -match "sharepoint.com")
{
write-ezlogs " | Download URL is a Onedrive share link" -showtime
if($DownloadURL -notmatch "&download=1")
{
$DownloadURL = "$DownloadURL&download=1"
}
}
if($Destination_File_Path)
{
$Download_Directory = Split-Path $Destination_File_Path -Parent
$download_file_name = Split-Path $Destination_File_Path -Leaf
}
$download_output_file = [System.IO.Path]::Combine($Download_Directory, $download_file_name)
$Test_Download_Directory = Test-Path $Download_Directory -PathType Container
$test_download_output_file = Test-Path $download_output_file -PathType Leaf
if($test_download_output_file)
{
if($Overwrite)
{
write-ezlogs " | Overwriting existing download file: $download_output_file" -showtime
}
else
{
write-ezlogs " | File to download already exists : $download_output_file | Overwite option disabled, Skipping download" -showtime -Warning
return $download_output_file
}
}
elseif (!$Test_Download_Directory)
{
write-ezlogs " | Creating destination directory: $Download_Directory" -ShowTime
$null = New-Item $Download_Directory -ItemType Directory -Force
}
else
{
write-ezlogs " | Destination directory is valid: $Download_Directory" -ShowTime
}
$start_time = Get-Date
$null = Invoke-WebRequest -Uri $DownloadURL -OutFile $download_output_file -UseBasicParsing
write-ezlogs " | Download Time taken for file $DownloadURL : $((Get-Date).Subtract($start_time).Seconds) second(s)" -ShowTime
$test_download_output_file = Test-Path $download_output_file
if($test_download_output_file)
{
write-ezlogs " | File successfully downloaded to $download_output_file" -ShowTime -color Green
return $download_output_file
}
else
{
write-ezlogs " | Unable to validate downloaded file: $download_output_file" -ShowTime -Warning
return $false
}
}
catch
{
write-ezlogs "[ERROR] An exception occured downloading from $DownloadURL :`n | $($_.exception.message)`n | $($_.InvocationInfo.positionmessage)`n | $($_.ScriptStackTrace)`n" -Color Red -showtime
}
}
#----------------------------------------------
#region Install-Office365Suite Function
#----------------------------------------------
function Invoke-Office365Setup
{
[CmdletBinding(DefaultParameterSetName = 'XMLFile')]
Param(
[Parameter(ParameterSetName = "XMLFile")][ValidateNotNullOrEmpty()][String]$ConfigurationXMLFile,
[Parameter(ParameterSetName = "NoXML")][ValidateSet("TRUE","FALSE")]$AcceptEULA = "TRUE",
[Parameter(ParameterSetName = "NoXML")][ValidateSet("TRUE","FALSE")]$FORCEAPPSHUTDOWN = "FALSE",
[Parameter(ParameterSetName = "NoXML")][ValidateSet("Current","CurrentPreview","SemiAnnual","SemiAnnualPreview","BetaChannel","MonthlyEnterprise")]$Channel = "Current",
[Parameter(ParameterSetName = "NoXML")][Switch]$DisplayInstall = $False,
[Parameter(ParameterSetName = "NoXML")][ValidateSet("Groove","Outlook","OneNote","Access","OneDrive","Publisher","Word","Excel","PowerPoint","Teams","Lync")][Array]$ExcludeApps,
[Parameter(ParameterSetName = "NoXML")][ValidateSet("64","32")]$OfficeArch = "64",
[Parameter(ParameterSetName = "NoXML")][ValidateSet("O365ProPlusRetail","O365BusinessRetail")]$OfficeEdition = "O365ProPlusRetail",
[Parameter(ParameterSetName = "NoXML")][ValidateSet("TRUE","FALSE")]$SharedComputerLicensing = "FALSE",
[Parameter(ParameterSetName = "NoXML")][ValidateSet("TRUE","FALSE")]$AUTOACTIVATE = "TRUE",
[Parameter(ParameterSetName = "NoXML")][ValidateSet("TRUE","FALSE")]$EnableUpdates = "TRUE",
[Parameter(ParameterSetName = "NoXML")][String]$OrgName,
[Parameter(ParameterSetName = "NoXML")][String]$SourcePath,
[Parameter(ParameterSetName = "NoXML")][ValidateSet("TRUE","FALSE")]$PinItemsToTaskbar = "TRUE",
[Parameter(ParameterSetName = "NoXML")][Switch]$RemoveMSI = $true,
[Parameter(ParameterSetName = "NoXML")][Switch]$RemoveOnly = $false,
[Parameter(ParameterSetName = "NoXML")][ValidateSet("O365ProPlusRetail","O365BusinessRetail","All")]$RemoveOnlyEdition = "O365ProPlusRetail",
[String]$Copy_SetupLog_directory = $logfile_directory,
[Switch]$Copy_SetupLog,
[String]$OfficeInstallDownloadPath = $Install_Office_Download_Path,
[switch]$Remove_Install_Office_Download_Path = $false
)
if($RemoveOnly)
{
write-ezlogs "#### Removing Office365 ####" -linesbefore 1 -color yellow
}
else
{
write-ezlogs "#### Installing Office365 ####" -linesbefore 1 -color yellow
}
Function Generate-XMLFile{
write-ezlogs "Creating XML configuration file based on supplied values" -showtime
if($RemoveOnly)
{
if(!$RemoveOnlyEdition -or $RemoveOnlyEdition -eq "All")
{
$RemoveAll = "TRUE"
$RemoveOnlyEdition = $null
write-ezlogs " | Remove All: $RemoveAll" -showtime
}
else
{
$RemoveAll = "FALSE"
write-ezlogs " | Remove Office Edition: $RemoveOnlyEdition" -showtime
}
$OfficeXML = [XML]@"
"@
}
else
{
write-ezlogs " | Office Edition: $OfficeEdition" -showtime
If($ExcludeApps){
write-ezlogs " | Excluded Apps: $ExcludeApps" -showtime
$ExcludeApps | ForEach-Object{
$ExcludeAppsString += ""
}
}
If($OfficeArch){
write-ezlogs " | Office Architecture: $OfficeArch" -showtime
$OfficeArchString = "`"$OfficeArch`""
}
if($OrgName)
{
write-ezlogs " | Organization Name: $OrgName" -showtime
$OrgName_String = "
"
}else{
$OrgName_String = $null
}
write-ezlogs " | Remove MSI: $RemoveMSI" -showtime
If($RemoveMSI){
$RemoveMSIString = ""
}Else{
$RemoveMSIString = $Null
}
write-ezlogs " | Office Channel: $Channel" -showtime
If($Channel){
$ChannelString = "Channel=`"$Channel`""
}Else{
$ChannelString = $Null
}
if($SourcePath -eq "Internet")
{
$SourcePathString = $Null
write-ezlogs " | Source Path: Internet - Microsoft CDN" -showtime
}
else
{
$SourcePath_Valid = Test-Path $SourcePath -PathType Container -ErrorAction SilentlyContinue
If($SourcePath_Valid){
write-ezlogs " | Source Path: $SourcePath" -showtime
$SourcePathString = "SourcePath=`"$SourcePath`""
}
Else
{
write-ezlogs " | Source Path: Internet - Microsoft CDN" -showtime
$SourcePathString = $Null
}
}
write-ezlogs " | Display Install: $DisplayInstall" -showtime
If($DisplayInstall){
$SilentInstallString = "Full"
}Else{
$SilentInstallString = "None"
}
write-ezlogs " | Auto Activate: $AUTOACTIVATE" -showtime
If($AUTOACTIVATE){
$AUTOACTIVATE = "1"
}Else{
$AUTOACTIVATE = "0"
}
write-ezlogs " | Accept EULA: $AcceptEULA" -showtime
write-ezlogs " | Shared Computer Licensing (RDP installs): $SharedComputerlicensing" -showtime
If($SharedComputerlicensing){
$SharedComputerlicensing = "1"
}Else{
$SharedComputerlicensing = "0"
}
write-ezlogs " | ForceAppShutdown: $FORCEAPPSHUTDOWN" -showtime
write-ezlogs " | PinIconsToTaskbar: $PinItemsToTaskbar" -showtime
write-ezlogs " | Enable Updates: $EnableUpdates" -showtime
#XML data that will be used for the download/install
$OfficeXML = [XML]@"
$ExcludeAppsString
$RemoveMSIString
$OrgName_String
"@
}
#Save the XML file
$OfficeXML.Save("$OfficeInstallDownloadPath\\OfficeInstall.xml")
write-ezlogs ">> XML File Generated: $OfficeInstallDownloadPath\\OfficeInstall.xml" -showtime -color cyan
Return "$OfficeInstallDownloadPath\\OfficeInstall.xml"
}
Function Get-ODTURL {
$ODTDLLink = ""
$MSWebPage = (Invoke-WebRequest "https://www.microsoft.com/en-us/download/confirmation.aspx?id=49117" -UseBasicParsing).Content
#Thank you reddit user, u/sizzlr for this addition.
Foreach ($m in $MSWebPage)
{
If($m -match "url=(https://.*officedeploymenttool.*\.exe)"){
$ODTDLLink = $matches[1]}
}
if(Test-URL $ODTDLLink)
{
Return $ODTDLLink
}
else
{
Return $false
}
}
$VerbosePreference = "SilentlyContinue"
$ErrorActionPreference = "Stop"
If(-Not(Test-Path $OfficeInstallDownloadPath )){
$Null = New-Item -Path $OfficeInstallDownloadPath -ItemType Directory -ErrorAction Stop | Out-Null
}
If(!($ConfigurationXMLFile))
{
$ConfigurationXMLFile = Generate-XMLFile #If the user didn't specify with -ConfigurationXMLFile param, we make one
}
Else
{
if(Test-URL($ConfigurationXMLFile))
{
write-ezlogs "XML file path provided is a web URL" -showtime
$Download_FileName = "365ODT-Config.xml"
$ConfigurationXMLFile = Invoke-FileDownload -DownloadURL $ConfigurationXMLFile -Download_Directory $OfficeInstallDownloadPath -Download_file_name $Download_FileName -Overwrite
}
elseif(!(Test-Path $ConfigurationXMLFile))
{
Write-ezlogs "The configuration XML file is not a valid file. Please check the path and try again" -showtime -Warning
Stop-EZLogs -ErrorSummary -stoptimer -clearErrors -logOnly
Exit
}
else
{
write-ezlogs "Using existing XML configuration file: $ConfigurationXMLFile" -showtime
}
}
#Get the ODT Download link
$ODTInstallLink = Get-ODTURL
#Download the Office Deployment Tool
write-ezlogs ">> Downloading the Office Deployment Toolkit" -showtime -color Cyan
if($ODTInstallLink -ne $false)
{
write-ezlogs " | ODT Install Link: $ODTInstallLink" -showtime
Try
{
#$null = Invoke-WebRequest -Uri $ODTInstallLink -OutFile "$OfficeInstallDownloadPath\\ODTSetup.exe"
$ODTInstallFile = Invoke-FileDownload -DownloadURL $ODTInstallLink -Destination_File_Path "$OfficeInstallDownloadPath\\ODTSetup.exe" -Overwrite
}
Catch
{
write-ezlogs "[ERROR] An exception occured downloading ODT from $ODTInstallLink :`n | $($_.exception.message)`n | $($_.InvocationInfo.positionmessage)`n | $($_.ScriptStackTrace)`n" -color Red -showtime
Stop-Ezlogs -ErrorSummary -logOnly -stoptimer -clearErrors -enablelogs:([System.Convert]::ToBoolean($enablelogs))
Exit
}
}
else
{
write-ezlogs "[ERROR] Unable to get the ODT download link" -color Red -showtime
Stop-Ezlogs -ErrorSummary -logOnly -stoptimer -clearErrors -enablelogs:([System.Convert]::ToBoolean($enablelogs))
Exit
}
#Run the Office Deployment Tool setup
Try
{
write-ezlogs " | Running the Office Deployment Toolkit Setup" -showtime
Start-Process $ODTInstallFile -ArgumentList "/quiet /extract:$OfficeInstallDownloadPath" -Wait
}
Catch
{
write-ezlogs "[ERROR] An exception occured running ODT:`n | $($_.exception.message)`n | $($_.InvocationInfo.positionmessage)`n | $($_.ScriptStackTrace)`n" -color Red -showtime
}
#Run the O365 install
Try
{
write-ezlogs ">> Downloading and Running Office 365 Setup" -showtime -color Cyan
$OfficeInstaller = "$OfficeInstallDownloadPath\\setup.exe"
$OfficeArguments = "/configure `"$ConfigurationXMLFile`""
write-ezlogs " | Office Setup Command: $OfficeInstaller $OfficeArguments" -showtime
$ODTLogFile = "$env:COMPUTERNAME-$(Get-Date -f 'yyyyMMdd-hhmm')"
$Proc = Start-Process -FilePath $OfficeInstaller -ArgumentList $OfficeArguments -Wait -PassThru -WindowStyle Hidden
$proc | Wait-Process -Timeout 400 -ErrorAction Continue -ErrorVariable timeouted
if ($timeouted)
{
# terminate the process
$proc | Stop-Process
Write-ezlogs "[ERROR] Process failed to finish before the timeout period and was canceled. Removing downloaded files and exiting. $timeouted" -Color red -showtime
$Null = Remove-Item $OfficeInstallDownloadPath -Recurse -Force
Stop-Ezlogs -ErrorSummary -logOnly -stoptimer -clearErrors -enablelogs:([System.Convert]::ToBoolean($enablelogs))
exit
}
elseif ($proc.ExitCode -ne 0)
{
Write-ezlogs "Unexpected process exit code ($($proc.ExitCode)). Halting further actions" -showtime -Warning
Stop-Ezlogs -ErrorSummary -logOnly -stoptimer -clearErrors -enablelogs:([System.Convert]::ToBoolean($enablelogs))
exit
}
}
Catch
{
write-ezlogs "[ERROR] An exception occured while running Office 365 setup:`n | $($_.exception.message)`n | $($_.InvocationInfo.positionmessage)`n | $($_.ScriptStackTrace)`n" -color Red -showtime
}
$OfficeInstalled = $False
$Office_Installs = Get-OfficeVersion -ShowAllInstalledProducts | select *
Foreach ($Key in $Office_Installs )
{
If($Key.("KeyName") -like "*$OfficeEdition*" -or $Key.("DisplayName") -like "*Microsoft 365*")
{
$OfficeVersionInstalled = "$($Key.('DisplayName')) - $($Key.('Version'))"
$OfficeInstalled = $True
}
}
If($OfficeInstalled -and !$RemoveOnly)
{
write-ezlogs "[SUCCESS] $($OfficeVersionInstalled) installed successfully" -showtime -color Green
write-ezlogs $($Office_Installs | out-string)
}
elseif(!$RemoveOnly)
{
write-ezlogs "Office 365 was not detected after the install ran. Check the log files to get more information" -showtime -warning
}
if($RemoveOnly -and !$OfficeInstalled)
{
write-ezlogs "[SUCCESS] Office 365 ($($RemoveOnlyEdition)) was removed successfully" -showtime -color Green
}
elseif($RemoveOnly)
{
write-ezlogs "Office 365 ($($RemoveOnlyEdition)) was detected after removal ran. Check the log files to get more information" -showtime -warning
}
if($Copy_SetupLog)
{
$ODTLogFileFound = Get-ChildItem $env:temp -Recurse -Include "$ODTLogFile*.log" -ErrorAction SilentlyContinue
if($ODTLogFileFound)
{
write-ezlogs "Copying Office 365 Setup log ($($ODTLogFileFound.FullName)) to directory ($Copy_SetupLog_directory)" -showtime
$null = Copy-Item $ODTLogFileFound -Destination $Copy_SetupLog_directory -Force
}
else
{
write-ezlogs "Unable to find an Office 365 Setup log file matching $ODTLogFile" -showtime -Warning
}
}
if($Remove_Install_Office_Download_Path)
{
write-ezlogs ">> Removing all files downloaded and created at $OfficeInstallDownloadPath" -showtime -color Cyan
try
{
$null = Remove-item $OfficeInstallDownloadPath -Recurse -Force
}
catch
{
write-ezlogs "[ERROR] An exception occurred when removing $OfficeInstallDownloadPath`n | $($_.exception.message)`n | $($_.InvocationInfo.positionmessage)`n | $($_.ScriptStackTrace)`n" -color red -showtime
}
}
}
#----------------------------------------------
#endregion Install-Office365Suite Function
#----------------------------------------------
#############################################################################
#endregion Core functions
#############################################################################
#############################################################################
#region Execution and Output - Functions or Code that executes required actions and/or performs output
#############################################################################
#----------------------------------------------
#region Execute Get-OfficeVersion
#----------------------------------------------
Use-RunAs
$OfficeInstalled = $False
write-ezlogs "#### Checking Office Installations ####" -linesbefore 1 -color yellow
$Office_Installs = Get-OfficeVersion -ShowAllInstalledProducts | select ComputerName,DisplayName,KeyName,Version,Bitness,ClientCulture,ClickToRun,ClickToRunUpdatesEnabled,ClickToRunUpdateUrl,Activate,DeviceBasedLicensing,SharedComputerLicensing,InstallPath,TeamsAddOn,ExcludedApps
if($Office_Installs)
{
write-ezlogs "---- Office Installation(s) found ----`n$($($Office_Installs | out-string).trim())`n"
Foreach ($Key in $Office_Installs )
{
If($Install_Office_Edition -and $Key.("KeyName") -like "*$Install_Office_Edition*")
{
$OfficeVersionInstalled = "Name: $($Key.('DisplayName')) - Version: $($Key.('Version')) - Edition: $($Key.('KeyName'))"
$OfficeInstalled = $True
}
}
}
else
{
write-ezlogs "No valid Office installations were found" -showtime
}
#----------------------------------------------
#endregion Execute Get-OfficeVersion
#----------------------------------------------
#----------------------------------------------
#region Execute Install-Office365Suite
#----------------------------------------------
if(([System.Convert]::ToBoolean($Remove_Office_Only)))
{
$RemoveOfficeInstalled = $false
if(!$Remove_Office_Only_Edition)
{
$Remove_Office_Only_Edition = "All"
}
Foreach ($Key in $Office_Installs )
{
If($Remove_Office_Only_Edition -and $Key.("KeyName") -like "*$Remove_Office_Only_Edition*")
{
$OfficeVersionInstalled = "Name: $($Key.('DisplayName')) - Version: $($Key.('Version')) - Edition: $($Key.('KeyName'))"
$RemoveOfficeInstalled = $True
}
elseif($Office_Installs -and $Remove_Office_Only_Edition -eq "All")
{
$RemoveOfficeInstalled = $true
}
else
{
$RemoveOfficeInstalled = $false
}
}
if($RemoveOfficeInstalled)
{
write-ezlogs " | Office Edition(s) to remove: $Remove_Office_Only_Edition" -showtime
Invoke-Office365Setup -RemoveOnly:([System.Convert]::ToBoolean($Remove_Office_Only)) -RemoveOnlyEdition:$Remove_Office_Only_Edition -Copy_SetupLog:([System.Convert]::ToBoolean($Copy_SetupLog)) -OfficeInstallDownloadPath:$Install_Office_Download_Path
}
else
{
write-ezlogs "The edition of Office specified to remove was not found" -showtime -warning
}
}
elseif(([System.Convert]::ToBoolean($Install_Office)))
{
if ($OfficeInstalled)
{
write-ezlogs "The Edition of Office specified to install is already installed on this machine | Skipping any further actions" -showtime -warning
break
}
else
{
if (([System.Convert]::ToBoolean($Install_Office_WITH_ODT)) -and $Install_Office_WITH_ODT_XMLFILE)
{
Invoke-Office365Setup -ConfigurationXMLFile $Install_Office_WITH_ODT_XMLFILE -OfficeInstallDownloadPath:$Install_Office_Download_Path -Copy_SetupLog:([System.Convert]::ToBoolean($Copy_SetupLog)) -Remove_Install_Office_Download_Path:([System.Convert]::ToBoolean($Remove_Install_Office_Download_Path))
}
else
{
Invoke-Office365Setup -AcceptEULA:([System.Convert]::ToBoolean($Install_Office_Accept_EULA)) -SharedComputerLicensing:([System.Convert]::ToBoolean($Install_Office_Shared_Computer_Licensing)) -FORCEAPPSHUTDOWN:([System.Convert]::ToBoolean($Install_Office_FORCE_APPSHUTDOWN)) -ExcludeApps $Install_Office_Exclude_Apps -OrgName $Install_Office_Org_Name -AUTOACTIVATE:([System.Convert]::ToBoolean($Install_Office_AUTO_ACTIVATE)) -EnableUpdates:([System.Convert]::ToBoolean($Install_Office_Enable_Updates)) -OfficeEdition $Install_Office_Edition -RemoveMSI:([System.Convert]::ToBoolean($Install_Office_Remove_Previous_Intalls)) -DisplayInstall:([System.Convert]::ToBoolean($Install_Office_Display_Install)) -Copy_SetupLog:([System.Convert]::ToBoolean($Copy_SetupLog)) -OfficeInstallDownloadPath:$Install_Office_Download_Path -SourcePath:$Install_Office_Source_Path -Channel:$Install_Office_Channel
}
}
}
#----------------------------------------------
#endregion Execute Install-Office365Suite
#----------------------------------------------
#----------------------------------------------
#region End Logging
#----------------------------------------------
Stop-EZLogs -ErrorSummary -logOnly -stoptimer -clearErrors -enablelogs:([System.Convert]::ToBoolean($enablelogs))
#----------------------------------------------
#endregion End Logging
#----------------------------------------------
#############################################################################
#endregion Execution and Output Functions
#############################################################################
'''
print ("iTarian RMM - Executing Powershell Script")
def ecmd(command):
import ctypes
from subprocess import PIPE, Popen
class disable_file_system_redirection:
_disable = ctypes.windll.kernel32.Wow64DisableWow64FsRedirection
_revert = ctypes.windll.kernel32.Wow64RevertWow64FsRedirection
def __enter__(self):
self.old_value = ctypes.c_long()
self.success = self._disable(ctypes.byref(self.old_value))
def __exit__(self, type, value, traceback):
if self.success:
self._revert(self.old_value)
with disable_file_system_redirection():
obj = Popen(command, shell = True, stdout = PIPE, stderr = PIPE)
out, err = obj.communicate()
ret=obj.returncode
if ret==0:
if out:
return out.strip()
else:
return ret
else:
if err:
return err.strip()
else:
return ret
file_name='EZT-DeployO365.ps1'
file_path=os.path.join(os.environ['TEMP'], file_name)
with open(file_path, 'wb') as wr:
wr.write(ps_content)
ecmd('powershell "Set-ExecutionPolicy Bypass"')
print ecmd('powershell "%s"'%file_path)
os.remove(file_path)