Script to install all Exchange 2010 prerequisites

Articles in the "Install Exchange 2010 Prerequisites" series

  1. Script to install all Exchange 2010 prerequisites [This article]
  2. Exchange 2010 prerequisite installation script updated
  3. Exchange 2010 prerequisite installation script updated
  4. 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.

You can copy the script inline below, or download it via the link at the bottom of the post.

#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)

3 thoughts on “Script to install all Exchange 2010 prerequisites

  1. Thank you for the script. I am reading “Forgotten God” by Francis Chan now. It is a good read.

  2. 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.

  3. 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.

Leave a Reply

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

*