SCCM Software Update Point (SUP) automated install via PowerShell

Automation is always good in large or small organizations to minimize error and remove the tediousness of repetitive tasks. This script will install the Software Update Point (SUP) role on one or multiple site system servers in their assigned site.

This script will run the following task

  • Check if the site server and admin domain groups were added to the local admin group. If not, the groups will be added.
  • Check if NO_SMS_ON_DRIVE.SMS exist on the C: drive. If not, create it.
  • Check if the content drive exist. If the drive does not exist, the script stops.
  • Install the prerequisites.
  • Check if the Site System for the SUP exist. If not, it will be added.
  • Check if the SUP role exist. If not, add it.
  • Reports the install status at the end of the script. If the SUP is still installing, wait 5 minutes and run the script again and it will report the install status.

How to run the script

The script consist of two files. Add both files to the same folder. Run the script from the CAS or standalone primary.

  • Install-SoftwareUpdatePoint.ps1
  • SUPInputFile.psd1

To run the script, do the following. First, dot source Install-SoftwareUpdatePoint.ps1 in order to run the function.

. C:\Script\Install-SoftwareUpdatePoint.ps1

Then run the Software Update Point install function.

Install-SoftwareUpdatePoint -InputFile "C:\Script\SUPInputFile.psd1"

Save the code below as Install-SoftwareUpdatePoint.ps1


Function Install-SoftwareUpdatePoint{
    <#
    .Synopsis
    This script will install the upstream Software Update Point and or multiple downstream Software Update Point.  The upstream SUP should be the first entry in the list of SUPs in the input file, or the only entry to install the upstream first, then add the entries for the downstream SUPs afterwards.  Run this script from the CAS or Standalone primary.
    
    .Description
     This script will do the following during the provisioning process
       1.  Check if domain groups were added to local admin group.  If not, add them.
       2.  Check if the content drive exist. If the drive does not exist, stop the script.
       3.  Check if the Site System for the SUP exist, if not add it.
       4.  Check the SUP role exist. if not add it
       5.  Configure the SUP (Update classification, Products, Language, etc,...) if installing the upstream.
    
     The input values are stored in SUPInputFile.psd1
    
    .PARAMETER InputFile
     Holds the path to the inputFile file - This file stores all the required values. Edit this file before running the script.
    
    .Example
     Install-SoftwareUpdatePoint -InputFile "C:\Script\SUPInputFile.psd1"
    
    .Notes
     Created on:  12/08/2020
     Created by:  Lynford Heron
     Filename:    Install-SoftwareUpdatePoint.ps1
     Version:     1.0
    #&gt;
    
    Param( 
        [string]$InputFile
    )
    
    If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(`
            [Security.Principal.WindowsBuiltInRole] "Administrator"))
    
        {
            Write-Warning "You do not have Administrator rights to run this script!`nPlease re-run this script as an Administrator!"
            Break
        }
    
    Write-host "Enter the credetial with admin rights on the remote server." -ForegroundColor Yellow
    $credential = Get-credential 
    $dataFile = Import-PowerShellDataFile $InputFile
    
    # Site configuration
    $casSiteCode = $dataFile.ParentSiteCode # Site code 
    $ProviderMachineName = $dataFile.ParentSrvName # SMS Provider machine name
    
    # Import the ConfigurationManager.psd1 module 
    if($null -eq (Get-Module ConfigurationManager)) {
        If ($ENV:SMS_ADMIN_UI_PATH) {
            Import-Module "$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1"
        }
        Else {
            #If running from jump server, change path below to the install location fo the admin console
            $modPath = $dataFile.cminstalldir + "\AdminConsole\bin\ConfigurationManager.psd1"
            Import-Module $modPath
        }
    }
    
    # Connect to the site's drive if it is not already present
    if($null -eq (Get-PSDrive -Name $casSiteCode -PSProvider CMSite -ErrorAction SilentlyContinue)) {
        New-PSDrive -Name $casSiteCode -PSProvider CMSite -Root $ProviderMachineName | Out-Null #@initParams
    }
    
    #copy files to get around double hop access denied.
    Write-verbose -message "Copying the SQL native client." -Verbose
    If ($($dataFile.CopyFiles) -eq 'Yes')
    {
        foreach ($srv in $dataFile.SUPInfo.servername)
        {
            Copy-Item –Path $datafile.SQLClient –Destination $datafile.SQLClientDrive.Substring(0,3) -Force –ToSession (New-PSSession –ComputerName $srv) | Out-Null
        }
        Get-PSSession | Remove-PSSession
    }
    
    # Set the current location to be the site code.
    Set-Location "$($casSiteCode):\"
    
        Foreach ($SUP in $dataFile.SUPInfo)
        {
            $session = New-PSSession -ComputerName $SUP.ServerName -Credential $credential
            $prepResults = Invoke-Command -Session $session -ScriptBlock {
    
                $Cmadmins      = $args[0]
                $CmSiteservers = $args[1]
                $InstallDrive  = $args[2]
                $Domain        = $args[3]
    
                $results = @{}
    
                #Create no_sms_on_drive.sms on the C:\drive
                Write-verbose -message "Creating no_sms_on_drive.sms on the c:\ drive" -Verbose
                New-Item c:\no_sms_on_drive.sms -ItemType file -Force
                If (!(Test-Path -Path c:\no_sms_on_drive.sms))
                {
                    $results['Installno'] = "No"
                    Write-Warning "There was a problem creating the file no_sms_on_drive.sms. Fix the problem and run the script again"
                    Break
                }
    
                $date = get-date
                $NewFolder = "c:\ProvisionSrv"
                If (!(Test-Path $NewFolder)) {New-Item c:\ProvisionSrv -ItemType directory}
                $Random = Get-Date -UFormat %Y%m%d_%H%M%S
                $logfile = $NewFolder + "\" + $env:COMPUTERNAME + "_" + $Random + ".log"
                new-item -ItemType file $logfile -Force
    
                $date = get-date; add-content $logfile ""
                $date = get-date; add-content $logfile " ==================================================================="
                $date = get-date; add-content $logfile "  $date  -  Check if the install partition exist "
                $date = get-date; add-content $logfile " ==================================================================="
                $date = get-date; add-content $logfile ""
    
                #Check if the install drive exit(E:)
                If (Test-Path $installDrive)
                {
                    Write-Verbose -Message "The content partition $($installDrive) is present on $env:COMPUTERNAME." -Verbose; $date = get-date; add-content $logfile "The content partition $($installDrive) is present on $($env:COMPUTERNAME)."
                    $results['Installyes'] = "Yes"
                }
                Else
                {
                    $results['Installno'] = "No"
                    Write-Warning "The content partition $($installDrive) is missing on $($env:COMPUTERNAME). This server will not be provisioned until the drive is present:"
                    $date = get-date; add-content $logfile "The content partition $($installDrive) is missing on $($env:COMPUTERNAME). This server will not be provisioned until the drive is present:"
                    Break
                }
    
    
                $date = get-date; add-content $logfile ""
                $date = get-date; add-content $logfile " ============================================================================================================"
                $date = get-date; add-content $logfile "  $date  -  Check if domain groups exist in local admin group"
                $date = get-date; add-content $logfile " ============================================================================================================"
                $date = get-date; add-content $logfile ""
    
                #Search if Domain groups exist in local Admin group
                Write-Verbose -message "Checking if the groups $Cmadmins and $CmSiteservers are local admins on $($env:COMPUTERNAME)" -Verbose; $date = get-date; add-content $logfile " $date  -  Checking if $Cmadmins and $CmSiteservers are local admins $($env:COMPUTERNAME)"
                $group = [ADSI]"WinNT://$($env:COMPUTERNAME)/Administrators,Group" 
                $GroupMembers = @($group.Invoke("Members")) | foreach-object {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}
    
                If (!($GroupMembers -contains $Cmadmins)) 
                {
                    Write-Host "The domain group $Cmadmins does not exist on $env:COMPUTERNAME. Adding group to local administrators:" -ForegroundColor cyan; $date = get-date; add-content $logfile " $date  -  The domain group $Cmadmins does not exist on $env:COMPUTERNAME. Adding group to local administrators"
                    $adgroup = [ADSI]"WinNT://$Domain/$Cmadmins"
                    $localgroup = [ADSI]"WinNT://$($env:COMPUTERNAME)/Administrators,Group"
                    $localGroup.PSBase.Invoke("Add", $adgroup.PSBase.Path) 
    
                    $GroupMembers2 = @($group.Invoke("Members")) | ForEach-Object {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
                 }
                    If ($GroupMembers2 -contains $Cmadmins) 
                    {
                        Write-Host "The missing group $Cmadmins was added" -ForegroundColor Yellow; $date = get-date; add-content $logfile " $date  -  The missing group $Cmadmins added"
                        $results['Installyes'] = "Yes"
                    } 
                    Else
                    {
                        $results['Installno'] = "No"
                        Write-Warning "There was a problem adding the domain $Cmadmins to the local administrators group on $env:COMPUTERNAME. Check the ProvisionSUP log and work to resolve"
                        $date = get-date; add-content $logfile " $date  -  ERROR: There was a problem adding the domain group $Cmadmins to the local administrators group on $env:COMPUTERNAME. Check the ProvisionSUP log and work to resolve"
                        Break
                    }
    
                }
    
                If (!($GroupMembers -contains $CmSiteservers)) 
                {
                    Write-Host "The domain group $CmSiteservers does not exist on $env:COMPUTERNAME. Adding group to local administrators:" -ForegroundColor Yellow #; #$date = get-date; #add-content $logfile " $date  -  The domain group $CmSiteservers does not exist on $env:COMPUTERNAME. Adding group to local administrators"
                    $adgroup = [ADSI]"WinNT://$Domain/$CmSiteservers"
                    $localgroup = [ADSI]"WinNT://$($env:COMPUTERNAME)/Administrators,Group"
                    $localGroup.PSBase.Invoke("Add", $adgroup.PSBase.Path) 
    
                    $GroupMembers2 = @($group.Invoke("Members")) | foreach-object {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
                 }
            
                    If ($GroupMembers2 -contains $CmSiteservers) 
                    {
                        Write-Host "The missing group $CmSiteservers was added" -ForegroundColor Yellow; $date = get-date; add-content $logfile " $date  -  The missing group $CmSiteservers was added"
                        $results['Installyes'] = "Yes"
                    } 
                    Else 
                    {
                        Write-Warning "There was a problem adding the domain group $CmSiteservers to the local administrators group on $env:COMPUTERNAME. Check the script and event log and work to resolve"
                        $date = get-date; add-content $logfile " $date  -  ERROR: There was a problem adding the domain group $CmSiteservers to the local administrators group on $env:COMPUTERNAME. Check the script and event log and work to resolve"
                        $results['Installno'] = "No"
                        Break
                    }
                } 
                If ($GroupMembers -contains $Cmadmins -and $GroupMembers -contains $CmSiteservers)
                {
                    $results['Installyes'] = "Yes"
                    Write-Host "Domain Groups $Cmadmins and $CmSiteservers already exist on $env:COMPUTERNAME" -ForegroundColor Yellow; $date = get-date; add-content $logfile " $date  -  Domain Groups CMAdmins and $CmSiteservers already exist on $env:COMPUTERNAME"
                }
    
    
                #Install Windows features - The commands below with also install IIS and management console as well
                If (Get-WindowsFeature NET-Framework-Core)
                {
                    Write-verbose -message ".Net Framework Core is already installed" -verbose
                }
                else
                {
        
                    Write-Verbose -Message ".Net Framework core is not installed.  Installing, please wait..." -Verbose
                    Install-WindowsFeature NET-Framework-Core | Out-Null
                    If (Get-WindowsFeature NET-Framework-Core)
                    {
                        Write-verbose -message ".Net Framework Core was successfully installed" -verbose
                        $results['InstallYes'] = "Yes"
                    }
                    else
                    {
                        Write-Warning "There was a problem installing .Net Framework Core."
                        $results['Installno'] = "No"
                        Break
                    }
                }
                Write-Verbose -Message "Installing IIS required features.  Please wait..." -Verbose
                Install-WindowsFeature  Web-WebServer,Web-ISAPI-Ext,Web-Windows-Auth,Web-Metabase,Web-WMI,Web-Mgmt-Console | Out-Null
    
                #If Windows firewall is on, add exceptions. 
                If((Get-NetFirewallProfile -Name Domain).Enabled)
                {   Write-host "Windows Firewall is enabled.  Adding exceptions" -ForegroundColor Yellow
                    New-NetFirewallRule -DisplayName 'SMB SUPInbound' -Profile Domain -Direction Inbound -Action Allow -Protocol TCP -LocalPort 445 -Group "For SCCM SUP"
                    New-NetFirewallRule -DisplayName 'SMB SUP Outbound' -Profile Domain -Direction Outbound -Action Allow -Protocol TCP -LocalPort 445 -Group "For SCCM SUP"
                    New-NetFirewallRule -DisplayName 'HTTP(S) SUP Outbound' -Profile Domain -Direction Outbound -Action Allow -Protocol TCP -LocalPort @(8530,8531) -Group "For SCCM SUP"
                    New-NetFirewallRule -DisplayName 'HTTP(S) SUP Inbound' -Profile Domain -Direction Inbound -Action Allow -Protocol TCP -LocalPort @(8530,8531) -Group "For SCCM SUP"
                }
                Else
                {  Write-host "Windows Firewall domain profile is disabled" -ForegroundColor Cyan}
    
            #Installing SQL Native Client
            #unblock the install file to prevent the security warning
            Write-Host "Checking if SQL Native Client is already installed..." -ForegroundColor Cyan
            If(Test-Path "HKLM:SOFTWARE\ODBC\ODBCINST.INI\SQL Server Native Client 11.0")
            { 
                $sqlNativeClient = (Get-ItemProperty "HKLM:SOFTWARE\ODBC\ODBCINST.INI\SQL Server Native Client 11.0").Driver
                Write-host "SQL Native Client driver $sqlNativeClient is already installed." -ForegroundColor Yellow
                $results['InstallYes'] = "Yes"
            }
            Else
            {
                Write-host "SQL Native Client is not installed.  Checking for installation files" -ForegroundColor White
                If(Test-Path $($Datafile.SQLClientDrive)) 
                {
                    Write-Host "SQL Native Client installation file exist.  Installing, please wait..." -ForegroundColor Yellow
                    #$sqlncliPath = $Datafile.SQLnativeClient
                    Start-Process -FilePath msiexec.exe -ArgumentList "/i `"$($Datafile.SQLClientDrive)`" /qn IACCEPTSQLNCLILICENSETERMS=YES" -Wait
                    If(Test-Path "HKLM:SOFTWARE\ODBC\ODBCINST.INI\SQL Server Native Client 11.0")
                    {
                        $sqlNativeClient = (Get-ItemProperty "HKLM:SOFTWARE\ODBC\ODBCINST.INI\SQL Server Native Client 11.0").Driver
                        Write-Host "SQL Native Client driver $sqlNativeClient was successfully installed." -ForegroundColor Yellow
                        $results['InstallYes'] = "Yes"
                    }
                    Else
                    {
                        $results['Installno'] = "No"
                        Write-Warning "There was a problem installing SQL Native Client. Check the eventlog for errors."
                        Break
                    }
                }
                Else
                {
                    $results['Installno'] = "No"
                    Write-Warning "SQL Native Client installation files does not exit. Exiting the script."
                    Break
                }
            }
    
            } -ArgumentList $dataFile.SG_CM_Admins, $dataFile.SG_CM_SiteServers, $SUP.InstallDrive, $datafile.Domain
    
        $date = get-date
        $LogFolder = "c:\ProvisionSRV"
        If (!(Test-Path $LogFolder)) {New-Item $LogFolder -ItemType directory}
        $Random2 = Get-Date -UFormat %Y%m%d_%H%M%S
        $logfile = $LogFolder + "\" + "SUPInstall" + "_" + $Random2 + ".log"
        new-item -ItemType file $logfile -Force
        Write-Host "The log file $logfile was created" -ForegroundColor Yellow; $date = get-date; add-content $logfile "$date  -  The log file $logfile was created"
    
        $date = get-date; add-content $logfile " =================================================================="
        $date = get-date; add-content $logfile "  $date  -  Installing Software Update Point role"
        $date = get-date; add-content $logfile " =================================================================="
        $date = get-date; add-content $logfile ""
    
    
        If(!($prepResults.Installno -eq "No"))
        {    
            $installSUP = @{}
            if((Get-PSDrive -Name $($SUP.Sitecode) -PSProvider CMSite -ErrorAction SilentlyContinue) -eq $null) {
            New-PSDrive -Name $($SUP.SiteCode) -PSProvider CMSite -Root $($SUP.PriServer) | Out-Null
            }
            Set-Location "$($SUP.Sitecode):\" | Out-Null
    
            $SSresults = (Get-CMSiteSystemServer -SiteSystemServerName $($SUP.ServerName)).NetworkOSPath 
            If ($SSresults)
            {
                Write-Host "SCCM Site System $SSresults already exit.  Checking if the Software Update Point role already exist." -ForegroundColor Yellow; $date = get-date; add-content $logfile "$date  -  SCCM Site System $SSresults already exit. Checking if the Software Update Point role already exist."
                $SUPresults = (Get-CMSoftwareUpdatePoint -SiteSystemServerName $($SUP.ServerName) -SiteCode $($SUP.Sitecode)).NetworkOSPath
                If ($SUPresults)
                {
                    Write-Host "The SCCM Software Update Point $($SUP.ServerName) already exist." -ForegroundColor Yellow; add-content $logfile "$date  -  The SCCM Software Update Point $SUPresults already exist."
                    $installSUP['Installyes'] = "Yes"
                }
                Else
                {
                    Write-Host "The Software Update Point (SUP) role does not exist on $($SUP.ServerName). Adding SUP role" -ForegroundColor Yellow; $date = get-date; add-content $logfile "$date  -  The SCCM Software Update Point (SUP) $($SUP.ServerName) does not exist. Adding SUP role"
                    Try
                    {
                        Add-CMSoftwareUpdatePoint -SiteCode $($SUP.Sitecode) -SiteSystemServerName $($SUP.ServerName) -ClientConnectionType $($SUP.ConnectionType) -WsusIisPort $($SUP.iisPort) -WsusIisSslPort $($SUP.IisSSLport) -Verbose -ErrorAction SilentlyContinue -ErrorVariable err
                        $SUPresults = (Get-CMSoftwareUpdatePoint -SiteSystemServerName $($SUP.ServerName) -SiteCode $($SUP.Sitecode)).NetworkOSPath
                        If ($SUPresults)
                        {
                            Write-Host "The installation of the SCCM Software Update Point $($SUP.ServerName) is in progress." -ForegroundColor Yellow; add-content $logfile "$date  -  The SCCM Software Update Point $SUPresults already exist."
                            $installSUP['Installyes'] = "Yes"
                        }
                    }
                    Catch
                    {
                        $installSUP['Installno'] = "No"
                        Write-Warning "There was a problem executing the add SUP command.  Correct and run the script again (CM1)."; $date = get-date; add-content $logfile "$date  -  There was a problem executing the add SUP command.  Existing the script (CM1)."
                        break
                    }
                    Start-Sleep -s 3
                }
            }
            Else 
            {
                Write-Host "SCCM Site System $($SUP.ServerName) does not exist. Adding Server as a CM site system.  Please wait..." -ForegroundColor Yellow; $date = get-date; add-content $logfile "$date  -  SCCM Site System $($SUP.ServerName) does not exist. Adding Server as a CM site system.  Please wait..."
                Try
                {
                    New-CMSiteSystemServer -ServerName $($SUP.ServerName) -SiteCode $($SUP.Sitecode) -AccountName $null | Out-Null -ErrorAction SilentlyContinue -ErrorVariable err
                }
                Catch 
                {
                    $installSUP['Installno'] = "No"
                    write-host "There was an error adding the site system. Exiting the script (CM2)."; $date = get-date; add-content $logfile "$date  -  The was an error adding the site system. Exiting the script (CM2)."
                    Break
                }
                Start-Sleep -s 7
                $SSresults2 = (Get-CMSiteSystemServer -SiteSystemServerName $($SUP.ServerName)).NetworkOSPath
                If ($SSResults2)
                {
                    Write-Host "Server $($SUP.ServerName) was added as a SCCM Site System. Adding the Software Update Point (SUP) role, please wait..." -ForegroundColor Yellow; $date = get-date; add-content $logfile "$date  -  Server $($SUP.ServerName) was added as a SCCM Site System. Adding SUP role, please wait..."
                    Try
                    {
                        Add-CMSoftwareUpdatePoint -SiteCode $($SUP.Sitecode) -SiteSystemServerName $($SUP.ServerName) -ClientConnectionType $($SUP.ConnectionType) -WsusIisPort $($SUP.iisPort) -WsusIisSslPort $($SUP.IisSSLport) -Verbose -ErrorAction SilentlyContinue -ErrorVariable err
                        $SUPresults = (Get-CMSoftwareUpdatePoint -SiteSystemServerName $($SUP.ServerName) -SiteCode $($SUP.Sitecode)).NetworkOSPath
                        If ($SUPresults)
                        {
                            Write-Host "The SCCM Software Update Point $($SUP.ServerName) installed successfully." -ForegroundColor Yellow; add-content $logfile "$date  -  The SCCM Software Update Point $SUPresults already exist."
                            $installSUP['Installyes'] = "Yes"
                        }
                    }
                    Catch
                    {
                        Write-Host "The was a problem executing the add SUP command.  Exiting the script (CM3)."
                        break
                    }
    
                    Start-Sleep -s 3
                }
            
             }
    
            # Configure the SUP 
            Start-Sleep -Seconds 7
            Try
            {
                If($($SUP.upstream) -eq "Yes")
                {
                    $SUPObj = Get-CMSoftwareUpdatePointComponent -SiteCode $($SUP.Sitecode) #-SiteSystemServerName $($SUP.ServerName)
                    Set-CMSoftwareUpdatePointComponent -Name $($SUP.ServerName) -AddUpdateClassification $($SUP.UpdateClass) -AddLanguageSummaryDetail $($SUP.Language) -AddLanguageUpdateFile $($SUP.Language) -AddProduct $($SUP.Products) -EnableCallWsusCleanupWizard $true -ImmediatelyExpireSupersedence $false -WaitMonth 2 -SynchronizeAction SynchronizeFromMicrosoftUpdate
                }
                else
                {
                    $SUPObj = Get-CMSoftwareUpdatePointComponent -SiteCode $($SUP.Sitecode) #-SiteSystemServerName $($SUP.ServerName)
                    Set-CMSoftwareUpdatePointComponent -InputObject $SUPObj -AddLanguageSummaryDetail $($SUP.Language) -AddLanguageUpdateFile $($SUP.Language)
                }
                
            }
            Catch
            {
                Write-Warning "There was a problem configuring the SUP. This might be a false positive.  Check th console if the language and classification were set."; $date = get-date; add-content $logfile "$date  -  There was a problem configuring the SUP. This might be a false positive.  Check th console if the language and classification were set."
            }
        }
        
        If(!($installSUP.Installno -eq "No"))
        {
                
                If($((Get-cmsite -SiteCode $($SUP.Sitecode)).ServerName) -eq $($SUP.ServerName))
                {
                    $supLog = $((Get-cmsite -SiteCode $($SUP.Sitecode)).installDir) + "\Logs\SUPsetup.log"
                }
                else
                {
                    $SUPlog = $SUP.SUPlog
                }
                
                $strcount = 0
                $date = get-date
                Write-Host "$date - Starting Do until loop.  Checking if the SUP role is installed on $($SUP.ServerName)."; $date = get-date; add-content $logfile "$date  -  Starting Do until loop.  Checking if the SUP is installed on $($SUP.ServerName)."
    
                Do {
                    Start-Sleep -s 30
                    $strcount += 30
                    $SUPinstall = Invoke-Command -ComputerName $SUP.serverName -Credential $credential -ScriptBlock {$SUPinstallLog = $args[0]; Get-Content -ErrorAction SilentlyContinue -ErrorVariable err $SUPinstallLog | select-object -Last 10 | where-object {$_ -match 'Installation was successful'}} -ArgumentList $SUP.SUPlog
                    If ($err) {Write-Host "The file $SUPlog does not exist as yet." -ForegroundColor Cyan; add-content $logfile "$date  -  The file $SUPlog does not exist as yet."}
                    Write-Host "$strcount seconds - still checking... " -ForegroundColor Yellow; $date = get-date; add-content $logfile "$date  -  $strcount minutes - still checking... " 
                } Until ($Null -ne $SUPinstall -or $strcount -eq 60)
                If ($SUPinstall) {
                    Write-host "SUP was installed successfully." -ForegroundColor Yellow; $date = get-date; add-content $logfile "$date  -  SUP role was installed successfully on $($SUP.ServerName)"
                    Start-Sleep -s 5
                }
                If ($strCount -eq 60) {
                    Write-Verbose -Message "It has been over 1 minutes and the SUP is still installing. Resolve the problem and try again." -Verbose; add-content $logfile "$date  -   It has been over 60 seconds and the SUP $($SUP.ServerName) is still installing. Do a manual check to confirm."
                }
        }

        Get-PSSession | Remove-PSSession
        }
    }
    

The code for the input file is displayed below. Copy and save as SUPInputFile.psd1

@{
    ParentSiteCode    = 'CAS' # Top level site code
    ParentSrvName     = 'TopLevelSrv.Domain.com' #Top level site server
    CMinstallDir      = 'E:\SCCM'
    SG_CM_Admins      = 'SG_CM_Admins'
    SG_CM_SiteServers = 'SG_CM_SiteServers'
    Domain            = 'Domain.com' #Change this to the domain of the Admin and Server groups if different from the domain of the computers.
    SQLClient         = 'c:\hold\SQL Server Native client\sqlncli.msi'
    SQLClientDrive    = 'C:\sqlncli.msi'  #Just change the file name if needed but leave the file on the root of C:\
    CopyFiles         = 'Yes' #Values are 'Yes' or 'No'
    SUPInfo = @(
        @{
            SiteCode       = 'PR1'
            ServerName     = 'SUP1.Domain.com' #WSUS and SUP server
            PriServer      = 'PR1.Domain.com' #CAS or primary
            ConnectionType = 'Intranet'
            IISport        = '8530'
            IisSSLport     = '8531'
            SUPlog         = 'E:\SMS\Logs\SUPsetup.log' #Enter path to SUPSetup.log
            InstallDrive   = 'E:'
            Fldname        = 'E:\WSUS'
            Sharename      = 'WSUS'
            UtilPath       = 'C:\Program Files\Update Services\Tools'
            UtilFullPath   = "C:\Program Files\Update Services\Tools\wsusutil.exe"
            DBserver       = 'DBsrv.Domain.Com'
            UpdateClass    = @('Critical Updates','Definition Updates','Security Updates','Update Rollups','Updates','Upgrades')
            Products       = @('Windows Server 2016','Windows Server 2016','Windows 10','Windows Defender')
            Language       = 'English'
            Upstream       = 'No' # Change this value to YES if this server will serve as the upstream SUP
        }
        @{
            SiteCode       = 'PR2'
            ServerName     = 'SUP2.Domain.com' #WSUS and SUP server
            PriServer      = 'PR2.Domain.com' #CAS or primary
            ConnectionType = 'Intranet'
            IISport        = '8530'
            IisSSLport     = '8531'
            SUPlog         = 'E:\SMS\Logs\SUPsetup.log' #Enter path to SUPSetup.log
            InstallDrive   = 'E:'
            Fldname        = 'E:\WSUS'
            Sharename      = 'WSUS'
            UtilPath       = 'C:\Program Files\Update Services\Tools'
            UtilFullPath   = "C:\Program Files\Update Services\Tools\wsusutil.exe"
            DBserver       = 'DBPR2.Domain.Com'
            UpdateClass    = @('Critical Updates','Definition Updates','Security Updates','Update Rollups','Updates','Upgrades')
            Products       = @('Windows Server 2016','Windows Server 2016','Windows 10','Windows Defender')
            Language       = 'English'
            Upstream       = 'No' # Change this value to no if you are not installing the upstream SUP
        }
    )
}

Authors