Articles in the "Install Exchange 2010 Prerequisites" series
- Script to install all Exchange 2010 prerequisites [This article]
- Exchange 2010 prerequisite installation script updated
- Exchange 2010 prerequisite installation script updated
- Updated script to install Exchange 2010 prerequisites
There are already several sites which have scripts to install Exchange 2010 prerequisites, but they all seem to fall short in one aspect or another. Some make you choose the right script if you are on 2008 or 2008 R2. Others download some files but not others. None make sure that WinRM is installed, which is needed for PowerShell v2. So I started with a great script and made it better. My starting point is Bhargav Shukla’s script, which in turn started elsewhere.
My script checks whether the server is running Windows Server 2008 SP2 or Windows Server 2008 R2. (If you aren’t running SP2, it will tell you.) Because the command to add the Windows components is different between them (ServerManagerCmd.exe in DOS and Add-WindowsFeature in PowerShell), the appropriate command will be run.
Instead of just downloading the 2007 Office Filter Pack, I added the option to download each file (including WinRM) if it isn’t installed and not in the installation source directory. I also chose to install the 2010 Office Filter Pack, which includes support for 2007.
If Windows Remote Management isn’t installed, it will install it and reboot the server. You don’t have to uninstall PowerShell v1 to do this, so you can run the script and install WinRM, then run the script again after the reboot to continue (which is then implicitly using PowerShell v2).
I also added functions to enable remote PowerShell and enable the Windows Firewall service. The latter is required for Exchange setup to be successful so it can create the firewall exceptions. You can always disable the service after setup is complete.
I added the option to install the HT and CAS roles together, should that apply to you.
If you want to download the required files ahead of time and put them in the same directory as the script, they are listed below (direct download links). Note that I renamed the filter pack installation file to 2010FilterPack64bit.exe in order to distinguish it from the Office 2007 Filter Pack installation file. If you have the 2007 Filter pack installed, the 2010 install will replace it upon installation. If you manually download the filter pack, though, remember to rename it.
- Windows Remote Management Framework (14MB)
- .NET 3.5 SP1 Redistributable installation (235MB)
- .NET 3.5 SP1 hotfix (1.4MB)
- Office 2010/2007 Filter Pack (4MB)
- The Exchange-Role.xml files from the installation media’s Scripts directory
You can copy the script inline below, or download it via the link at the bottom of the post.
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 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
#Installs prerequisites necessary to install Exchange 2010 on #Windows 2008 SP2 or Windows 2008 R2. #Version 1.3 #Last modified: June 28, 2010 #Set installation source to same directory as script execution $sourcePath = Split-Path -Parent $MyInvocation.MyCommand.Path Write-Host 'Using ' -NoNewline Write-Host $sourcePath -ForegroundColor DarkGreen -NoNewline Write-Host ' as the installation source.' # Detect correct OS here and exit if no match if ((Get-WMIObject win32_OperatingSystem).Version -eq '6.1.7600') {$os = 'R2'} elseif ((Get-WMIObject win32_OperatingSystem).Version -eq '6.0.6002') {$os = 'R1'} else { Write-Host 'This script requires Windows Server 2008 with SP2, or R2, which this is not.' -ForegroundColor Red -BackgroundColor Black break } #Installation files and properties (filename, shortname, displayname, download URL, size) $fileWinRM = ('Windows6.0-KB968930-x64.msu','WinRM','Windows Remote Management Framework','http://download.microsoft.com/download/2/8/6/28686477-3242-4E96-9009-30B16BED89AF/Windows6.0-KB968930-x64.msu','14MB') $fileNET35 = ('dotnetfx35.exe','.NET 3.5','.NET 3.5 SP1','http://download.microsoft.com/download/2/0/E/20E90413-712F-438C-988E-FDAA79A8AC3D/dotnetfx35.exe','235MB') $fileNET35HF = ('NDP35SP1-KB958484-x64.exe','.NET 3.5 hotfix','.NET 3.5 hotfix','http://download.microsoft.com/download/B/4/2/B42197BD-AEE1-4FE6-8CB3-29D60D0C3727/Windows6.0-KB958483-x64.msu','1.4MB') $fileOFP = ('2010FilterPack64bit.exe','Office 2010 Filter Pack','Office 2010/2007 Filter Pack','http://download.microsoft.com/download/0/A/2/0A28BBFA-CBFA-4C03-A739-30CCA5E21659/FilterPack64bit.exe','4MB') Function InstallApp($app) { switch ($app) { 'WinRM' { $appArray = $fileWinRM $kb = 'KB968930' } 'NET35' { $appArray = $fileNET35 $checkExpression = "test-path 'HKLM:Software\Microsoft\NET Framework Setup\NDP\v3.5'" } 'NET35HF' { $appArray = $fileNET35HF $checkExpression = "test-path 'HKLM:SOFTWARE\Wow6432Node\Microsoft\Updates\Microsoft .NET Framework 3.5 SP1\SP1\KB958484'" } 'OFP' { $appArray = $fileOFP $checkExpression = "test-path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\{95140000-2000-0409-1000-0000000FF1CE}'" } } trap { Write-Host '' Write-Host "There was a problem downloading or installing $($appArray[1])." -ForegroundColor Red Write-Host '' break } #Check for existing installation Write-Host "Verifying $($appArray[2]) is installed..." -NoNewline if ($app -eq 'WinRM') { $hfInst = Get-WMIObject Win32_QuickFixEngineering | where {$_.HotFixID -eq $kb} if ($hfInst) { $bInstalled = $true } else { $bInstalled = $false } } else { if (Invoke-Expression $checkExpression) { $bInstalled = $true } else { $bInstalled = $false } } if ($bInstalled) { Write-Host "$($appArray[2]) is installed." -ForegroundColor Green return } Write-Host "$($appArray[2]) is not installed." -ForegroundColor Red Write-Host "Installing $($appArray[2])..." -NoNewline #Install app: Check for existing installation file. $fullPath = $sourcePath+"\$($appArray[0])" if (!(Test-Path $fullPath)) { Write-Host '' Write-Host "$($appArray[0]) not found in source path." -ForegroundColor Yellow $dl = Read-Host "Do you want to download it now? ($($appArray[4]))(Y/N)" if ($dl -ne 'y') { Write-Host "You have chosen to not download the $($appArray[1]) installation file." Write-Host "Put $($appArray[0]) in the source directory and run the script again." break } else { Write-Host "Downloading $($appArray[1])..." -NoNewline $dlClient = New-Object System.Net.WebClient $dlClient.DownloadFile($appArray[3],$fullPath) if (!(Test-Path $fullPath)) { Write-Host '' Write-Host "There was a problem downloading $($appArray[1])." -ForegroundColor Red Write-Host '' } else { Write-Host 'done.' -ForegroundColor Green } } } #Install app: Run installation. if ($app -eq 'WinRM') { $expression = "wusa $fullPath /quiet" Invoke-Expression $expression Write-Host 'External update process started...Be patient, it takes time.' -ForegroundColor Yellow Write-Host '' Write-Host 'When the WinRM installation is complete, the system will automatically reboot.' Write-Host 'Then you can rerun the script to continue. This script will now end.' break } else { if ($app -eq 'NET35HF') {$arguments = '/passive /norestart'} else {$arguments = '/quiet /norestart'} $process = [System.Diagnostics.Process]::Start($fullPath,$arguments) $process.WaitForExit() Write-Host "$($appArray[1]) installation complete." -ForegroundColor Green } } Function InstallNET35() { InstallApp('NET35') InstallApp('NET35HF') } Function SetTCPSharing() { trap { Write-Host '' Write-Host 'There was problem setting the NET TCP Port Sharing service to Automatic startup.' -ForegroundColor Red Write-Host 'The service must be set to Automatic for Exchange setup to be successful.' -ForegroundColor Red Write-Host '' return } #Set NETTCPPortSharing to Automatic Write-Host 'Configuring the NET TCP Port Sharing service...' -NoNewline Set-Service NetTcpPortSharing -StartupType Automatic Write-Host 'done.' -ForegroundColor Green } Function EnableRemoting() { trap { Write-Host '' Write-Host 'There was problem configuring the system for remote PowerShell.' -ForegroundColor Red Write-Host '' return } #Enable Remote PowerShell for Exchange administration from workstations Write-Host 'Enabling system for remote PowerShell connections...' Enable-PSRemoting -force Write-Host 'Remote PowerShell configuration is done.' -ForegroundColor Green } Function EnableFirewall() { trap { Write-Host '' Write-Host 'There was problem starting the Windows Firewall service.' -ForegroundColor Red Write-Host 'The firewall service must be running during Exchange setup. It can be stopped after it completes.' -ForegroundColor Red Write-Host '' return } #Ensure Windows Firewall is running or Exchange install will fail Write-Host 'Starting the Windows Firewall service...' -NoNewline Set-Service 'MpsSvc' -StartupType Automatic -Status Running Write-Host 'done.' -ForegroundColor Green } if ($os -eq 'R1') { $ht = '. ServerManagerCmd.exe -ip '+$sourcePath+'\Exchange-Hub.xml' $cas = '. ServerManagerCmd.exe -ip '+$sourcePath+'\Exchange-CAS.xml' $mbx = '. ServerManagerCmd.exe -ip '+$sourcePath+'\Exchange-MBX.xml' $um = '. ServerManagerCmd.exe -ip '+$sourcePath+'\Exchange-UM.xml' $edge = '. ServerManagerCmd.exe -ip '+$sourcePath+'\Exchange-Edge.xml' $typical = '. ServerManagerCmd.exe -ip '+$sourcePath+'\Exchange-Typical.xml' } elseif ($os -eq 'R2') { $ht = 'Add-WindowsFeature NET-Framework,RSAT-ADDS,Web-Server,Web-Basic-Auth,Web-Windows-Auth,Web-Metabase,Web-Net-Ext,Web-Lgcy-Mgmt-Console,WAS-Process-Model,RSAT-Web-Server -restart' $cas = 'Add-WindowsFeature NET-Framework,RSAT-ADDS,Web-Server,Web-Basic-Auth,Web-Windows-Auth,Web-Metabase,Web-Net-Ext,Web-Lgcy-Mgmt-Console,WAS-Process-Model,RSAT-Web-Server,Web-ISAPI-Ext,Web-Digest-Auth,Web-Dyn-Compression,NET-HTTP-Activation,RPC-Over-HTTP-Proxy -restart' $mbx = 'Add-WindowsFeature NET-Framework,RSAT-ADDS,Web-Server,Web-Basic-Auth,Web-Windows-Auth,Web-Metabase,Web-Net-Ext,Web-Lgcy-Mgmt-Console,WAS-Process-Model,RSAT-Web-Server -restart' $um = 'Add-WindowsFeature NET-Framework,RSAT-ADDS,Web-Server,Web-Basic-Auth,Web-Windows-Auth,Web-Metabase,Web-Net-Ext,Web-Lgcy-Mgmt-Console,WAS-Process-Model,RSAT-Web-Server,Desktop-Experience -restart' $edge = 'Add-WindowsFeature NET-Framework,RSAT-ADDS,ADLDS -restart' $typical = 'Add-WindowsFeature NET-Framework,RSAT-ADDS,Web-Server,Web-Basic-Auth,Web-Windows-Auth,Web-Metabase,Web-Net-Ext,Web-Lgcy-Mgmt-Console,WAS-Process-Model,RSAT-Web-Server,Web-ISAPI-Ext,Web-Digest-Auth,Web-Dyn-Compression,NET-HTTP-Activation,RPC-Over-HTTP-Proxy -restart' Import-Module ServerManager } $opt = 'None' InstallApp('WinRM') clear if ($opt -ne 'None') {write-host 'Last command: '$opt -foregroundcolor Yellow} write-host write-host 'Exchange Server 2010 Prerequisites Installation' write-host 'Please select which role you are going to install:' write-host write-host '1) Hub Transport' write-host '2) Client Access Server' write-host '3) Mailbox' write-host '4) Unified Messaging' write-host '5) Edge Transport' write-host '6) Typical (CAS\HT\Mailbox)' write-host '7) Client Access and Hub Transport' write-host write-host '9) Configure NetTCP Port Sharing service' write-host ' Required for the Client Access Server role' -foregroundcolor yellow write-host ' Automatically set for options 2,6, and 7' -foregroundcolor yellow write-host '10) Install 2010 Office System Converter: Microsoft Filter Pack' write-host ' Required if installing Hub Transport or Mailbox Server roles' -foregroundcolor yellow write-host ' Automatically set for options 1,3,6, and 7' -foregroundcolor yellow Write-Host '11) Enable PowerShell Remoting' Write-Host ' Automatically set for options 1,2,3,4,6, and 7' -ForegroundColor Yellow write-host write-host '13) Restart the Server' write-host '14) End' write-host Write-Host 'Note: Using ' -NoNewline Write-Host $sourcePath -ForegroundColor DarkGreen -NoNewline Write-Host ' as the installation source.' $opt = Read-Host 'Select an option.. [1-14]? ' switch ($opt) { 1{ InstallNET35; InstallApp('OFP'); EnableFirewall; EnableRemoting Write-Host 'Beginning Windows components installation...' Invoke-Expression $ht } 2{ InstallNET35; EnableFirewall; EnableRemoting Write-Host 'Beginning Windows components installation...' Invoke-Expression $cas SetTCPSharing } 3{ InstallNET35; InstallApp('OFP'); EnableFirewall; EnableRemoting Write-Host 'Beginning Windows components installation...' Invoke-Expression $mbx } 4{ InstallNET35; EnableRemoting; EnableFirewall Write-Host 'Beginning Windows components installation...' Invoke-Expression $um } 5{ InstallNET35; EnableFirewall Write-Host 'Beginning Windows components installation...' Invoke-Expression $edge } 6{ InstallNET35; InstallApp('OFP'); EnableFirewall; EnableRemoting Write-Host 'Beginning Windows components installation...' Invoke-Expression $typical SetTCPSharing } 7{ InstallNET35; InstallApp('OFP'); EnableFirewall; EnableRemoting Write-Host 'Beginning Windows components installation...' Invoke-Expression $cas SetTCPSharing } 9 { SetTCPSharing } 10 { InstallApp('OFP') } 11 { EnableRemoting } 13 { Restart-Computer } 14 {write-host 'Exiting...'} default {write-host "You haven't selected any of the available options."} } |
Prepare-Exchange2010Install.zip (4.7 KiB)
Thank you for the script. I am reading “Forgotten God” by Francis Chan now. It is a good read.
hmm. I think it needs updating. when I run it it receives various errors about windows version number, .net 3.5 version update not relevant anymore. stuff like that.
You are correct that it doesn’t take into account the latest .NET updates that may have superseded what the script is looking for. It has been my intention to update the script to account for the latest fixes, but I haven’t had time to do so.