SCRIPT: Exchange2010Prereqs.ps1

Script Name: Exchange2010Prereqs.ps1

Script Author: Pat Richard, MVP

Original Post: http://www.ucblogs.net/blogs/exchange/archive/2010/05/07/Automated-prerequisite-installation-via-PowerShell-for-Exchange-Server-2010-on-Windows-Server-2008-R2-_2D00_-v2.0.aspx

Log:
1.0 – Original script 11/27/09 based on the work of Anderson Patricio and Bhargav Shukla
1.1 – 04/09/2010 – added help; downloads of update rollups; cleanup of variables; added another option for typical install w/o RPC-Over-HTTP added RunOnce to delete download path on reboot
2.0 – 05/07/2010 – better detection of installed filter packs; uses Filter Pack 2; includes PDF iFilter pack; added disabling TCP/IP V6 option. Now uses BITS for file transfers; added unzip function to unzip the PDF iFilter pack download. Cleaned up some functions. Uses environmental variable “temp” for download location. Checks if things are already installed/downloaded/unzipped before trying to install/download/unzip them.
2.1 – 12/08/2011 – Added the new prerequisite introduced with the release of SP2, IIS 6 WMI Compatibility feature (Web-WMI). This is added to all options containing the CAS role

Code:

<#
.SYNOPSIS
   	Configures the necessary prerequisites to install Exchange 2010 on a Windows Server 2008 R2 server
.DESCRIPTION
    Installs all required Windows 2008 R2 components, the filter pack, and configures service startup settings. Provides options for disabling TCP/IP v6, downloading latest Update Rollup, etc.
.NOTES
    Version      	: 1.0 - 11/27/2009 - initial version
    			: 1.1 - 04/09/2010 - added help; downloads of update rollups; cleanup of variables; added another option for typical install w/o RPC-Over-HTTP
    			: 	added RunOnce to delete download path on reboot
			: 2.0 - 05/07/2010 - better detection of installed filter packs; uses Filter Pack 2; includes PDF iFilter pack; added disabling TCP/IP V6 option.
			:	Now uses BITS for file transfers; added unzip function to unzip the PDF iFilter pack download. Cleaned up some functions. Uses environmental
			:	variable "temp" for download location. Checks if things are already installed/downloaded/unzipped before trying to install/download/unzip them.
    Rights Required	: Local Admin on server
    Sched Task Req'd	: No
    Exchange Version	: 2010
    Author       	: Pat Richard, Exchange MVP
    Email / Blog 	: pat@innervation.com 	http://ucblogs.net/blogs/exchange
    Dedicated Blog	: http://www.ucblogs.net/blogs/exchange/archive/2009/12/12/Automated-prerequisite-installation-via-PowerShell-for-Exchange-Server-2010-on-Windows-Server-2008-R2.aspx
    Disclaimer   	: You running this script means you won't blame me if this breaks your stuff.
    Info Stolen from 	: Anderson Patricio and Bhargav Shukla
.LINK
    http://www.ucblogs.net/blogs/exchange/archive/2009/12/12/Automated-prerequisite-installation-via-PowerShell-for-Exchange-Server-2010-on-Windows-Server-2008-R2.aspx
.LINK
    http://msmvps.com/blogs/andersonpatricio/archive/2009/11/13/installing-exchange-server-2010-pre-requisites-on-windows-server-2008-r2.aspx
.LINK
    http://www.bhargavs.com/index.php/powershell/2009/11/script-to-install-exchange-2010-pre-requisites-for-windows-server-2008-r2/
.EXAMPLE
		.\Set-Exchange2010Prereqs.ps1
.INPUTS
		None. You cannot pipe objects to this script.
#>

#Requires -Version 2.0

# Detect correct OS here and exit if no match
if (-not((Get-WMIObject win32_OperatingSystem).OSArchitecture -eq '64-bit') -and (Get-WMIObject win32_OperatingSystem).Version -eq '6.1.7600'){
	Write-Host "`nThis script requires a 64bit version of Windows Server 2008 R2, which this is not. Exiting...`n" -ForegroundColor Red
	Exit
}
clear-host
pushd
[string] $targetfolder = "c:\Innervation"
# [string] $targetfolder = (Get-Content Env:Temp)
[bool] $wasinstalled = $false
[bool] $RebootRequired = $false
# determine if BitsTransfer is already installed
if (Get-Module BitsTransfer){$wasinstalled = $true}else{$wasinstalled = $false}

# this should probably get moved to a function...
if ((Get-Module ServerManager) -eq $null){Import-Module ServerManager}

[string] $opt = "None"
[bool] $HasInternetAccess = ([Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]'{DCB00C01-570F-4A9B-8D69-199FDBA5723B}')).IsConnectedToInternet)
[string] $menu = @'

	Exchange Server 2010 - Prerequisites script
	Please select an option from the list below..

	1) install Hub Transport prerequisites
	2) install Client Access Server prerequisites
	3) install Mailbox prerequisites
	4) install Unified Messaging prerequisites
	5) install Edge Transport prerequisites
	6) install Typical (CAS/HUB/Mailbox) prerequisites
	7) install Typical (CAS/HUB/Mailbox) prerequisites [NO RPC-OVER-HTTP]
    	8) install Client Access and Hub Transport prerequisites
	9) Configure NetTCP Port Sharing service
	   (Required for the Client Access Server role
	   Automatically set for options 2,6,7,8, and 11)
	10) Install 2010 Office System Converter: Microsoft Filter Pack 2.0
	    (Required if installing Hub Transport or Mailbox Server roles
	    Automatically set for options 1,3,6,7,8, and 11)
	11) install Typical (CAS/HUB/Mailbox) prerequisites [with .PDF ifilter]
	12) Download Exchange Server 2010 Update Rollup 3
	13) Disable TCP/IP V6
	14) Restart the Server
	15) Exit

'@

function InstallFilterPack(){
    # Office filter pack
    if ((Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{95140000-2000-0409-1000-0000000FF1CE}") -eq $false){
    	GetIt "http://download.microsoft.com/download/0/A/2/0A28BBFA-CBFA-4C03-A739-30CCA5E21659/FilterPack64bit.exe"
    	Set-Location $targetfolder
    	[string]$expression = ".\FilterPack64bit.exe /quiet /norestart /log:$targetfolder\FilterPack64bit.log"
    	Write-Host "File: FilterPack64bit.exe installing..." -NoNewLine
    	Invoke-Expression $expression
    	Start-Sleep -Seconds 20
    	if ((Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{95140000-2000-0409-1000-0000000FF1CE}") -eq $true){Write-Host "`b`b`b`b`b`b`b`b`b`b`b`b`binstalled!   " -Foregroundcolor Green}else{Write-Host "`b`b`b`b`b`b`b`b`b`b`b`b`bFAILED!" -Foregroundcolor Red}
    }else{
    	Write-Host "`nOffice filter pack already installed" -Foregroundcolor Green
    }
}# end installing office filter pack

function InstallPDFFilterPack(){
    # adobe ifilter
    if ((Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{5EA12CF3-8162-47F6-ACAF-45AD03EFB08F}") -eq $false){
    	GetIt "http://download.adobe.com/pub/adobe/acrobat/win/9.x/PDFiFilter64installer.zip"
    	UnZipIt "PDFiFilter64installer.zip" "PDFFilter64installer.msi"
    	Set-Location $targetfolder
    	[string]$expression = ".\PDFFilter64installer.msi /quiet /norestart /l* $targetfolder\PDFiFilter64Installer.log"
    	Write-Host "File: PDFFilter64installer.msi installing..." -NoNewLine
    	Invoke-Expression $expression
    	Start-Sleep -Seconds 20
    	if ((Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{5EA12CF3-8162-47F6-ACAF-45AD03EFB08F}") -eq $true){Write-Host "`b`b`b`b`b`b`b`b`b`b`b`b`binstalled!   " -Foregroundcolor Green}else{Write-Host "`b`b`b`b`b`b`b`b`b`b`b`b`bFAILED!" -Foregroundcolor Red}
    }else{
    	Write-Host "`nPDF filter pack already installed" -Foregroundcolor Green
    }
} # end installing pdf filter pack

function SetRunOnce(){
	# Sets the NetTCPPortSharing service for automatic startup before the first reboot
	# by using the old RunOnce registry key (because the service doesn't yet exist, or we could
	# use 'Set-Service')
	$hostname = (hostname)
	$RunOnceCommand1 = "sc \\$hostname config NetTcpPortSharing start= auto"
	if (Get-ItemProperty -Name "NetTCPPortSharing" -path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce' -ErrorAction SilentlyContinue) {
	    	Write-host "Registry key HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce\NetTCPPortSharing already exists." -ForegroundColor yellow
            Set-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce" -Name "NetTCPPortSharing" -Value $RunOnceCommand1 | Out-Null
	} else {
	    	New-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce" -Name "NetTCPPortSharing" -Value $RunOnceCommand1 -PropertyType "String" | Out-Null
	}
} # end SetRunOnce

function GetIt ([string]$sourcefile)	{
	if ($HasInternetAccess){
		# check if BitsTransfer is installed
		if ((Get-Module BitsTransfer) -eq $null){
			Write-Host "BitsTransfer: Installing..." -NoNewLine
			Import-Module BitsTransfer
			Write-Host "`b`b`b`b`b`b`b`b`b`b`b`b`binstalled!   " -ForegroundColor Green
		}
		[string] $targetfile = $sourcefile.Substring($sourcefile.LastIndexOf("/") + 1)
		if (Test-Path $targetfolder){
			Write-Host "Folder: $targetfolder exists."
		} else{
			Write-Host "Folder: $targetfolder does not exist, creating..." -NoNewline
			New-Item $targetfolder -type Directory | Out-Null
			Write-Host "`b`b`b`b`b`b`b`b`b`b`bcreated!   " -ForegroundColor Green
		}
		if (Test-Path "$targetfolder\$targetfile"){
			Write-Host "File: $targetfile exists."
		}else{
			Write-Host "File: $targetfile does not exist, downloading..." -NoNewLine
			Start-BitsTransfer -Source "$SourceFile" -Destination "$targetfolder\$targetfile"
			Write-Host "`b`b`b`b`b`b`b`b`b`b`b`b`b`bdownloaded!   " -ForegroundColor Green
		}
	}else{
		Write-Host "Internet Access not detected. Please resolve and try again." -foregroundcolor red
	}
} #end GetIt

function UnZipIt ([string]$source, [string]$target){
	if (Test-Path "$targetfolder\$target"){
		Write-Host "File: $target exists."
	}else{
		Write-Host "File: $target doesn't exist, unzipping..." -NoNewLine
		$sh = new-object -com shell.application
		$zipfolder = $sh.namespace("$targetfolder\$source")
		$item = $zipfolder.parsename("$target")
		$targetfolder2 = $sh.namespace("$targetfolder")
		Set-Location $targetfolder
		$targetfolder2.copyhere($item)
		Write-Host "`b`b`b`b`b`b`b`b`b`b`b`bunzipped!   " -ForegroundColor Green
		Remove-Item $source
	}
} #end UnZipIt

Do {
	if ($RebootRequired -eq $true){write-host "`t`t`t`t`t`t`t`t`t`n`t`t`t`tREBOOT REQUIRED!`t`t`t`n`t`t`t`t`t`t`t`t`t`n`t`tDO NOT INSTALL EXCHANGE BEFORE REBOOTING!`t`t`n`t`t`t`t`t`t`t`t`t" -backgroundcolor red -foregroundcolor black}
	if ($opt -ne "None") {write-host "Last command: "$opt -foregroundcolor Yellow}
	write-host $menu
	$opt = Read-Host "Select an option.. [1-15]? "

	switch ($opt)    {
		1 { InstallFilterPack; 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; $RebootRequired = $true }
		2 { SetRunOnce; 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,Web-WMI; $RebootRequired = $true }
		3 { InstallFilterPack; 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; $RebootRequired = $true }
		4 { 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; $RebootRequired = $true }
		5 { Add-WindowsFeature NET-Framework,RSAT-ADDS,ADLDS; $RebootRequired = $true }
		6 { SetRunOnce; InstallFilterPack; 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,Web-WMI; $RebootRequired = $true }
		7 { SetRunOnce; InstallFilterPack; 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,Web-WMI; $RebootRequired = $true }
		8 { SetRunOnce; InstallFilterPack; 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,Web-WMI; $RebootRequired = $true }
		9 { Set-Service NetTcpPortSharing -StartupType Automatic;Write-Host "done!" -ForegroundColor Green }
		10 { InstallFilterPack }
		11 { SetRunOnce; InstallFilterPack; InstallPDFFilterPack; 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,Web-WMI; $RebootRequired = $true }
		12 { GetIt "http://download.microsoft.com/download/A/C/0/AC0E7C57-9FF2-488A-938D-FD65C39B9B00/Exchange2010-KB981401-x64-en.msp"}
	        13 { Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters DisabledComponents 0xffffffff -type dword; Write-Host "done!" -foregroundcolor green; $RebootRequired = $true}
		14 { Restart-Computer }
		15 { if (($wasinstalled -eq $false) -and (Get-Module BitsTransfer)){Write-Host "Removing BitsTransfer..." -NoNewLine;Remove-Module BitsTransfer;Write-Host "removed!" -ForegroundColor Green};popd;write-host "Exiting..."}
		default {write-host "You haven't selected any of the available options. "}
	}
} while ($opt -ne 15)

18 thoughts on “SCRIPT: Exchange2010Prereqs.ps1

  1. Would it be beneficial to allow the user to decide which NIC to disable TCP/IP v6 on instead of disabling it on all NICs (say in disabling ip v6 only on Replication NIC)? And then, how about having a “Re-Enable TCP/IP v6 choice?

  2. is there a download link for the scripts….copying and pasting doesnt work at that well

    thanks

    edward

    • Hi Edward, thanks for commenting. If you mouse over the script code you should get the option to copy the script to you clip borard or open the script correctly formated in notepad in the left corner. Let me know if that does not work for you.

      • I’ve tried this page with three browsers and I’m not seeing a simple way to use this version of the script either. There’s no option to copy the script to clipboard and no link to open it in notepade. Have tried two versions of IE8 and Chrome.

        • I have used IE8 myself from different computers and servers and it works every time. You dont have to install flash to be able to copy to clipboard. When you mouse over the PS script you should to see a view source button up to the right of the PS script area. Hope this helps.

  3. Line 182 which is used for option 6 has a missing comma at the end …. RPC-Over-HTTP-ProxyWeb-WMI…. should instead be …RPC-Over-HTTP-Proxy,Web-WMI…. as that causes the roles to not install properly otherwise.

  4. Love the script!

    One small typo, though:

    at line 182 it reads in part:
    “RPC-Over-HTTP-ProxyWeb-WMI; ”

    but it is missing a comma between the final two modules ‘RPC-Over-HTTP-Proxy’ and ‘Web-WMI’ :
    “RPC-Over-HTTP-Proxy,Web-WMI; ”

    Without this change there is an error that module “”RPC-Over-HTTP-ProxyWeb-WMI” can’t be found.

  5. […] Anyone who’s done the deployments knows that based on the host operating system, certain prerequisites vary. Its a waste of time having to go and install the windows services, filter packs, etc on each server individually, when more than one server is involved in the process. Fortunately for us there’s a script available to facilitate this whole process. Pat Richard, Microsoft MVP created a script to make our lives a lot easier. This script can be found here. […]

  6. I edited the script so it’s also capable of installing Service Pack 2 fo Exchange Server 2010.

    Code:
    function InstallServicePack2(){
    # Exchange Service pack 2
    if ((Test-Path “HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{4934D1EA-BE46-48B1-8847-F1AF20E892C1}”) -eq $false){
    GetIt “http://download.microsoft.com/download/F/5/F/F5FADCEF-D96B-48C4-ADD9-067FDB1AEDB6/Exchange2010-SP2-x64.exe”
    Set-Location $targetfolder
    [string]$expression = “.\Exchange2010-SP2-x64.exe /x:$targetfolder\ExchSP2 /quiet”
    Write-Host “File: Exchange 2010 SP2 extracting…” -NoNewLine
    Invoke-Expression $expression
    Start-Sleep -Seconds 20
    Write-Host “Extracted!” -Foregroundcolor Green
    [string]$expression2 = “.\ExchSP2\setup /m:upgrade /InstallWindowsComponents”
    Write-Host “File: Exchange 2010 SP2 installing…” -NoNewLine
    Invoke-Expression $expression2
    Start-Sleep -Seconds 20
    if ((Test-Path “HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{4934D1EA-BE46-48B1-8847-F1AF20E892C1}”) -eq $true){Write-Host “`b`b`b`b`b`b`b`b`b`b`b`b`binstalled! ” -Foregroundcolor Green}else{Write-Host “`b`b`b`b`b`b`b`b`b`b`b`b`bFAILED!” -Foregroundcolor Red}
    }else{
    Write-Host “`nExchange 2010 Service Pack 2 already installed” -Foregroundcolor Green
    }
    }# end installing Exchange 2010 Serice pack 2

    Things could be a bit nicer or better, but this works for me!

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.