-
Notifications
You must be signed in to change notification settings - Fork 45
/
Copy pathDownload and Install Office 365 via ODT.ps1
187 lines (150 loc) · 6.52 KB
/
Download and Install Office 365 via ODT.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#requires -version 3
<#
Install Office 365 via ODT. Script to be used by Flexxible IT Apps2Digital formulas
https://docs.microsoft.com/en-us/deployoffice/overview-of-the-office-2016-deployment-tool
@guyrleech 2019
#>
[CmdletBinding()]
Param
(
# no parameters as parameter mechanism is via #pattern#
)
$ProgressPreference = 'SilentlyContinue'
## TODO Replace "64" with a #Bitness# parameter
## TODO Option to install Visio
## TODO Option to not install OneDrive
# SourcePath="**officeDownloadFolder**"
[string]$configXML = @'
<Configuration>
<Add OfficeClientEdition="64" Channel="Monthly">
<Product ID="O365ProPlusRetail">
<Language ID="en-us" />
</Product>
</Add>
<Updates Enabled="FALSE" Channel="Monthly" />
<Display Level="None" AcceptEULA="TRUE" />
<Property Name="AUTOACTIVATE" Value="0" />
<Logging Level="Standard" Path="**workingFolder**" />
</Configuration>
'@
[bool]$createdFolder = $false
[string]$odtDownloadRegex = '/officedeploymenttool[a-z0-9_-]*\.exe$'
## Check running as admin
$myWindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal([System.Security.Principal.WindowsIdentity]::GetCurrent())
$adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator
if ( ! ( $myWindowsPrincipal.IsInRole( $adminRole ) ) )
{
Throw 'Script is not being run elevated'
}
try
{
[string]$workingFolder = (Join-Path -Path $env:temp -ChildPath (([guid]::NewGuid()).Guid))
# URL the ODT
[string]$downloadURL = 'https://www.microsoft.com/en-us/download/confirmation.aspx?id=49117'
# TODO How do we deal with a proxy?
if( ( Test-Path -Path $workingFolder -ErrorAction SilentlyContinue ) )
{
Throw "Random working folder name `"$workingFolder`" already exists"
}
$newFolder = New-Item -Path $workingFolder -ItemType Directory
if( ! $newFolder )
{
Throw "Failed to create working folder `"$workingFolder`""
}
else
{
$createdFolder = $true
}
$html = Invoke-WebRequest -Uri $downloadURL -UseBasicParsing
if( ! $html -or ! $html.Links )
{
Throw "Failed to download from $downloadURL"
}
[string[]]$downloadLinks = @( $html.Links | Where-Object { $_.href -Match $odtDownloadRegex } | Select-Object -ExpandProperty href | Sort-Object -Unique )
if( ! $downloadLinks.Count )
{
Throw "No links on page $downloadURL matching regex $odtDownloadRegex"
}
if( $downloadLinks.Count -gt 1 )
{
Throw "Ambiguous download links on $downloadURL : $($downloadLinks -join ',')"
}
[string]$outputFile = Join-Path -Path $workingFolder -ChildPath ($downloadLinks[0] -split '/')[-1]
Write-Verbose "$(Get-Date -Format G): Starting download from $($downloadLinks[0]) to `"$outputFile`""
(New-Object System.Net.WebClient).Downloadfile( $downloadLinks[0] , $outputFile )
if( ! ( Test-Path -Path $outputFile -PathType Leaf -ErrorAction SilentlyContinue ) )
{
Throw "Failed to download from $($downloadLinks[0]) to `"$outputFile`""
}
# Now check signature to ensure we are running the correct executable
Unblock-File -Path $outputFile -ErrorAction SilentlyContinue
$signing = Get-AuthenticodeSignature -FilePath $outputFile -ErrorAction SilentlyContinue
if( ! $signing )
{
Throw "Could not get signing information from `"$outputFile`""
}
if( $signing.Status -ne 'Valid' )
{
Throw "Certificate status for `"$outputFile`" is $($signing.Status), not `"Valid`""
}
if( $signing.SignerCertificate.Subject -notmatch '^CN=Microsoft Corporation,' )
{
Throw "`"$outputFile`" is not signed by Microsoft Corporation, found $($signing.SignerCertificate.Subject)"
}
# Run silently to extract setup.exe
$odtInstallProcess = Start-Process -FilePath $outputFile -ArgumentList "/extract:`"$($workingFolder)`" /quiet" -PassThru -Wait -WindowStyle Hidden
if( ! $odtInstallProcess )
{
Throw "Failed to run `"$outputFile`""
}
if( ! $odtInstallProcess -or $odtInstallProcess.ExitCode )
{
Throw "Bad exit code $($odtInstallProcess.ExitCode) from `"$outputFile`""
}
[string]$setupExe = Join-Path -Path $workingFolder -ChildPath 'setup.exe'
if( ! ( Test-Path -Path $setupExe -PathType Leaf -ErrorAction SilentlyContinue ) )
{
Throw "Unable to locate extracted setup.exe after running `"$outputFile`""
}
Unblock-File -Path $setupExe -ErrorAction SilentlyContinue
# Construct XML config file for Office Deployment Kit setup.exe
[string]$xmlFilePath = Join-Path -Path $workingFolder -ChildPath 'office365.xml'
## TODO verify bitness is 32 or 64 bit
# Get the log file in our folder.
$configXML -replace '\*\*workingFolder\*\*' , $workingFolder | Out-File -FilePath $xmlFilePath -Force -Encoding ascii
# Run silently to download media
Write-Verbose "$(Get-Date -Format G): Running `"$setupExe`" to download office media"
$odtProcess = Start-Process -FilePath $setupExe -ArgumentList "/download $(Split-Path -Path $xmlFilePath -Leaf)" -PassThru -Wait -WorkingDirectory $workingFolder -WindowStyle Hidden
if( ! $odtProcess )
{
Throw "Failed to run `"$setupExe`" to download Office"
}
if( $odtProcess.ExitCode )
{
Throw "Bad exit code $($odtProcess.ExitCode) from `"$setupExe`" to download Office"
}
Write-Verbose -Message "$(Get-Date -Format G): download of Office media to `"$workingFolder`" finished, starting installation"
## Install
$installProcess = Start-Process -FilePath $setupExe -ArgumentList "/configure $(Split-Path -Path $xmlFilePath -Leaf)" -PassThru -Wait -WorkingDirectory $workingFolder -WindowStyle Hidden
if( ! $installProcess )
{
Throw "Failed to run `"$setupExe`" to install Office"
}
if( $odtProcess.ExitCode )
{
Throw "Bad exit code $($odtProcess.ExitCode) from `"$setupExe`" to install Office"
}
Write-Verbose -Message "$(Get-Date -Format G): installation of Office media from `"$workingFolder`" finished"
}
catch
{
Throw $_
}
finally
{
# Delete temp folder and files
if( ( Get-Variable -Name createdFolder -ErrorAction SilentlyContinue ) -and $createdFolder -and ( Test-Path -Path $workingFolder -ErrorAction SilentlyContinue ) )
{
Remove-Item -Path $workingFolder -Force -Recurse -ErrorAction Continue
}
}