Script Name: Set-Lync2010Features.ps1
Script Authors: MVP Ståle Hansen, MVP Pat Richard and Marjus Sirvinsks
Log:
- v01 23.11.2010
- Initial Script based on the work of Pat Richard, Anderson Patricio and Bhargav Shukla
- Thanks to Marjus Sirvinsks for adapting the script for OCS and Lync
- Installs prerequisites based on this blog article: https://msunified.net/2010/11/23/installing-lync-server-2010-prerequisites-on-windows-server-2008-r2/
- Added option for downloading and installing Lync Server 2010 Resource Kit
- v02 20.12.2010
- Added option for Exit and reboot server
- v03 22.02.2011
- Added option to download and install the Lync BPA
- v04 06.04.2011
- Pat Richard updated the script with a lot of nifty features. Documented here: http://www.ehloworld.com/236
- v05 25.07.2011
- Pat Richard updated the script with even more nifty features. Documented here: http://www.ehloworld.com/255
- v05.3 23.12.2011
- Pat Richard updated the script with even more nifty features like Mobility and a good segmentation on pre and post work. Documented here: http://www.ehloworld.com/255
#Requires -Version 2.0
[string] $FilenameTranscript = $MyInvocation.MyCommand.Name + " " + (hostname)+ " {0:yyyy-MM-dd hh-mmtt}.log" -f (Get-Date)
Start-Transcript -path .\$FilenameTranscript | Out-Null
$error.clear()
# Detect correct OS here and exit if no match (we intentionally truncate the last character to account for service packs)
if ((Get-WMIObject win32_OperatingSystem).Version -notmatch '6.1.760'){
Write-Host "`nThis script requires a version of Windows Server 2008 R2, which this is not. Exiting...`n" -ForegroundColor Red
Stop-Transcript
Exit
} #end OS detection
Clear-Host
pushd
[string] $TargetFolder = "c:\_Install"
[bool] $global:RebootRequired = $false
if ((Get-Module BitsTransfer).installed -eq $true){
[bool] $WasInstalled = $true
}else{
[bool] $WasInstalled = $false
}
[string] $MenuOption = "None"
[bool] $HasInternetAccess = ([Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]'{DCB00C01-570F-4A9B-8D69-199FDBA5723B}')).IsConnectedToInternet)
[string] $Menu = @'
**********************************
Lync Server 2010 - Features script
**********************************
Please select an option from the choices below.
Preinstallation steps
========================
1) Front-End
2) Director
3) Monitoring/Archiving
4) Communicator Web Access (OCS 2007 R2)
5) Mediation/Edge/XMPP GW/AV Conferencing
6) Install Unified Communications Managed API 3.0 Runtime (alpha)
7) GroupChat
11) Disable IPv6
12) Install telnet client
13) Install Visual C++ 2008 Redistributable
16) Check group membership
20) OWA/Lync integration (run on Exchange server) (alpha)
22) Install Microsoft Silverlight
23) Install Windows Media Format Runtime
27) Install loopback adapter (beta)
29) Download Lync Server 2010 (trial)
31) Check Local Security Settings
'@
# front end server
if (Get-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{78D5615E-F753-40C1-B301-9AAD2727B9C8}" -ErrorAction SilentlyContinue){
# {3F297EB8-2526-4B0E-A7A4-143E202EF0DE} for monitoring server
# {9521B708-9D80-46A3-9E58-A74ACF4E343E} for core components
[bool]$isLyncInstalled = $true
$Menu += @'
Post installation steps
========================
8) Install Lync Server 2010 Resource Kit
9) Install Lync Server 2010 Best Practices Analyzer
10) Install Lync Server 2010 Stress and Performance Tool
14) Install Lync 'IM an Expert' (alpha)
15) Launch Windows Update
17) Download 07-25-2011 Lync Server 2010 updates & start updater program
18) Install 07-20-2011 Microsoft Lync Server 2010 Documentation Help File
19) Backup local Lync server configuration
21) Install 'Find Lync Versions' (includes .Net 4 installation)
26) Enable federation with Office365
28) Install Windows Update PowerShell module
30) Restrict features to Standard CAL
'@
}else{
[bool]$isLyncInstalled = $false
}
$Menu += @'
98) Restart the server
99) Exit
Select an option.. [1-99]?
'@
function New-FileDownload ([string]$SourceFile,[string]$DestFolder,[string]$DestFile) {
# I should switch this to using a param block and pipelining from property name - just for consistency
# I should clean up the display text to be consistent with other functions
$error.clear()
if (!($DestFolder)){$DestFolder = $TargetFolder}
Get-ModuleStatus -name BitsTransfer
if (!($DestFile)){[string] $DestFile = $SourceFile.Substring($SourceFile.LastIndexOf("/") + 1)}
if (Test-Path $DestFolder){
Write-Host "Folder: `"$DestFolder`" exists."
} else{
Write-Host "Folder: `"$DestFolder`" does not exist, creating..." -NoNewline
New-Item $DestFolder -type Directory
Write-Host "Done! " -ForegroundColor Green
}
if (Test-Path "$DestFolder\$DestFile"){
Write-Host "File: $DestFile exists."
}else{
if ($HasInternetAccess){
Write-Host "File: $DestFile does not exist, downloading..." -NoNewLine
Start-BitsTransfer -Source "$SourceFile" -Destination "$DestFolder\$DestFile"
Write-Host "Done! " -ForegroundColor Green
}else{
Write-Host "Internet access not detected. Please resolve and try again." -ForegroundColor red
}
}
} # end function New-FileDownload
function New-UnzippedFile {
param (
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No zip file specified")]
[string]$ZipFile,
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No file to unzip specified")]
[string]$UnzipFile,
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No location to unzip file specified")]
[string]$UnzipFileLocation
)
$error.clear()
Write-Host "Zip File........................................................[" -NoNewLine
Write-Host "Unzipping" -ForegroundColor yellow -NoNewLine
Write-Host "]" -NoNewLine
if (Get-Item $zipfile){
$objShell = new-object -com shell.application
# where the .zip is
$FuncZipFolder = $objShell.namespace($ZipFile)
# the item in the zip
$FuncFile = $FuncZipFolder.parsename($UnzipFile)
# where the item is to go
$FuncTargetFolder = $objShell.namespace($UnzipFileLocation)
# do the copy of zipfile item to target folder
$FuncTargetFolder.copyhere($FuncFile)
}
if ($error){
Write-Host "`b`b`b`b`b`b`b`b`b`bfailed!" -ForegroundColor red -NoNewLine
}else{
Write-Host "`b`b`b`b`b`b`b`b`b`bdone!" -ForegroundColor green -NoNewLine
}
Write-Host "] "
} # end function New-UnzippedFile
function New-Shortcut {
param (
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No shortcut name specified")]
[string]$ShortcutName,
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No shortcut file specified")]
[string]$ShortcutFile,
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No shortcut working directory specified")]
[string]$ShortcutWorkingDir,
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No shortcut description specified")]
[string]$ShortcutDescription
)
$error.clear()
# AllUsers start menu = "$env:ProgramData\Microsoft\Windows\Start Menu\Programs"
Write-Host "Shortcut........................................................[" -NoNewLine
Write-Host "Creating" -ForegroundColor yellow -NoNewLine
Write-Host "]" -NoNewLine
if (Get-Item $ShortcutFile){
$wshshell = New-Object -ComObject WScript.Shell
if (($ShortcutName.Substring($ShortcutName.Length – 4, 4) -ne ".lnk") -and ($ShortcutName.Substring($ShortcutName.Length – 4, 4) -ne ".url")){
$ShortcutName += ".lnk"
}
$lnk = $wshshell.CreateShortcut($ShortcutName)
$lnk.TargetPath = $ShortcutFile
#maps to Start in: on GUI
$lnk.WorkingDirectory = $ShortcutWorkingDir
#corresponds to the Comment field on the shortcut tab.
$lnk.Description = $ShortcutDescription
$lnk.Save()
}
if ($error){
Write-Host "`b`b`b`b`b`b`b`b`b`bfailed!" -ForegroundColor red -NoNewLine
}else{
Write-Host "`b`b`b`b`b`b`b`b`bcreated!" -ForegroundColor green -NoNewLine
}
Write-Host "] "
} # end function New-Shortcut
function New-ProgramInstallation {
param (
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No installation file specified")]
[string]$InstallFile,
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No installation switches specified")]
[string]$InstallSwitches
)
$error.clear()
$DestFile = $InstallFile.Substring($InstallFile.LastIndexOf("\") + 1)
Write-Host "File: $DestFile" -NoNewLine
for($i=0;$i -lt (64 - ($DestFile.length + 6));$i++){Write-Host "." -NoNewLine}
Write-Host "[" -NoNewLine
Write-Host "Installing" -ForegroundColor yellow -NoNewLine
Write-Host "]" -NoNewLine
$install = $InstallFile + " " + $InstallSwitches
Invoke-Expression $install
if ($error){
Write-Host "`b`b`b`b`b`b`b`b`b`b`bFailed" -ForegroundColor Red -NoNewLine
}else{
Write-Host "`b`b`b`b`b`b`b`b`b`b`binstalled!" -ForegroundColor Green -NoNewLine
}
Write-Host "] "
} # end function New-ProgramInstallation
function New-FileShare {
param (
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No folder name specified")]
[string]$FolderName,
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No share name specified")]
[string]$ShareName,
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$false, HelpMessage="No description specified")]
[string]$Description
)
$error.clear()
# Check for folder; Create it if it doesn't exist
If (!(Test-Path $FolderName)) {
New-Item $FolderName -type Directory | Out-Null
}
# Check for share; Create it if it doesn't exist
$Shares=[WMICLASS]"WIN32_Share"
if (!(Get-WMIObject Win32_share -filter "name='$ShareName'")){
$Shares.Create($FolderName,$ShareName,0,65535,$Description) | Out-Null
if (!($error)){
# the share was created
return $true
} else {
# there was an error
return $false
}
} else {
# the share already exists
return $false
}
} # end function New-FileShare
function New-EventLogEntry {
param (
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No event log text specified")]
[string]$EventLogText,
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No event type specified")]
[ValidateSet("Error","Warning","Information","SuccessAudit","FailureAudit")]
[string]$EventType,
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No event source specified")]
[string]$EventSource,
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No event log specified")]
[ValidateSet("Application","Security","Setup","System","Hardware Events","Internet Explorer","Key Management Service","Lync Server")]
[string]$EventLog,
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No event ID specified")]
[ValidateRange(0,65535)]
[int]$EventID
)
$objEvt = new-object System.Diagnostics.EventLog("System")
# $objEvt.Source = $strScriptName
$objEvt.Source = $EventSource
# to see all possible event types: [enum]::getvalues([system.diagnostics.eventlogentrytype])
# $infoevent=[System.Diagnostics.EventLogEntryType]::Information
$objEvt.WriteEntry($EventLogText,$EventType,$eventID)
} # end function New-EventLogEntry
function Install-WindowsMediaFormatRuntime {
# Requires local admin
# required if installing Lync on Front End servers running Server 2008 SP1
# If this isn't done BEFORE installing Lync, an installation error may occur as per
# http://support.microsoft.com/kb/2522454
if ((Get-WMIObject win32_OperatingSystem).Version -eq '6.1.7601'){
$error.clear()
New-ProgramInstallation -InstallFile "$env:systemroot\system32\dism.exe" -InstallSwitches "/online /add-package /packagepath:$env:windir\servicing\Packages\Microsoft-Windows-Media-Format-Package~31bf3856ad364e35~amd64~~6.1.7601.17514.mum /ignorecheck /NoRestart /quiet /logpath:$TargetFolder\dism.log"
$global:RebootRequired = $true
}
} # end function Install-WindowsMediaFormatRuntime
function Install-TelnetClient {
Get-ModuleStatus -name "ServerManager"
if ((Get-WindowsFeature Telnet-Client).installed -eq $false){
$a = New-Object -comobject wscript.shell
$intAnswer = $a.popup("Do you want to include Telnet client?",0,"Telnet client",4)
if ($intAnswer -eq 6) {
#yes
# Get-ModuleStatus -name "ServerManager"
#if ((Get-WindowsFeature Telnet-Client).installed -eq $false){
Add-WindowsFeature Telnet-Client | Out-Null
#} else {
#Write-Host "Telnet client already installed"
#}
} else {
#no
# $a.popup("You answered no.")
}
}
} # end function Install-TelnetClient
function Install-DocViewer {
$a = new-object -comobject wscript.shell
$intAnswer = $a.popup("Lync Resource Kit documentation is based on Microsoft Word. Would you like to install the free Word viewer?",0,"Word Viewer",4)
if ($intAnswer -eq 6) {
#yes
if (!(Get-Item "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{90850409-6000-11D3-8CFE-0150048383C9}" -ErrorAction SilentlyContinue)){
New-FileDownload "http://download.microsoft.com/download/6/a/6/6a689355-b155-4fa7-ad8a-dfe150fe7ac6/wordview_en-us.exe"
New-ProgramInstallation -InstallFile "$TargetFolder\wordview_en-us.exe" -InstallSwitches "/q"
}
if (!(Get-Item "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{90120000-0020-0409-0000-0000000FF1CE}" -ErrorAction SilentlyContinue)){
New-FileDownload "http://download.microsoft.com/download/9/2/2/9222D67F-7630-4F49-BD26-476B51517FC1/FileFormatConverters.exe"
New-ProgramInstallation -InstallFile "$TargetFolder\FileFormatConverters.exe" -InstallSwitches "/q"
}
} else {
#no
# $a.popup("You answered no.")
}
} # end function Install-DocViewer
function Install-SilverLight {
# http://dwlpr.wordpress.com/2010/04/15/silverlight-4-final-download-direct-link/
if (!(Get-Item "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{89F4137D-6C26-4A84-BDB8-2E5A4BB71E00}" -ErrorAction SilentlyContinue)){
# 4.0.50401.0 (doesn't include hotfix from KB 2512827)
# New-FileDownload "http://download.microsoft.com/download/2/2/C/22CABA89-3580-4611-8E0D-56749D2120DF/runtime/Silverlight.exe"
# 4.0.60531.0 (http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=26488)
New-FileDownload "http://download.microsoft.com/download/C/0/B/C0B404F0-F025-4156-95B0-164AD7CA07AA/runtime/Silverlight.exe"
New-ProgramInstallation -InstallFile "$TargetFolder\silverlight.exe" -InstallSwitches "/q"
}
} # end function Install-SilverLight
function Install-VisualC++Redist {
if (!(Get-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{4B6C7001-C7D6-3710-913E-5BC23FCE91E6}" -ErrorAction SilentlyContinue)){
# 9.0.30729.4148
# New-FileDownload "http://download.microsoft.com/download/9/7/7/977B481A-7BA6-4E30-AC40-ED51EB2028F2/vcredist_x64.exe"
# New-ProgramInstallation -InstallFile "$TargetFolder\vcredist_x64.exe" -InstallSwitches "/qb"
# should add update from KB 2538243 (MS11-025) install with /q (see http://www.microsoft.com/technet/security/bulletin/MS11-025.mspx)(http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=26368)
# 9.0.30729.6161
New-FileDownload "http://download.microsoft.com/download/5/D/8/5D8C65CB-C849-4025-8E95-C3966CAFD8AE/vcredist_x64.exe"
New-ProgramInstallation -InstallFile "$TargetFolder\vcredist_x64.exe" -InstallSwitches "/qb"
# validate by checking HKLM:\SOFTWARE\Microsoft\DevDiv\VC\Servicing\9.0\RED\1033 for "Install" = dword:1
Do {Start-Sleep -m 100}while(!(Get-ItemProperty HKLM:\SOFTWARE\Microsoft\DevDiv\VC\Servicing\9.0\RED\1033 -Name Install -ErrorAction SilentlyContinue))
}
} # end function Install-VisualC++Redist
function Get-ModuleStatus {
param (
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No module name specified!")]
[string]$name
)
if(!(Get-Module -name "$name")) {
if(Get-Module -ListAvailable | ? {$_.name -eq "$name"}) {
Import-Module -Name "$name"
# module was imported
return $true
} else {
# module was not available
return $false
}
}else {
# module was already imported
# Write-Host "$name module already imported"
return $true
}
} # end function Get-ModuleStatus
function Get-WebPage{
param (
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No URL specified!")]
[string]$url
)
$ie = new-object -comobject internetexplorer.application;
$ie.Navigate($url);
$ie.Visible = $true;
} # end function Get-WebPage
function Remove-IPv6 {
$error.clear()
Write-Host "TCP/IP v6......................................................[" -NoNewLine
Write-Host "removing" -ForegroundColor yellow -NoNewLine
Write-Host "]" -NoNewLine
Set-ItemProperty -path HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters -name DisabledComponents -value 0xffffffff -type dword
if ($error){
Write-Host "`b`b`b`b`b`b`b`bfailed!" -ForegroundColor red -NoNewLine
}else{
Write-Host "`b`b`b`b`b`b`b`b`bdone!" -ForegroundColor green -NoNewLine
}
Write-Host "] "
$global:RebootRequired = $true
} # end function Remove-IPv6
function Remove-ScriptVariables($path) {
$result = Get-Content $path |
ForEach { if ( $_ -match '(\$.*?)\s*=') {
$matches[1] | ? { $_ -notlike '*.*' -and $_ -notmatch 'result' -and $_ -notmatch 'env:'}
}
}
ForEach ($v in ($result | Sort-Object | Get-Unique)){
# Write-Host "Removing" $v.replace("$","")
Remove-Variable ($v.replace("$","")) -ErrorAction SilentlyContinue
}
} # end function Get-ScriptVariables
function Get-RegistryValue { # http://powershell.com/cs/blogs/tips/archive/2009/11/25/reading-registry-values.aspx
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No registry key specified.")]
$key,
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No value specified!")]
$value
)
(Get-ItemProperty $key $value).$value
} # end function Get-RegistryValue
Do {
if ($global: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 Lync BEFORE REBOOTING!`t`t`n`t`t`t`t`t`t`t`t`t" -ForegroundColor yellow}
if ($MenuOption -ne "None") {Write-Host "`nLast command: "$MenuOption -BackgroundColor Yellow -ForegroundColor black}
$MenuOption = Read-Host $Menu
switch ($MenuOption) {
1 { # Front-End
Get-ModuleStatus -name "ServerManager"
Install-VisualC++Redist
Install-TelnetClient
Add-WindowsFeature NET-Framework-Core, msmq-server, msmq-directory, RSAT-ADDS, Web-Static-Content, Web-Default-Doc, Web-Http-Errors, Web-Asp-Net, Web-Net-Ext, Web-ISAPI-Ext, Web-ISAPI-Filter, Web-Http-Logging, Web-Log-Libraries, Web-Http-Tracing, Web-Windows-Auth, Web-Filtering, Web-Stat-Compression, Web-Mgmt-Console, Web-Scripting-Tools, Web-Client-Auth, Web-Dyn-Compression, Desktop-Experience | Out-Null
Install-SilverLight
Install-WindowsMediaFormatRuntime
$global:RebootRequired = $true
}
2 { # Director
Get-ModuleStatus -name "ServerManager"
Install-VisualC++Redist
Install-TelnetClient
Add-WindowsFeature NET-Framework-Core, msmq-server, msmq-directory, Web-Static-Content, Web-Default-Doc, Web-Http-Errors, Web-Asp-Net, Web-Net-Ext, Web-ISAPI-Ext, Web-ISAPI-Filter, Web-Http-Logging, Web-Log-Libraries, Web-Http-Tracing, Web-Windows-Auth, Web-Filtering, Web-Stat-Compression, Web-Mgmt-Console, Web-Scripting-Tools, Web-Client-Auth, Web-Dyn-Compression | Out-Null
Install-SilverLight
$global:RebootRequired = $true
}
3 { # Monitoring/Archiving
Get-ModuleStatus -name "ServerManager"
Install-VisualC++Redist
Install-TelnetClient
Add-WindowsFeature NET-Framework-Core, msmq-server, msmq-directory
}
4 { # Communicator Web Access (OCS 2007 R2)
Get-ModuleStatus -name "ServerManager"
Install-TelnetClient
Add-WindowsFeature NET-Framework-Core, web-server, web-http-redirect, web-asp-net, web-http-logging, web-log-libraries, web-request-monitor, web-http-tracing, web-basic-auth, web-windows-auth, web-mgmt-console, web-scripting-tools, web-mgmt-compat, was-process-model, was-net-environment, rsat-adds
$global:RebootRequired = $true
}
5 { # Mediation/Edge/XMPP GW/AV Conferencing
Get-ModuleStatus -name "ServerManager"
Install-VisualC++Redist
Install-TelnetClient
Add-WindowsFeature NET-Framework-Core, msmq-server, msmq-directory
}
6 { # Unified Communications Managed API 3.0 Runtime
New-FileDownload "http://download.microsoft.com/download/3/B/1/3B13662A-8445-4238-A685-F15899032755/UcmaRuntimeSetup.exe"
New-ProgramInstallation -InstallFile "$TargetFolder\UcmaRuntimeSetup.exe" -InstallSwitches "/qb"
}
7 { # GroupChat
Get-ModuleStatus -name "ServerManager"
Install-TelnetClient
Add-WindowsFeature NET-Framework-Core, web-server, web-mgmt-compat, web-asp-net, msmq-server, msmq-directory, rsat-adds
$global:RebootRequired = $true
}
8 { # Lync Server 2010 Resource Kit
if (!(Get-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{9C44E652-CBBC-4E1C-8172-21A7D46CAB85}" -ErrorAction SilentlyContinue)){
$error.clear()
New-FileDownload "http://download.microsoft.com/download/1/8/A/18ADD884-E16F-4AD3-8422-FC80073439AA/OCSReskit.msi"
Get-ModuleStatus -name "ServerManager"
Add-WindowsFeature NET-Framework-Core
New-ProgramInstallation -InstallFile "$TargetFolder\OCSReskit.msi" -InstallSwitches "/qb"
}
Install-DocViewer
}
9 { # Lync Server 2010 Best Practices Analyzer
if ((!(Get-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{88033F09-23A0-44EC-9063-7CBAA4BE4975}" -ErrorAction SilentlyContinue))-and $isLyncInstalled){
$error.clear()
New-FileDownload "http://download.microsoft.com/download/3/3/8/338D2314-1D23-47C1-8BB4-80FD39B84EA6/RTCBPA.msi"
Get-ModuleStatus -name "ServerManager"
Add-WindowsFeature NET-Framework-Core
New-ProgramInstallation -InstallFile "$TargetFolder\RTCBPA.msi" -InstallSwitches "/qb"
}
}
10 { # Lync Server 2010 Stress and Performance Tool
if ((!(Get-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{94FD6E73-38F6-4DBE-AA3B-E403678868C9}" -ErrorAction SilentlyContinue)) -and $isLyncEnabled){
Get-ModuleStatus -name "ServerManager"
Add-WindowsFeature NET-Framework-Core
Install-VisualC++Redist
New-FileDownload "http://download.microsoft.com/download/7/1/E/71EC25F9-575C-47BF-A4C0-E5DFFD42AA56/CapacityPlanningTool.msi"
New-ProgramInstallation -InstallFile "$TargetFolder\CapacityPlanningTool.msi" -InstallSwitches "/qb"
}
Install-DocViewer
}
11 { # Disable IPv6
Remove-IPv6
}
12 { # telnet client
Install-TelnetClient
}
13 { # Visual C++ 2008 Redistributable
Install-VisualC++Redist
}
14 { # Lync 'IM an Expert'
if ($isLyncInstalled){
Get-ModuleStatus -name "ServerManager"
Add-WindowsFeature NET-Framework-Core
New-FileDownload "http://download.microsoft.com/download/3/B/1/3B13662A-8445-4238-A685-F15899032755/UcmaRuntimeSetup.exe"
New-ProgramInstallation -InstallFile "$TargetFolder\UcmaRuntimeSetup.exe" -InstallSwitches "/q"
New-FileDownload "http://download.microsoft.com/download/9/E/2/9E2CBE89-A25F-4158-A2FC-CD227FC4ED14/IManExpert.msi"
New-ProgramInstallation -InstallFile "$TargetFolder\IManExpert.msi" -InstallSwitches "/qb"
}
}
15 { # Windows Update
Invoke-Expression "$env:windir\system32\wuapp.exe startmenu"
}
16 { # Check group membership
Whoami /groups /fo list | findstr /I BUILTIN\Administrators; Whoami /groups /fo list | findstr /I Cs; Whoami /groups /fo list | findstr /I Rtc
}
17 { # Lync Server 2010 updates
if ((!(Get-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{9521B708-9D80-46A3-9E58-A74ACF4E343E}" -ErrorAction SilentlyContinue))-and $isLyncInstalled){
New-FileDownload "http://download.microsoft.com/download/3/4/1/341C256C-0E74-4968-B6FA-EEA87600E283/LyncServerUpdateInstaller.exe"
New-ProgramInstallation -InstallFile "$TargetFolder\LyncServerUpdateInstaller.exe" -InstallSwitches ""
}
}
18 { # Microsoft Lync Server 2010 Documentation Help File (07-20-2011)
if ($isLyncInstalled){
# http://www.microsoft.com/download/en/details.aspx?id=23888
New-FileDownload "http://download.microsoft.com/download/E/F/B/EFBBCD0C-CC33-4E91-B921-05D47550B9BF/Lync_ITPro.exe"
New-ProgramInstallation -InstallFile "$TargetFolder\Lync_ITPro.exe" -InstallSwitches "-auto"
Do {Start-Sleep -m 100}while(Get-Process | ?{$_.ProcessName -match "Lync_ITPro"})
New-Shortcut -ShortcutName "$env:public\Desktop\Lync Server 2010 Help Documentation.lnk" -ShortcutFile "C:\Program Files\Microsoft Lync Server 2010\Documentation\Lync_ITPro.chm" -ShortcutWorkingDir "C:\Program Files\Microsoft Lync Server 2010\Documentation" -ShortcutDescription "Lync Server 2010 Help Documentation"
}
}
19 { # Backup local Lync server configuration
if ($isLyncInstalled){
# http://blog.danovich.com.au/2010/12/30/scheduled-task-powershell-script-to-backup-lync-server-2010-config/
[string] $FileNameConfigBackup = "$TargetFolder\config backup " + (hostname)+ " {0:yyyy-MM-dd hh-mmtt}.zip" -f (Get-Date)
Export-CsConfiguration -Filename .\$FileNameConfigBackup -Force:$True
# Should also incorporate http://blogs.technet.com/b/uc_mess/archive/2011/03/17/lync_2d00_server_2d00_2010_2d00_backup_2d00_instructions.aspx
}
}
20 { # OWA/Lync integration
Get-ModuleStatus ServerManager
if ((Get-WindowsFeature Net-Framework).Installed -eq $true){
# to do: determine if we're running within the Exchange management shell
popd
# if ($env:ExchangeInstallPath){
if (!(Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{02FD4158-9AFC-455F-B8FD-5C7C75D973AA}" -Name UninstallString -ErrorAction SilentlyContinue)){
New-FileDownload "http://download.microsoft.com/download/C/D/6/CD65672F-E0D1-471B-8404-B7B63966A8AA/CWAOWASSPMain.msi"
New-ProgramInstallation -InstallFile "$TargetFolder\CWAOWASSPMain.msi" -InstallSwitches "/qb"
Do {Start-Sleep -m 100}while(!(Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{02FD4158-9AFC-455F-B8FD-5C7C75D973AA}" -Name UninstallString -ErrorAction SilentlyContinue))
}
$InstallDir = "C:\Web Service Provider Installer Package"
Set-Location $InstallDir
Start-Sleep -s 15
New-ProgramInstallation -InstallFile ".\vcredist_x64.exe" -InstallSwitches "/qb"
Do {Start-Sleep -m 100}while(Get-Process "vcredist_x64.exe" -ErrorAction SilentlyContinue)
# Do {Start-Sleep -m 100}while(!(Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{350AA351-21FA-3270-8B7A-835434E766AD}" -Name UninstallString -ErrorAction SilentlyContinue))
Start-Sleep -s 15
New-ProgramInstallation -InstallFile ".\UcmaRedist.msi" -InstallSwitches "/qb"
# Do {Start-Sleep -m 100}while(Get-Process "msiexec*" -ErrorAction SilentlyContinue)
Do {Start-Sleep -m 100}while(!(Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{7EB901DD-CB50-4046-A434-3E9A112E8F86}" -Name UninstallString -ErrorAction SilentlyContinue))
New-FileDownload "http://download.microsoft.com/download/3/6/9/3693C940-1B9A-4386-836F-A21C7F4AE9C6/UcmaRedist.msp" $InstallDir
New-ProgramInstallation -InstallFile ".\UcmaRedist.msp" -InstallSwitches "/qb"
# Do {Start-Sleep -m 100}while(Get-Process "msiexec*" -ErrorAction SilentlyContinue)
Start-Sleep -s 15
New-FileDownload "http://download.microsoft.com/download/D/9/6/D967F77F-D0BD-43FB-987B-6FBF7C82251B/UcmaRedist.msp" $InstallDir "UcmaRedist-R2.msp"
New-ProgramInstallation -InstallFile ".\UcmaRedist-R2.msp" -InstallSwitches "/qb"
# Do {Start-Sleep -m 100}while(Get-Process "msiexec*" -ErrorAction SilentlyContinue)
Start-Sleep -s 15
# This does a detected for the CAS role
New-ProgramInstallation -InstallFile ".\CWAOWASSP.msi" -InstallSwitches "/qb"
# Do {Start-Sleep -m 100}while(Get-Process "msiexec*" -ErrorAction SilentlyContinue)
Do {Start-Sleep -m 100}while(!(Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{D702B231-2EA5-4AD7-85E1-713538CBD656}" -Name NoRemove -ErrorAction SilentlyContinue))
New-FileDownload "http://download.microsoft.com/download/C/2/7/C27C449E-76FB-4BBF-A899-A82C2BBEB47C/CWAOWASSP.msp" $InstallDir
New-ProgramInstallation -InstallFile ".\CWAOWASSP.msp" -InstallSwitches "/qb"
# Do {Start-Sleep -m 100}while(Get-Process "msiexec*" -ErrorAction SilentlyContinue)
Start-Sleep -s 15
[string] $LyncPool = Read-Host "Enter FQDN of Lync front end server/pool"
[string] $CertThumbprint = (Get-ExchangeCertificate | Where {$_.Services -ilike "*IIS*"}).Thumbprint
[string] $CertSubject = (Get-ExchangeCertificate | Where {$_.Services -ilike "*IIS*"}).Subject
$CertSubject = $subject.substring(3,$subject.indexof(",")-3)
Get-ExchangeServer (hostname) | Get-OWAVirtualDirectory | Set-OWAVirtualDirectory -InstantMessagingType OCS -InstantMessagingEnabled:$true -InstantMessagingCertificateThumbprint $CertThumbprint -InstantMessagingServerName $LyncPool
Get-ExchangeServer (hostname) | Get-OWAVirtualDirectory | fl name,instant*
# prompt user to create CSTrustedApp using CN from certificate
Write-Host "Create CsTrustedApplication using the name $CertSubject"
#}else{
#Write-Host "Exchange not detected. Cannot complete." -ForegroundColor red
#}
} else { Write-Warning "Net-Framework not installed"
}
}
21 { # Find Lync Versions
if ($isLyncInstalled){
if (!(Get-ItemProperty "HKLM:\Software\Microsoft\NET Framework Setup\NDP\v4\Full" -Name install -ErrorAction SilentlyContinue | Out-Null)){
New-FileDownload "http://download.microsoft.com/download/9/5/A/95A9616B-7A37-4AF6-BC36-D6EA96C8DAAE/dotNetFx40_Full_x86_x64.exe"
New-ProgramInstallation -InstallFile "$TargetFolder\dotNetFx40_Full_x86_x64.exe" -InstallSwitches "/q"
}
New-FileDownload "http://www.stumper66.com/software/files/Find Lync Versions.zip"
New-UnzippedFile -ZipFile "$TargetFolder\Find Lync Versions.zip" -UnzipFile "Find Lync Versions.exe" -UnzipFileLocation "C:\Program Files\Microsoft Lync Server 2010\Administrative Tools"
New-Shortcut -ShortcutName "$env:public\Desktop\Find Lync Versions" -ShortcutFile "C:\Program Files\Microsoft Lync Server 2010\Administrative Tools\Find Lync Versions.exe" -ShortcutWorkingDir "C:\Program Files\Microsoft Lync Server 2010\Administrative Tools" -ShortcutDescription "Display client version and connection info"
}
}
22 { # SilverLight
Install-SilverLight
}
23 { # WindowsMediaFormatRuntime
Install-WindowsMediaFormatRuntime
}
24 { # Upload phone firmware update
}
25 { # create file share
# New-FileShare -FolderName "c:\LyncShare" -ShareName "LyncShare" -Description "Used by Lync server to store Address Book files, phone updates, and other important files."
}
26 { # enable federation with Office365
if ($isLyncInstalled){
$error.clear()
# need menu display
Set-CsExternalAccessPolicy "global" -EnableFederationAccess $true
Write-Host "Office365 federation............................................[" -NoNewLine
Write-Host "configuring" -ForegroundColor yellow -NoNewLine
Write-Host "]" -NoNewLine
if (Get-ModuleStatus -name "Lync") {
if(!(Get-CsHostingProvider | ? {$_.proxyFqdn -match "sipfed.online.lync.com"})){
New-CSHostingProvider –identity "Office365" –ProxyFqdn "sipfed.online.lync.com" –Enabled $true -ErrorAction SilentlyContinue | Out-Null
if (!($error)){
Write-Host "`b`b`b`b`b`b`b`b`b`b`b`bdone!" -ForegroundColor green -NoNewLine
}else{
Write-Host "`b`b`b`b`b`b`b`b`b`b`b`bFailed!" -ForegroundColor red -NoNewLine
}
} else {
Write-Host "`b`b`b`b`b`b`b`b`b`b`b`balready enabled!" -ForegroundColor green -NoNewLine
}
}
Write-Host "] "
}else{
Write-Host "***** Lync not installed *****" -ForegroundColor red
}
}
27 { # add loopback adapter
New-LoopbackAdapter
}
28 { # install Windows Update module
$ModulePath = $env:PSModulePath.Substring($env:PSModulePath.LastIndexOf(";")+1)+"JH-WindowsUpdate"
if (!(Test-Path $ModulePath)){New-Item -path $ModulePath -type directory}
New-FileDownload "http://jdhitsolutions.com/blog/wp-content/uploads/2010/08/JH-WindowsUpdate-v1.5.zip"
New-UnzippedFile -ZipFile "$TargetFolder\JH-WindowsUpdate-v1.5.zip" -UnzipFile "JH-WindowsUpdate\Backup-WindowsUpdateLog.ps1" -UnzipFileLocation $ModulePath
New-UnzippedFile -ZipFile "$TargetFolder\JH-WindowsUpdate-v1.5.zip" -UnzipFile "JH-WindowsUpdate\Clear-WindowsUpdateLog.ps1" -UnzipFileLocation $ModulePath
New-UnzippedFile -ZipFile "$TargetFolder\JH-WindowsUpdate-v1.5.zip" -UnzipFile "JH-WindowsUpdate\Get-WindowsUpdate.ps1" -UnzipFileLocation $ModulePath
New-UnzippedFile -ZipFile "$TargetFolder\JH-WindowsUpdate-v1.5.zip" -UnzipFile "JH-WindowsUpdate\Install-WindowsUpdate.ps1" -UnzipFileLocation $ModulePath
New-UnzippedFile -ZipFile "$TargetFolder\JH-WindowsUpdate-v1.5.zip" -UnzipFile "JH-WindowsUpdate\JH-WindowsUpdate.psd1" -UnzipFileLocation $ModulePath
New-UnzippedFile -ZipFile "$TargetFolder\JH-WindowsUpdate-v1.5.zip" -UnzipFile "JH-WindowsUpdate\JH-WindowsUpdate.psm1" -UnzipFileLocation $ModulePath
Remove-Item "$TargetFolder\JH-WindowsUpdate-v1.5.zip"
Import-Module JH-WindowsUpdate
}
29 { # Download Lync Server 2010 (trial)
Get-WebPage -url http://technet.microsoft.com/en-us/evalcenter/ff808407.aspx
}
30 { # Restrict features to those available to Standard user CALs
Set-CsConferencingPolicy –Identity "Global" –AllowIPAudio $false –AllowIPVideo $false –AllowUserToScheduleMeetingsWithAppSharing $false –AllowPolls $false –EnableAppDesktopSharing None –EnableDialinConferencing $false
Set-CsMeetingConfiguration -DesignateAsPresenter None
Write-Host "A GPO to disable client side features in the Lync Outlook plug must also be configured. See http://howdouc.blogspot.com/2011/09/understanding-and-enforcing-licensing_21.html for more information." -ForegroudColor yellow
}
31 {
# Get-RegistryValue "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0" NtlmMinClientSec
# Get-RegistryValue "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0" NtlmMinServerSec
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0" -Name "NtlmMinClientSec" -Value 0
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0" -Name "NtlmMinServerSec" -Value 0
$global:RebootRequired = $true
}
98 { # Exit and restart
if (($WasInstalled -eq $false) -and (Get-Module BitsTransfer)){
Write-Host "Removing BitsTransfer..." -NoNewLine
Remove-Module BitsTransfer
Write-Host "removed!" -ForegroundColor Green
}
Write-Host "Exiting and rebooting..."
New-EventLogEntry -EventType Information -EventId 70 -EventLogText "Server shutdown initiated. See transcript file $pwd.path\$FilenameTranscript for more information." -EventSource $MyInvocation.MyCommand.Name -EventLog Application
Stop-Transcript
Restart-Computer
}
99 { # Exit
if (($WasInstalled -eq $false) -and (Get-Module BitsTransfer)){
Write-Host "Removing BitsTransfer..." -NoNewLine
Remove-Module BitsTransfer
Write-Host "removed!" -ForegroundColor Green
}
popd
Remove-ScriptVariables($MyInvocation.MyCommand.Name)
Write-Host "Exiting..."
}
default {
Write-Host "You haven't selected any of the available options."
}
}
} while ($MenuOption -ne 99)
Stop-Transcript | Out-Null
[…] https://msunified.net/lyncdownloads/script-set-lync2010windows2008r2features-ps1/ […]
New version, v5.0, released. See http://www.ucblogs.net/blogs/exchange/archive/2011/07/25/Set_2D00_Lync2010Features.ps1-v5.0-_2D00_-automated-prereq-PowerShell-script-for-Lync-Server-2010-released.aspx
[…] SCRIPT: Set-Lync2010Windows2008R2Features.ps1 « msunified.net Posted on November 24, 2010 by johnacook https://msunified.net/lyncdownloads/script-set-lync2010windows2008r2features-ps1/ […]
Excellent script! However, it should include installation of Web-Http-Redirect for 1 Frontend to avoid issues with easy URL for admin and Lync Control Panel.
Thanks Rune for the heads up.
I will modify accordingly :)
Very nice. Small typo in the option selection list…
8) Donwnload and install Lync Server 2010 ResKit
other than that, s w e e t !
Thanks for notifying me and I am happy you like the script :) I have corrected the typo
Kanon! :)
[…] SCRIPT: Set-Lync2010Windows2008R2Features.ps1 « msunified.net Posted on January 27, 2011 by johnacook https://msunified.net/lyncdownloads/script-set-lync2010windows2008r2features-ps1/ […]
[…] Veja aqui o script do Stale Hansen: https://msunified.net/lyncdownloads/script-set-lync2010windows2008r2features-ps1/ […]
Wow – just heard about this from some Lync people at the MVP Summit. Glad to see the script that Anderson, Bhargav, and I created was able to help you Lync guys. Even now more than anything, as I’ve been roped into doing a Lync install for a customer, and can use this.
I like the idea to install the BPA, and may incorporate that in the new version of the Exchange prereq script coming out soon.
Cool, happy to hear you like it. Look forward to your updated Exchange prereq script :)
Great script, but we need to have message queueing with AD integration installed as well. The QoE Monitoring agent complains a lot without it.
I have noticed that, by now I have run the monitoring role on the Front End as well, I will look into adding msmq to the roles where AD integration is required. For OCS it was released a CU that removed this at a point, guess they are back in Lync :)
[…] Prima di poter installare Lync 2010 è necessario installare i prerequisiti di Windows 2008 R2, Ståle Hansen ha creato uno script che automatizza questo processo, lo trovate al seguente indirizzo: https://msunified.net/lyncdownloads/script-set-lync2010windows2008r2features-ps1/ […]
[…] Prima di poter installare Lync Server 2010 è necessario installare i prerequisiti di Windows 2008 R2, Ståle Hansen ha creato uno script che automatizza questo processo, lo trovate al seguente indirizzo: https://msunified.net/lyncdownloads/script-set-lync2010windows2008r2features-ps1/ […]
[…] I have adapted a PowerShell script for installing the prerequisites: SCRIPT: Set-Lync2010Windows2008R2Features.ps1 […]
GREAT script. Would be nice if it installed the Visual C++ redist as well.
I’ve been working on a newer version that also removes IPv6. Let me look into the VC++ option.
Hi, but on the Front-End server, i know that is necessary to install also Message Queueing Directory Services:
In server manager to install the feature “Message Queueing”, when you select Message Queueing it will automatically select one of the 2 features you need, for the other expand Message Queueing and choose “Directory Services Integration”
Right???
When installing MSMQ I install Server and Directory and that works (msmq-server,msmq-directory). For the Front End, I don’t think you need MSMQ if you don’t have monitoring or archiving server deployed. By default monitoring is selected on the Front End server when you install, thats why you get the event viewer entries on MSMQ.
It’s not required on the Front End servers unless you’re doing archiving.
BTW – I have the new version done. I need to test it a little more before posting. I’ve added quite a few options, and cleaned up the code.
Cool, looking forward to it :)
[…] that script and adapted it to installing the prerequisites for Lync Server 2010 and posted the results online. He did some neat things like installing the Best Practice Analyzer and the Resource Kit.I got […]
Okay – finally built some servers with the new version, and things went well. I posted a new article that discusses the changes at http://www.ucblogs.net/blogs/exchange/archive/2011/04/27/Automated-prerequisite-installation-via-PowerShell-for-Lync-Server-2010-on-Windows-Server-2008-R2.aspx.
I welcome any suggestions or comments.
I’ll add that one thing I really tried to do, but failed, was to automate the installation of Silverlight. I just could not get a direct link to the installer. If someone can figure that out, I’m happy to add it, but the link MUST be to a microsoft.com location. Going to http://go.microsoft.com/fwlink/?LinkID=149156 will give you the file from silverlight.dlservice.microsoft.com, but I need the exact link.
If anyone has some requested features, please let me know. I’ve got the following added for the next version:
added group membership check
added 04-20-2011 Lync Server update download
added chm file download and install & shortcut
added standalone AV server prereq option
added PowerShell transcript
added backup Lync configuration
and the following are on the wishlist:
Better menu during various steps
Better error trapping
Auto install of SilverLight
The Lync PG released a new version of the .chm file. The link for that file is the same as what I already have in the script. So even though it says it’s the 4/14/2011 chm file, you’re actually getting the 5/19/2011 version. I’ll update the menu on the next release.
[…] SCRIPT: Set-Lync2010Windows2008R2Features.ps1 « msunified.net Posted on August 1, 2011 by johnacook https://msunified.net/lyncdownloads/script-set-lync2010windows2008r2features-ps1/ […]
[…] Hansen took that script and adapted it to installing the prerequisites for Lync Server 2010 and posted the results online. He did some neat things like installing the Best Practice Analyzer and the Resource […]
[…] A PowerShell script for installing the prerequisites: SCRIPT: Set-Lync2010Windows2008R2Features.ps1 […]
[…] Hansen took that script and adapted it to installing the prerequisites for Lync Server 2010 and posted the results online. He did some neat things like installing the Best Practice Analyzer and the Resource […]
I get error: Start-BitsTransfer : HTTP status 407: Proxy authentication is required.
It it becuase you Lync Server probably is behind proxy server. The script does not support proxy servers regrettably
[…] Further investigating lead me to the fact that the Lync Edge Server was running with IPv6 fully enabled, so I decided to disable IPv6 on the server. Did that with the following script: Set-Lync2010Features […]