SCCM MP automated install via PowerShell

Automation is always good in large or small organizations to minimize error and remove the tediousness of repetitive task. This script will install the management point (MP) role on one or multiple site system servers in thier assigned site.

The script will run the following task

  • Check if the site server and SCCM admin domain groups were added to local admin group. If not, add them.
  • Create if No_SMS_On_Drive.SMS exist on the C:\ drive. If not, create it
  • Check if the install drive exist. If the drive does not exist, stop the script.
  • Check for the prerequisites exist. If not install them
    • Install .Net Framework Core and 4.8
    • SQL Native Client
    • Firewall exception
    • BITS, BITS-IIS-Ext, Web-ISAPI-Ext,Web-Windows-Auth,Web-Metabase,Web-WMI
  • Check if the site system for the MP exist. If not, add it
  • Check if the MP role exist. If not, add it.
  • Wait until the MP role is installed and report success or failure.

How to run the script

The script consist of two files. You can add both files to the same folder.

  • Install-ManagementPoint.ps1
  • MPInputFile.psd1

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

. C:\Script\Install-Managementpoint.ps1

Then run the MP install function.

Install-ManagementPoint -InputFile "C:\Script\MPInputFile.psd1"

Download the script from Technet Gallery. The code is also listed below. Copy and save in Install-ManagementPoint.ps1


Function Install-ManagementPoint{
<#
.Synopsis
 This script will install the Management Point role on one or multiple server in each ConfigMgr site.

.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.  Create No_SMS_On_Drive.SMS on the C:\ drive.
   3.  Check if the content drive exist. If the drive does not exist, stop te script.
   4.  Check for the prerequisites and install (IIS, SQL native client, firewall exception, .Net 4.8...)
   5.  Check if the Site System for the MP exist, if not add it.
   6.  Check the MP exist, if not add it.
   7.  Wait until the MP role is installed and report success or failure.

 The input values are stored in the MPInputFile.psd1 - edit this file to add specific values.

.PARAMETER InputFile
 Holds the path to the inputFile file - This file stores all the required values.

.Example
 Install-ManagementPoint -InputFile "C:\Script\MPInputFile.psd1"

.NOTES
 Created on:  05/28/2020
 Created by:  Lynford Heron
 Filename:    Install-ManagementPoint.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!"
        Exit
    }

#Import-Module
Import-Module CMinstall -Force


Write-Host "Enter the credetial with admin rights on the remote server." -ForegroundColor Yellow | Out-Null
$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 of 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
}

# Set the current location to be the site code.
Set-Location "$($casSiteCode):\"

#Preflight Check - AD computer account - if company policy or settings prevents this section from running, just remove it.
foreach ($srv in $dataFile.MPInfo.servername)
{
    $ADmodule = (Get-module -Name Activedirectory).Name
    If(!($ADmodule))
    {
        Install-WindowsFeature RSAT-AD-PowerShell | Out-Null
    }
    Import-Module -Name ActiveDirectory 

    Try 
    {
        $compResult = Get-ADComputer -Identity $srv.Replace(("." + $dataFile.CompDomain),"") -ErrorAction SilentlyContinue
        If($compResult)
        {
            Write-Verbose -Message "Valid computer account found: $($srv)" -Verbose 
        }
    }
    catch
    {
        Write-warning "Computer account $($srv) was not found. Exiting script"  
        Exit 
    }
}

#copy files to get around double hop access denied - .Net 4.8 and SQL native client
If ($($dataFile.CopyFiles) -eq 'Yes')
{
    foreach ($srv in $dataFile.mpinfo.servername)
    {
        Try
        {
            Copy-Item -Path $datafile.NetFramework -Destination $datafile.DotNetDrive.Substring(0,3) -Force -ToSession (New-PSSession -ComputerName $srv) | Out-Null # -ErrorAction SilentlyContinue this works fine, 4.8 is not approved at VA
        }
        Catch
        {
            Write-Warning "There was an error copying the file $($datafile.NetFramework) "
        }
        
        Try
        {
            Copy-Item -Path $datafile.SQLClient -Destination $datafile.SQLClientDrive.Substring(0,3) -Force -ToSession (New-PSSession -ComputerName $srv) | Out-Null  #-ErrorAction SilentlyContinue 
        }
        Catch
        {
            Write-Warning "There was an error copying the file $($datafile.SQLClient))"
        }
    }
    Get-PSSession | Remove-PSSession
}

    Foreach ($MP in $dataFile.MPInfo)
    {
        $session = New-PSSession -ComputerName $MP.ServerName -Credential $credential
        Invoke-Command -Session $session -ScriptBlock {

            $Cmadmins       = $args[0]
            $CmSiteservers  = $args[1]
            $InstallDrive   = $args[2]
            $Server         = $args[3]
            $Domain         = $args[4]
            $DotNetDrive    = $args[5]
            $SQLClientDrive = $args[6]

            #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)) {
                Write-Warning "There was a problem creating the file no_sms_on_drive.sms on $env:COMPUTERNAME. Fix the problem and run the script again"
                Exit
            }

            $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 E: drive
            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)."
            }
            Else
            {
                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:"
            }

                $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-verbose -message "The domain group $Cmadmins does not exist on $env:COMPUTERNAME. Adding group to local administrators:" -Verbose; $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-verbose -message "The missing group $Cmadmins was added" -Verbose; $date = get-date; add-content $logfile " $date  -  The missing group $Cmadmins added"} 
                    Else {write-Warning "There was a problem adding the domain $Cmadmins to the local administrators group on $env:COMPUTERNAME. Check the ProvisionPDP log and work to resolve" -ForegroundColor red; $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 ProvisionPDP log and work to resolve"}

                }

                If (!($GroupMembers -contains $CmSiteservers)) 
                {
                    Write-verbose -message "The domain group $CmSiteservers does not exist on $env:COMPUTERNAME. Adding group to local administrators:" -Verbose
                    $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-verbose -message "The missing group $CmSiteservers was added" -Verbose; $date = get-date; add-content $logfile " $date  -  The missing group $CmSiteservers was added"
                    } 
                    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"
                        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"
                    }
                } 
                If ($GroupMembers -contains $Cmadmins -and $GroupMembers -contains $CmSiteservers) {Write-verbose -message "Domain Groups $Cmadmins and $CmSiteservers already exist on $env:COMPUTERNAME" -Verbose; $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
                Write-Verbose -Message "Installing .Net Framework Core.  Please wait..." -Verbose
                #Install-WindowsFeature Net-Framework-Core -Source $SXSpath | Out-Null
                Install-WindowsFeature NET-Framework-Core | Out-Null
                #Enable-WindowsOptionalFeature -Online -FeatureName "NetFx3"
                Write-Verbose -Message "Installing BITS.  Please wait..." -Verbose
                Install-WindowsFeature BITS,BITS-IIS-Ext | Out-Null
                Write-Verbose -Message "Installing IIS required features.  Please wait..." -Verbose
                Install-WindowsFeature Web-ISAPI-Ext,Web-Windows-Auth,Web-Metabase,Web-WMI | Out-Null

                #If Windows firewall is on, add exceptions. 
                If((Get-NetFirewallProfile -Name Domain).Enabled)
                {   Write-verbose -message "Windows Firewall is enabled.  Adding exceptions" -Verbose
                    New-NetFirewallRule -DisplayName 'HTTP(S) Inbound' -Profile Domain -Direction Inbound -Action Allow -Protocol TCP -LocalPort @(80,443) -Group "For SCCM MP"
                    New-NetFirewallRule -DisplayName 'SQL over TCP  Outbound' -Profile Domain -Direction Outbound -Action Allow -Protocol TCP -LocalPort 1433 -Group "For SCCM MP"
                    New-NetFirewallRule -DisplayName 'LDAP Outbound' -Profile Domain -Direction Outbound -Action Allow -Protocol TCP -LocalPort 389 -Group "For SCCM MP"
                    New-NetFirewallRule -DisplayName 'LDAP(SSL) Outbound' -Profile Domain -Direction Outbound -Action Allow -Protocol TCP -LocalPort 636 -Group "For SCCM MP"
                    New-NetFirewallRule -DisplayName 'LDAP(SSL) UDP Outbound' -Profile Domain -Direction Outbound -Action Allow -Protocol UDP -LocalPort 636 -Group "For SCCM MP"
                    New-NetFirewallRule -DisplayName 'Global Catelog LDAP Outbound' -Profile Domain -Direction Outbound -Action Allow -Protocol TCP -LocalPort 3268 -Group "For SCCM MP"
                    New-NetFirewallRule -DisplayName 'Global Catelog LDAP SSL Outbound' -Profile Domain -Direction Outbound -Action Allow -Protocol TCP -LocalPort 3269 -Group "For SCCM MP"

                    New-NetFirewallRule -DisplayName 'SMB Inbound' -Profile Domain -Direction Inbound -Action Allow -Protocol TCP -LocalPort 445 -Group "For SCCM MP"
                    New-NetFirewallRule -DisplayName 'SMB Outbound' -Profile Domain -Direction Outbound -Action Allow -Protocol TCP -LocalPort 445 -Group "For SCCM MP"
                    New-NetFirewallRule -DisplayName 'RPC Endpoint Mapper Inbound' -Profile Domain -Direction Inbound -Action Allow -Protocol TCP -LocalPort 135 -Group "For SCCM MP"
                    New-NetFirewallRule -DisplayName 'RPC Endpoint Mapper Outbound' -Profile Domain -Direction Outbound -Action Allow -Protocol TCP -LocalPort 135 -Group "For SCCM MP"
                    New-NetFirewallRule -DisplayName 'RPC Endpoint Mapper UDP Inbound' -Profile Domain -Direction Inbound -Action Allow -Protocol UDP -LocalPort 135 -Group "For SCCM MP"
                    New-NetFirewallRule -DisplayName 'RPC Endpoint Mapper UDP Outbound' -Profile Domain -Direction Outbound -Action Allow -Protocol UDP -LocalPort 135 -Group "For SCCM MP"
                }
                Else
                {  Write-verbose -message "The domain profile for Windows firewall is disabled" -Verbose}

            #Install .Net 4.8 or later
            Write-verbose -message "Checking if .Net Framework release 4.8 or later is installed." -Verbose
            $_NetFrameworkVersion = (Get-ItemProperty "HKLM:SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full").Release
            If ($_NetFrameworkVersion -ge 528040) #.Net 4.8 release number.  Change the number for new release.
            {
                Write-verbose -message ".Net Framework release $_NetFrameworkVersion which is version 4.8 or later is already installed. Next step is to install the SQL native client." -Verbose
            }
            Else
            {
                Write-verbose -message ".Net Framework 4.8 or later is not installed.  Checking if the installation file ($DotNetDrive) exist" -Verbose
                If(Test-Path $DotNetDrive) 
                    {Write-verbose -message ".Net Framework 4.8 or later installation files exist.  Installing, please wait..." -Verbose
                     Start-Process -FilePath $DotNetDrive -argumentlist '/quiet', '/norestart' -wait
                     $_NetFrameworkVersion = (Get-ItemProperty "HKLM:SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full").Release
                     If($_NetFrameworkVersion -ge 528040)
                        {
                            Write-verbose -message ".Net Framework release $_NetFrameworkVersion was successfully installed.  Restart Pending..." -Verbose
                        }
                     Else { Write-Warning "There was a problem installing .Net Framework. Check the eventlog for errors or reboot is pending..."}
                    }
                Else
                    {
                     Write-Warning ".Net Framework 4.8 or later installation files does not exit."
                    }
            }
            
            #Installing SQL Native Client
            #unblock the install file to prevent the security warning
            Write-verbose -message "Checking if SQL Native Client is already installed..." -Verbose
            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-verbose -message "SQL Native Client driver $sqlNativeClient is already installed." -Verbose
            }
            Else
            {
                Write-verbose -message "SQL Native Client is not installed.  Checking for installation files $($SQLClientDrive)" -Verbose
                If(Test-Path $SQLClientDrive) 
                    {Write-verbose -message "SQL Native Client installation file exist.  Installing, please wait..." -Verbose
                     Start-Process -FilePath msiexec.exe -ArgumentList "/i `"$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-verbose -message "SQL Native Client driver $sqlNativeClient was successfully installed." -Verbose
                        }
                     Else { Write-Warning "There was a problem installing SQL Native Client. Check the eventlog for errors."}
                    }
                Else
                    {
                     Write-Warning "SQL Native Client installation files does not exit. Exiting the script."
                     Exit
                    }
              }
       
     } -ArgumentList $dataFile.SG_CM_Admins, $dataFile.SG_CM_SiteServers, $MP.InstallDrive, $MP.ServerName, $datafile.Domain, $dataFile.DotNetDrive, $dataFile.SQLClient
   }

    $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 + "\" + "MPInstall" + "_" + $Random2 + ".log"
    new-item -ItemType file $logfile -Force
    Write-verbose -message "The log file $logfile was created" -Verbose; $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 Management Point role"
    $date = get-date; add-content $logfile " =================================================================="
    $date = get-date; add-content $logfile ""

        Foreach ($MP2 in $dataFile.MPInfo)
        {
            if((Get-PSDrive -Name $($MP2.Sitecode) -PSProvider CMSite -ErrorAction SilentlyContinue) -eq $null) {
            New-PSDrive -Name $($MP2.SiteCode) -PSProvider CMSite -Root $($MP2.PriServer) | Out-Null
            }
            Set-Location "$($MP2.Sitecode):\" | Out-Null

            $SSresults = (Get-CMSiteSystemServer -SiteSystemServerName $($MP2.ServerName)).NetworkOSPath 
            If ($SSresults) {
                Write-verbose -message "SCCM Site System $SSresults already exit.  Checking if the Management Point role already exist." -Verbose; $date = get-date; add-content $logfile "$date  -  SCCM Site System $SSresults already exit. Checking if the MP role already exist."
                $MPresults = (Get-CMManagementPoint -SiteSystemServerName $($MP2.ServerName) -SiteCode $($MP2.SiteCode)).NetworkOSPath
                If ($MPresults) {Write-verbose -message "The SCCM Management Point $($MP2.ServerName) already exist." -Verbose; add-content $logfile "$date  -  The SCCM Management Point $MPresults already exist."}
                Else {
                    Write-verbose -message "The Management Point role does not exist on $($MP2.ServerName). Adding MP role" -Verbose; $date = get-date; add-content $logfile "$date  -  The SCCM Management Point $($MP2.ServerName) does not exist. Adding MP role"
                    Add-CMManagementPoint -SiteSystemServerName $($MP2.ServerName) -SiteCode $($MP2.SiteCode) -ClientConnectionType $($MP2.ConnectionType) -CommunicationType $($MP2.CommunicationType) | Out-Null -ErrorAction SilentlyContinue -ErrorVariable err
                    Start-Sleep -s 10

                }
            }
            Else {
                Write-verbose -message "SCCM Site System $($MP2.ServerName) does not exist. Adding Server as a CM site system.  Please wait..." -Verbose; $date = get-date; add-content $logfile "$date  -  SCCM Site System $($MP2.ServerName) does not exist. Adding Server as a CM site system.  Please wait..."
                Try {New-CMSiteSystemServer -ServerName $($MP2.ServerName) -SiteCode $($MP2.SiteCode) -AccountName $null | Out-Null -ErrorAction SilentlyContinue -ErrorVariable err}
                Catch {Write-verbose -message "There was an error adding the site system. Exiting the script (CM2)." -Verbose; $date = get-date; add-content $logfile "$date  -  There was an error adding the site system. Exiting the script (CM2)." ;Exit}
                Start-Sleep -s 7
                $SSresults2 = (Get-CMSiteSystemServer -SiteSystemServerName $($MP2.ServerName)).NetworkOSPath
                If ($SSResults2) {
                    Write-verbose -message "Server $($MP2.ServerName) was added as a SCCM Site System. Adding Management Point role, please wait..." -Verbose; $date = get-date; add-content $logfile "$date  -  Server $($MP2.ServerName) was added as a SCCM Site System. Adding MP role, please wait..."
                    Try {
                            Add-CMManagementPoint -SiteSystemServerName $($MP2.ServerName) -SiteCode $($MP2.SiteCode) -ClientConnectionType $($MP2.ConnectionType) -CommunicationType $($MP2.CommunicationType) | Out-Null -ErrorAction SilentlyContinue -ErrorVariable err
                        }
                    Catch {
                            Write-verbose -message "There was a problem executing the add MP command for $($MP2.ServerName).  Exiting the script (CM3)." -Verbose; $date = get-date; add-content $logfile "$date  -  There was a problem executing the add MP command for $($MP2.ServerName).  Exiting the script."; Exit
                          }
                    Start-Sleep -s 10
                }
        
            }

        }
    
    Foreach ($MPsrv in $dataFile.MPInfo)
    {
            $strcount = 0
            $date = get-date
            Write-verbose -message "$date - Starting Do until loop.  Checking if the MP role is installed on $($MPsrv.ServerName)." -Verbose; $date = get-date; add-content $logfile "$date  -  Starting Do until loop.  Checking if the MP is installed on $($MPsrv.ServerName)."
            $MPlog = $MPsrv.MPlog
            Do {
                Start-Sleep -s 30
                $strcount += 30
                $MPinstall = Invoke-Command -ComputerName $MPsrv.serverName -Credential $credential -ScriptBlock {$MPinstallLog = $args[0]; Get-Content -ErrorAction SilentlyContinue -ErrorVariable err $MPinstallLog | select-object -Last 10 | where-object {$_ -match 'return code: 0' -or $_ -match 'return code: 3010'}} -ArgumentList $MPsrv.MPlog
                If ($err) {Write-verbose -message "The file $MPlog does not exist as yet." -Verbose; add-content $logfile "$date  -  The file $MPlog does not exist as yet."}
                Write-verbose -message "$strcount seconds - still checking... " -Verbose; $date = get-date; add-content $logfile "$date  -  $strcount minutes - still checking... " 
            } Until ($Null -ne $MPinstall -or $strcount -eq 120)
            If ($MPinstall) {
                Write-verbose -message "MP was installed successfully." -Verbose; $date = get-date; add-content $logfile "$date  -  MP role was installed successfully on $($MPsrv.ServerName)"
                Start-Sleep -s 5
            }
            If ($strCount -eq 120) {
                Write-Verbose -Message "It has been over 2 minutes and the MP is still installing. Resolve the problem and try again." -Verbose; add-content $logfile "$date  -   It has been over 60 seconds and the MP $($MPsrv.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 in MPInputFile.psd1


@{
    ParentSiteCode    = 'CAS'
    ParentSrvName     = 'ServerName.Domain.com'
    CMinstallDir      = 'E:\SCCM'
    SG_CM_Admins      = 'SG_CM_Admins'
    SG_CM_SiteServers = 'SG_CM_SiteServers'
    Domain            = 'SubDomain.com' #Change this to the domain of the Admin or Server groups
    CompDomain        = 'Domain.com' #Domain of computers
    DotNetDrive       = 'c:\ndp48-x86-x64-allos-enu.exe' #Just change the file name if needed but leave the file on the root of C:\ -  run script from source server (CAS)
    NetFramework      = 'c:\Hold\.Net_Framewor_4.8\ndp48-x86-x64-allos-enu.exe'
    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:\ - can delete it after the install
    CopyFiles         = 'Yes' #Values are 'Yes' or 'No'
    MPInfo = @(
        @{
            SiteCode          = 'PR1'
            ServerName        = 'MPServerName.Domain.com'
            PriServer         = 'PRServerName.Domain.com'
            MPdesc            = 'West Palm MP'
            ConnectionType    = 'Intranet' #ConnectionType values are Intranet, Internet or InternetAndIntranet
            CommunicationType = 'HTTP' #CommunicationType values are HTTP or HTTPS
            MPLog             = 'E:\SMS\logs\MPsetup.log'
            InstallDrive      = 'E:'
        }
        @{
            SiteCode          = 'PR1'
            ServerName        = 'MPServerName.Domain.com'
            PriServer         = 'PRServerName.Domain.com'
            MPdesc            = 'Tamarac, FL MP'
            ConnectionType    = 'Intranet' #ConnectionType values are Intranet, Internet or InternetAndIntranet
            CommunicationType = 'HTTP' #CommunicationType values are HTTP or HTTPS
            MPLog             = 'E:\SMS\logs\MPsetup.log'
            InstallDrive      = 'E:'
        }
    )
}

Authors