Public/Invoke-CMBuild.ps1
#requires -RunAsAdministrator #requires -version 5 function Invoke-CMBuild { <# .SYNOPSIS SCCM site server installation script .DESCRIPTION Yeah, what he said. .PARAMETER XmlFile Path and Name of XML input file .PARAMETER NoCheck Skip platform validation restrictions .PARAMETER NoReboot Suppress reboots until very end .PARAMETER Detailed Show verbose output .PARAMETER ShowMenu Choose package items to execute directly from GUI menu .PARAMETER Resume Indicates a resumed process request .EXAMPLE Invoke-CMBuild -XmlFile .\cmbuild.xml -Verbose .EXAMPLE Invoke-CMBuild -XmlFile .\cmbuild.xml -NoCheck -NoReboot -Detailed .EXAMPLE Invoke-CMBuild -XmlFile .\cmbuild.xml -ShowMenu -Verbose .NOTES 1.0.6 - 11/16/2017 - David Stein Read the associated XML to make sure the path and filename values all match up like you need them to. #> [CmdletBinding(SupportsShouldProcess=$True)] param ( [parameter(Mandatory=$True, HelpMessage="Path or URI of XML input file")] [ValidateNotNullOrEmpty()] [string] $XmlFile, [parameter(Mandatory=$False, HelpMessage="Skip platform validation checking")] [switch] $NoCheck, [parameter(Mandatory=$False, HelpMessage="Suppress reboots")] [switch] $NoReboot, [parameter(Mandatory=$False, HelpMessage="Display verbose output")] [switch] $Detailed, [parameter(Mandatory=$False, HelpMessage="Override control set from XML file")] [switch] $ShowMenu, [parameter(Mandatory=$False, HelpMessage="Resume from previous unfinished processing")] [switch] $Resume ) Write-Host "CMBuild $CMBuildVersion" -ForegroundColor Cyan $ScriptPath = Get-ScriptDirectory $RunTime1 = Get-Date $tsFile = "$LogsFolder\cm_build`_$HostName`_transaction.log" try {stop-transcript -ErrorAction SilentlyContinue} catch {} try {Start-Transcript -Path $tsFile -Force} catch {} if ($Resume) {$OpenKey = 'RESUME'} else {$OpenKey = 'BEGIN'} Write-Log -Category "info" -Message "******************* $OpenKey $(Get-Date) *******************" Write-Log -Category "info" -Message "script version = $CMBuildVersion" Install-CMBuildModules [xml]$xmldata = Get-CMxConfigData $XmlFile Write-Log -Category "info" -Message "----------------------------------------------------" if ($xmldata.configuration.schemaversion -ge $SchemaVersion) { Write-Log -Category "info" -Message "xml template schema version is valid" } else { Write-Log -Category "info" -Message "xml template schema version is invalid: $($xmldata.configuration.schemaversion)" Write-Warning "The specified XML file is not using a current schema version" break } Set-CMxTaskCompleted -KeyName 'START' -Value $(Get-Date) if ($ShowMenu) { $controlset = $xmldata.configuration.packages.package | Out-GridView -Title "Select Packages to Run" -PassThru } else { $controlset = $xmldata.configuration.packages.package | Where-Object {$_.use -eq '1'} } if ($controlset) { $project = $xmldata.configuration.project $AltSource = $xmldata.configuration.sources.source | Where-Object {$_.name -eq 'WIN10'} | Select-Object -ExpandProperty path Write-Log -Category "info" -Message "alternate windows source = $AltSource" Write-Log -Category "info" -Message "----------------------------------------------------" Write-Log -Category "info" -Message "project info....... $($project.comment)" if (-not (Import-CMxFolders -DataSet $xmldata)) { Write-Warning "error: failed to create folders (aborting)" break } if (-not (Import-CMxFiles -DataSet $xmldata)) { Write-Warning "error: failed to create files (aborting)" break } Write-Host "Executing project configuration" -ForegroundColor Green Disable-InternetExplorerESC | Out-Null Set-CMxRegKeys -DataSet $xmldata -Order "before" | Out-Null Write-Log -Category "info" -Message "beginning package execution" Write-Log -Category "info" -Message "----------------------------------------------------" $continue = $True $pkgcount = 0 foreach ($package in $controlset) { if ($continue) { $pkgName = $package.name $pkgType = $package.type $pkgComm = $package.comment $payload = $xmldata.configuration.payloads.payload | Where-Object {$_.name -eq $pkgName} $pkgSrcX = $xmldata.configuration.sources.source | Where-Object {$_.name -eq $pkgName} $pkgSrc = $pkgSrcX.path $pkgFile = $payload.file $pkgArgs = $payload.params $detRule = $xmldata.configuration.detections.detect | Where-Object {$_.name -eq $pkgName} $detPath = $detRule.path $detType = $detRule.type $depends = $package.dependson Write-Log -Category "info" -Message "package name.... $pkgName" Write-Log -Category "info" -Message "package type.... $pkgType" Write-Log -Category "info" -Message "package comment. $pkgComm" Write-Log -Category "info" -Message "payload source.. $pkgSrc" Write-Log -Category "info" -Message "payload file.... $pkgFile" Write-Log -Category "info" -Message "payload args.... $pkgArgs" Write-Log -Category "info" -Message "rule type....... $detType" if (!(Test-CMxPackage -PackageName $dependson)) { Write-Log -Category "error" -Message "dependency missing: $depends" $continue = $False break } if (($detType -eq "") -or ($detPath -eq "") -or (-not($detPath))) { Write-Log -Category "error" -Message "detection rule is missing for $pkgName (aborting)" $continue = $False break } $installed = $False $installed = Get-CMxInstallState -PackageName $pkgName -RuleType $detType -RuleData $detPath if ($installed) { Write-Log -Category "info" -Message "install state... $pkgName is INSTALLED" } else { Write-Log -Category "info" -Message "install state... $pkgName is NOT INSTALLED" $x = Invoke-CMxPackage -Name $pkgName -PackageType $pkgType -PayloadSource $pkgSrc -PayloadFile $pkgFile -PayloadArguments $pkgArgs if ($x -ne 0) {$continue = $False; break} } $pkgcount += 1 Write-Log -Category "info" -Message "----------------------------------------------------" if (Test-PendingReboot) { if ($NoReboot) { Write-Log -Category 'info' -Message 'a reboot is required - but NoReboot was requested.' Write-Warning "A reboot is required but has been suppressed." } else { Write-Log -Category 'info' -Message 'a reboot is requested.' Invoke-CMxRestart -XmlFile $XmlFile Write-Warning "A reboot is requested. Reboot now." Restart-Computer -Force break } } } else { Write-Warning "STOP! aborted at step [$pkgName] $(Get-Date)" break } } # foreach if (($pkgcount -gt 0) -and ($continue)) { Set-CMxRegKeys -DataSet $xmldata -Order "after" | Out-Null } } Write-Host "Processing finished at $(Get-Date)" -ForegroundColor Green $RunTime2 = Get-TimeOffset -StartTime $RunTime1 Write-Log -Category "info" -Message "finished at $(Get-Date) - total runtime = $RunTime2" if ((Test-PendingReboot) -and ($NoReboot)) { Write-Host "A REBOOT is REQUIRED" -ForegroundColor Cyan } Stop-Transcript } Export-ModuleMember -Function Invoke-CMBuild |