With the advent of Microsoft Endpoint Manager Configuration Manager 1910, I started researching the upgrade requirements. I happened to run into a great blog post by fellow MVP Martin Bengtsson on what should be done before the upgrade takes place. That got me to thinking that most of the tasks he listed can be automated with PowerShell.
The script below will automate the following tasks from his list of prerequisites:
The script below will automate the following tasks from his list of prerequisites:
- Backs up the cd.latest directory to the specified UNC path
- Disables the following maintenance tasks
- Backup site server
- Delete aged client operations
- Delete aged discovery data
- Delete aged log data
- Checks if the server is fully patched
- Backs up the Configuration Manager SQL database
For the script to complete all of these tasks, the following PowerShell modules are required:
- SQLServer
- ConfigurationManager.psd1
- PSWindowsUpdate
The SQLServer and PSWindowsUpdate can both be installed from the PowerShell Gallery. The ConfigurationManager.psd1 resides on the Configuration Manager server. The script needs to be run on that server, along with the other two modules being installed. The script will automatically locate the ConfigMgr module. You will also need to have a UNC path that will house the cd.latest directory backup and the SQL database backup.
When executing this script, I recommend doing so using PowerShell ISE. The reason for this is because as you can see in the screenshot below, ISE will give you a status on the SQL server backup so you do not think the script might be locked up.
When the server has passed all prereqs, the output will look like this:
NOTE: The script is intended to be executed on the Configuration Manager server.
Here is the script. It can also be downloaded from my GitHub site.
<#
.SYNOPSIS
Configuration Manager Upgrade Prerequisite
.DESCRIPTION
This script will prepare configuration manager for the upgrade to the newest version. This is based off of Martin Bengtsson's Updating MEMCM (Microsoft Endpoint Manager Configuration Manager) to version 1910 on Christmas Eve. https://www.imab.dk/early-christmas-present-updating-memcm-microsoft-endpoint-manager-configuration-manager-to-version-1910-on-christmas-eve/
.PARAMETER MEMCMModule
Name of the ConfigMgr PowerShell Module
.PARAMETER MEMCMServer
FQDN Name of the Configuration Manager server
.PARAMETER MEMCMSiteDescription
Arbitrary description of the configuration manager server
.PARAMETER SiteCode
Three letter ConfigMgr site code
.PARAMETER BackupLocation
Location for SQL and SCCM backups
.PARAMETER SQLServer
FQDN of the SQL server
.PARAMETER SQLDatabase
Name of the SQL database
.PARAMETER SQLModuleName
Name of the SQL PowerShell Module
.NOTES
===========================================================================
Created with: SAPIEN Technologies, Inc., PowerShell Studio 2017 v5.4.142
Created on: 12/26/2019 12:22 PM
Created by: Mick Pletcher
Filename: ConfigMgrUpgrade.ps1
===========================================================================
#>
[CmdletBinding()]
param
(
[ValidateNotNullOrEmpty()]
[string]$MEMCMModule = 'ConfigurationManager.psd1',
[ValidateNotNullOrEmpty()]
[string]$MEMCMServer,
[ValidateNotNullOrEmpty()]
[string]$MEMCMSiteDescription = 'MEMCM Site Server',
[ValidateNotNullOrEmpty()]
[string]$SiteCode,
[ValidateNotNullOrEmpty()]
[string]$BackupLocation,
[ValidateNotNullOrEmpty()]
[string]$SQLServer,
[ValidateNotNullOrEmpty()]
[string]$SQLDatabase,
[ValidateNotNullOrEmpty()]
[string]$SQLModuleName = 'SQLServer'
)
#Import SQL Server PowerShell Module
If ((Get-Module -Name ((Import-Module -Name $SQLModuleName -ErrorAction SilentlyContinue -Force -PassThru).Name)) -eq $null) {
#Install module if it does not exist
Install-Module -Name $SQLModuleName -Confirm:$false -Force
#Verify module got installed. Exit the script if it failed
If ((Get-Module -Name ((Import-Module -Name $SQLModuleName -ErrorAction SilentlyContinue -Force -PassThru).Name)) -eq $null) {
Write-Host 'Failed'
Exit 2
} else {
Import-Module -Name $SQLModuleName -ErrorAction SilentlyContinue -Force
}
}
If ((Get-Module).Name -contains $SQLModuleName) {
Write-Host ('Successfully imported' + [char]32 + $SQLModuleName + [char]32 + 'PowerShell module')
} else {
Write-Host ('Failed to load' + [char]32 + $SQLModuleName + [char]32 + 'PowerShell module')
}
#Import ConfigMgr PowerShell Module
$Module = (Get-ChildItem ((Get-WmiObject -Class 'sms_site' -Namespace 'Root\sms\site_BNA').InstallDir) -Filter $MEMCMModule -Recurse -ErrorAction SilentlyContinue)
Import-Module -Name $Module[0].FullName -Force
If ((Get-Module).Name -contains $Module[0].BaseName) {
Write-Host ('Successfully imported' + [char]32 + $Module[0].BaseName + [char]32 + 'PowerShell module')
} else {
Write-Host ('Failed to load' + [char]32 + $MEMCMModule + [char]32 + 'PowerShell module')
}
#Import PSWindowsUpdate PowerShell Module
Import-Module -Name PSWindowsUpdate -Force
If ((Get-Module).Name -contains 'PSWindowsUpdate') {
Write-host 'Successfully imported PSWindowsUpdate PowerShell module'
}
#Map ConfigMgr Drive
If ((Test-Path ($SiteCode + ':')) -eq $false) {
New-PSDrive -Name $SiteCode -PSProvider 'AdminUI.PS.Provider\CMSite' -Root $MEMCMServer -Description $MEMCMSiteDescription | Out-Null
}
#Change directory to ConfigMgr drive
Set-Location -Path ($SiteCode + ':')
#Backup cd.latest directory
$DIR = Get-ChildItem -Path (Get-WmiObject -Class 'sms_site' -Namespace 'Root\sms\site_BNA').InstallDir -Filter 'cd.latest' -Directory -Recurse -ErrorAction SilentlyContinue
robocopy $DIR.FullName ($BackupLocation + '\cd.latest') /e /eta ('/log:' + $BackupLocation + '\Robocopy.log')
If ($LastExitCode -le 7) {
Write-Host 'cd.latest backup succeeded' -ForegroundColor Yellow
} else {
Write-Host 'cd.latest backup failed' -ForegroundColor Red
}
#Disable Maintenance tasks for upgrade
$Enabled = $false
Get-CMSiteMaintenanceTask | Where-Object {$_.ItemName -like 'backup* site server'} | Set-CMSiteMaintenanceTask -Enabled $Enabled
If (((Get-CMSiteMaintenanceTask | Where-Object {$_.ItemName -like 'backup* site server'}).Enabled) -eq $false) {
$BackupSiteServer = $true
} else {
$BackupSiteServer = $false
}
If ($BackupSiteServer -eq $true) {
Write-Host 'Backup site server is disabled' -ForegroundColor Yellow
} else {
Write-Host 'Backup site server is still enabled' -ForegroundColor Red
}
Get-CMSiteMaintenanceTask | Where-Object {$_.ItemName -eq 'delete aged client operations'} | Set-CMSiteMaintenanceTask -Enabled $Enabled
If (((Get-CMSiteMaintenanceTask | Where-Object {$_.ItemName -eq 'delete aged client operations'}).Enabled) -eq $false) {
$AgedClientOperations = $true
} else {
$AgedClientOperations = $false
}
If ($AgedClientOperations -eq $true) {
Write-Host 'Delete aged client operations is disabled' -ForegroundColor Yellow
} else {
Write-Host 'Delete aged client operations is still enabled' -ForegroundColor Red
}
Get-CMSiteMaintenanceTask | Where-Object {$_.ItemName -eq 'delete aged discovery data'} | Set-CMSiteMaintenanceTask -Enabled $Enabled
If (((Get-CMSiteMaintenanceTask | Where-Object {$_.ItemName -eq 'delete aged discovery data'}).Enabled) -eq $false) {
$AgedDiscoveryData = $true
} else {
$AgedDiscoveryData = $false
}
If ($AgedDiscoveryData -eq $true) {
Write-Host 'Delete aged discovery data is disabled' -ForegroundColor Yellow
} else {
Write-Host 'Delete aged discovery data is still enabled' -ForegroundColor Red
}
Get-CMSiteMaintenanceTask | Where-Object {$_.ItemName -eq 'delete aged log data'} | Set-CMSiteMaintenanceTask -Enabled $Enabled
If (((Get-CMSiteMaintenanceTask | Where-Object {$_.ItemName -eq 'delete aged log data'}).Enabled) -eq $false) {
$AgedLogData = $true
} else {
$AgedLogData = $false
}
If ($AgedLogData -eq $true) {
Write-Host 'Delete aged log data is disabled' -ForegroundColor Yellow
} else {
Write-Host 'Delete aged log data is still enabled' -ForegroundColor Red
}
#Verify all windows updates are applied
If ((Get-WindowsUpdate -WindowsUpdate) -eq $null) {
$AppliedUpdates = $true
} else {
$AppliedUpdates = $false
}
If ($AppliedUpdates -eq $true) {
Write-Host ((Get-WmiObject -Class Win32_OperatingSystem).Caption + [char]32 + 'is fully patched') -ForegroundColor Yellow
} else {
Write-Host ((Get-WmiObject -Class Win32_OperatingSystem).Caption + [char]32 + 'is not fully patched') -ForegroundColor Red
}
#Backup the Configuration Manager SQL Database
Backup-SqlDatabase -ServerInstance $SQLServer -Database $SQLDatabase -BackupFile ($BackupLocation + '\CM_SQL_Backup.bak') -Checksum
$Verbose = $($Verbose = Invoke-Sqlcmd -ServerInstance $SQLServer -Database $SQLDatabase -Query ('RESTORE VERIFYONLY FROM DISK = N' + [char]39 + $BackupLocation + '\CM_SQL_Backup.bak' + [char]39) -QueryTimeout 0 -Verbose) 4>&1
If ($Verbose -like '*The backup set on file 1 is valid*') {
$SQLBackup = $true
} else {
$SQLBackup = $false
}
#Output the results
If ($SQLBackup -eq $true) {
Write-Host 'SQL backup was successful' -ForegroundColor Yellow
} else {
Write-Host 'SQL backup failed' -ForegroundColor Red
}
0 comments:
Post a Comment