Exchange 2013 DAG CU19 Upgrade

Here is the step that I will do to upgrade the Exchange 2013 to CU19, with the new .NET Framework 4.7.1.

Exchange 2013 has a different servicing strategy than Exchange 2007/2010 and utilises Cumulative Updates (CUs) rather than the Rollup Updates (RU/UR) which were used previously. CUs are a complete installation of Exchange 2013 and can be used to install a fresh server or to update a previously installed one. Exchange 2013 SP1 was in effect CU4, and CU18 is the fourteenth post SP1 release. Updating from any CU to any CU is supported, however to the best of my knowledge Microsoft only tests updates from N-2 builds. For example, when Microsoft released CU19, they would test the update process from CU17 and CU18 as they were the previously supported builds. It means that when we are updating from CU10 to CU19, it’s possible that we will encounter some problem that Microsoft has not identified in their testing. Although that risk exists, in my opinion, it has diminished over time as the quality of the Exchange 2016/2013 code has improved. Microsoft best practices are to keep the Exchange upgrade with the two last version available, so now we should have been at CU17 or CU18, but since we are not, the best approach, in my opinion, is go directly to CU19.

After the Exchange 2013 CU16 the .NET 4.6.2 is a requirement, and to make a smooth transition, the CU15 was working with .NET 4.6.1 and .NET 4.6.2, so we could upgrade the .NET without getting big downtimes.

Since the CU15 is no longer available the bridge has washed out, so we need to upgrade the .NET first and then the Exchange.

How to Upgrade from Exchange 2013 CU10 to CU19 on DAG Members

  1. Backup/Snapshot of all Server
  2. I will check if the databases are healthy (Check the links below for more information about this step)
  3. Put one node in Maintenance mode (Check the links below for more information about this step)
  4. Reboot the Server
  5. Install .Net 4.7.1
  6. Reboot the Server
  7. Disable the Antivirus
  8. Install the CU19 (This step will take between 1 hour to 2 hours) – Note: We need to make sure there is disk space available, it makes sense to extract the CU to another drive than C: drive.
  9. Reboot the server after the successful CU installation.
  10. Wait a few minutes for the servers to get sorted, and check if the databases are healthy (Check the links below for more information about this step)
  11. Remove the server from Maintenance mode (Check the links below for more information about this step)
  12. Re-check if the databases are healthy (Check the links below for more information about this step)
  13. Repeat the same steps to update the Other DAG member

More information for the Steps 2,3,10,11 and 12 on this links below:

Technet: https://technet.microsoft.com/en-us/library/ee861125.aspx

Simple instruction: https://enterpriseit.co/microsoft-exchange/install-exchange-update-rollups-on-dag/

Installation failure recovery

Experience will show whether this is a major concern or not. Update rollups are usually able to roll back seamlessly if they encounter an error. Whether the cumulative update failed installation recovery process becomes a burden or not, only time will tell.

Some Items for Consideration

  • Make a full backup of the Exchange servers
  • The customs customisations can be lost, especially on the OWA
  • Third-party software integrations

Exchange .NET Framework Support Table

I believe that is all, the important things that we need to think about, off course, Microsoft have made it much simple the Exchange upgrades, and normally this runs smoothly, but be sure that you have a full backup of the servers.

Best of luck and hope this can help you.

Script to set Outlook signature using AD info, Security Groups and Templates

Script to set Outlook e-mail signature using Active Directory information, Security groups and unlimited templates.

Script Localization: https://gallery.technet.microsoft.com/office/Script-to-set-Outlook-da7b56ee 

PowerShell
<#
    .SYNOPSIS
    Script to set Outlook 2010/2013/2016 e-mail signature using Active Directory information, Security groups and unlimited templates
    .DESCRIPTION
    This script will set the Outlook 2010/2013/2016 e-mail signature on the local client using Active Directory information. 
    The template is created with a Word document, where images can be inserted and AD values can be provided.

    Author: João Dias
	Company: Mutega IT AB
	Email: jd@mutega.se
	Site: www.mutega.se
    Version 1.0
	
	Script it is a mix of Jan Egil Ring and Daniel Classon Script
	https://gallery.technet.microsoft.com/office/6f7eee4b-1f42-499e-ae59-1aceb26100de
	https://gallery.technet.microsoft.com/office/Set-Outlook-20102013-8341e049

    .DISCLAIMER
    All scripts and other powershell references are offered AS IS with no warranty.
    These script and functions are tested in my environment and it is recommended that you test these scripts in a test environment before using in your production environment.
    #>


#Custom variables
$SignatureName = 'OSignature' #insert the company name (no spaces) - could be signature name if more than one sig needed
$SigSource = $env:appdata+"MUTEGAOutlookSignatureTemplatesOSignature.docx" #Path to the *.docx file, i.e "c:temptemplate.docx"
$Source = $env:appdata+"MutegaOutlookSignatureIMG"
$SignatureVersion = "1.0" #Change this if you have updated the signature. If you do not change it, the script will quit after checking for the version already on the machine
$ForceSignature = '1' #Set to 1 if you don't want the users to be able to change signature in Outlook
 
#Environment variables
$AppData=(Get-Item env:appdata).value
$SigPath = 'MicrosoftSignatures'
$LocalSignaturePath = $AppData+$SigPath
$RemoteSignaturePathFull = $SigSource

<# #Copy version file
If (-not(Test-Path -Path $LocalSignaturePath$SignatureVersion))
{
New-Item -Path $LocalSignaturePath$SignatureVersion -ItemType Directory
}
Elseif (Test-Path -Path $LocalSignaturePath$SignatureVersion)
{
Write-Output "Latest signature already exists"
break
}  #>

#Check signature path (needs to be created if a signature has never been created for the profile
if (-not(Test-Path -path $LocalSignaturePath)) {
	New-Item $LocalSignaturePath -Type Directory
}

#Get Active Directory information for current user
$UserName = $env:username
$Filter = "(&(objectCategory=User)(samAccountName=$UserName))"
$Searcher = New-Object System.DirectoryServices.DirectorySearcher
$Searcher.Filter = $Filter
$ADUserPath = $Searcher.FindOne()
$ADUser = $ADUserPath.GetDirectoryEntry()
$ADDisplayName = $ADUser.DisplayName
$ADEmailAddress = $ADUser.mail
$ADTitle = $ADUser.title
$ADDescription = $ADUser.description
$ADTelePhoneNumber = $ADUser.TelephoneNumber
$ADMobile = $ADUser.mobile
$ADStreetAddress = $ADUser.streetaddress
$ADwWWHomePage = $ADUser.wWWHomePage
$ADCity = $ADUser.l
<# $ADCustomAttribute1 = $ADUser.extensionAttribute1 #>
$ADModify = $ADUser.whenChanged

#Copy signature templates from source to local Signature-folder
Write-Output "Copying Signatures"
Copy-Item "$Sigsource" $LocalSignaturePath -Recurse -Force
$ReplaceAll = 2
$FindContinue = 1
$MatchCase = $False
$MatchWholeWord = $True
$MatchWildcards = $False
$MatchSoundsLike = $False
$MatchAllWordForms = $False
$Forward = $True
$Wrap = $FindContinue
$Format = $False
	
#Insert variables from Active Directory to rtf signature-file
$MSWord = New-Object -ComObject word.application
$fullPath = $LocalSignaturePath+''+$SignatureName+'.docx'
$MSWord.Documents.Open($fullPath)

<# 	
#User Name $ Designation 
$FindText = "DisplayName"
$Designation = $ADCustomAttribute1.ToString()

#Designations in Exchange custom attribute 1
If ($Designation -ne '') { 
	$Name = $ADDisplayName.ToString()
	$ReplaceText = $Name+', '+$Designation
}
Else {
	$ReplaceText = $ADDisplayName.ToString() 
}
$MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord,	$MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap,	$Format, $ReplaceText, $ReplaceAll	) 
#>

#DisplayName		
$FindText = "DisplayName"
$ReplaceText = $ADDisplayName.ToString() 
$MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord,	$MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap,	$Format, $ReplaceText, $ReplaceAll	)
	
#Title		
$FindText = "Title"
$ReplaceText = $ADTitle.ToString()
$MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord,	$MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap,	$Format, $ReplaceText, $ReplaceAll	)
	
#Description