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 […]