├── Citrix Build ├── CitrixLab.ps1 └── readme.md ├── HSD Build ├── HSD Build - VDI.ps1 ├── HSDBuild - Multiple HSD No Apps.ps1 ├── HSDBuild - Multiple HSD with Apps.ps1 ├── HSDBuild - Single HSD Mutiple Apps.ps1 ├── HSDBuild - Single HSD No Apps.ps1 ├── InstallRDS.psm1 └── readme.md ├── MDT Build ├── AL Custom Role │ ├── DownloadAdk.ps1 │ ├── HostInit.ps1 │ ├── InstallMDT.ps1 │ └── MDTApplications.xml ├── MDT Server Build.ps1 ├── MDTApplications.xml └── readme.md ├── MIM Build ├── MIMLab.ps1 ├── UserRights.ps1 └── readme.md ├── MS TLG ├── BaseConfig.ps1 └── readme.md ├── README.md ├── SCCM Build 2 ├── Custom Roles │ └── SCCM │ │ ├── DownloadAdk.ps1 │ │ ├── DownloadSccm.ps1 │ │ ├── HostStart.ps1 │ │ ├── InstallSCCM.ps1 │ │ ├── Old │ │ ├── DownloadAdk.ps1 │ │ ├── DownloadSccm.ps1 │ │ ├── HostStart.ps1 │ │ └── InstallSCCM.ps1 │ │ └── README.md ├── Props.ps1 ├── SCCMLab.ps1 ├── SCCMProps.json └── readme.md └── SCCM Build ├── AL CustomRole └── SCCM │ ├── DownloadAdk.ps1 │ ├── DownloadSccm.ps1 │ ├── HostStart.ps1 │ ├── InstallSCCM.ps1 │ └── README.md ├── SCCM Server Build.ps1 └── readme.md /Citrix Build/CitrixLab.ps1: -------------------------------------------------------------------------------- 1 | function Install-Application { 2 | 3 | param ( 4 | 5 | #Session hosts to install the application on 6 | [Parameter(Mandatory)] 7 | [AutomatedLab.Machine[]]$ComputerName, 8 | 9 | #URL for the application to be downloaded 10 | [Parameter(ParameterSetName='ByURL')] 11 | [string]$URL, 12 | 13 | #ISO Path for the installation ISO 14 | [Parameter(ParameterSetName='ByISO')] 15 | [string]$ISOPath, 16 | 17 | #Folder where existing installation files are located 18 | [Parameter(ParameterSetName='ByPath')] 19 | [string]$DirectoryPath, 20 | 21 | #Path relative to source media where installation executable is located. If a URL was provided, it is assumed the InstallExecutable is the last segment in the URL name 22 | [parameter(Mandatory, ParameterSetName='ByISO')] 23 | [parameter(Mandatory, ParameterSetName='ByPath')] 24 | [ValidateNotNullOrEmpty()] 25 | [string]$InstallExecutable, 26 | 27 | #Required arguments for the installation 28 | [parameter(Mandatory)] 29 | [ValidateNotNullOrEmpty()] 30 | [string]$InstallArguments, 31 | 32 | [parameter(ParameterSetName='ByISO')] 33 | [parameter(ParameterSetName='ByPath')] 34 | [switch]$NoCopy 35 | ) 36 | 37 | switch ($PSCmdlet.ParameterSetName) { 38 | 'ByURL' { 39 | #We were passed a URL of the application to install, download if necessary 40 | $downloadTargetFolder = Join-Path -Path $labSources -ChildPath SoftwarePackages 41 | $internalUri = New-Object System.Uri($URL) 42 | Get-LabInternetFile -Uri $internalUri -Path $downloadTargetFolder -ErrorAction Stop 43 | $DownloadedFileName = $internalUri.Segments[$internalUri.Segments.Count-1] 44 | Write-ScreenInfo 'Copying source files to Target Servers' -TaskStart 45 | Copy-LabFileItem -Path (Join-Path -Path $downloadTargetFolder -ChildPath $DownloadedFileName) -DestinationFolderPath C:\Install -ComputerName $ComputerName 46 | Write-ScreenInfo 'Finished Copying Files' -TaskEnd 47 | 48 | $job = Install-LabSoftwarePackage -ComputerName $ComputerName -LocalPath "C:\Install\$DownloadedFileName" -CommandLine $InstallArguments -AsJob -PassThru -ErrorAction Stop 49 | $result = Wait-LWLabJob -Job $job -NoNewLine -ProgressIndicator 10 -PassThru -ErrorAction Stop 50 | } 51 | 'ByPath' { 52 | #See if the NoCopy flag was passed 53 | if ($NoCopy) { 54 | #Execute the file in place. 55 | $job = Install-LabSoftwarePackage -ComputerName $ComputerName -LocalPath "$DirectoryPath\$InstallExecutable" -CommandLine $InstallArguments -AsJob -PassThru -ErrorAction Stop 56 | $result = Wait-LWLabJob -Job $job -NoNewLine -ProgressIndicator 10 -PassThru -ErrorAction Stop 57 | } 58 | else { 59 | #Copy in the files to the C:\Install directory and execute from there. $InstallExecutable will be relative to the C:\Install Directory 60 | Write-ScreenInfo 'Copying source directories to Target Servers' -TaskStart 61 | Copy-LabFileItem -Path $DirectoryPath -DestinationFolderPath 'C:\Install' -ComputerName $ComputerName -Recurse 62 | Write-ScreenInfo 'Finished Copying Files' -TaskEnd 63 | $job = Install-LabSoftwarePackage -ComputerName $ComputerName -LocalPath "C:\Install\$InstallExecutable" -CommandLine $InstallArguments -AsJob -PassThru -ErrorAction Stop 64 | $result = Wait-LWLabJob -Job $job -NoNewLine -ProgressIndicator 10 -PassThru -ErrorAction Stop 65 | } 66 | 67 | } 68 | 'ByISO' { 69 | Write-ScreenInfo 'Mounting ISO on target servers' -TaskStart 70 | $disk = Mount-LabIsoImage -ComputerName $ComputerName -IsoPath $ISOPath -PassThru -SupressOutput 71 | Write-ScreenInfo 'Finished' -TaskEnd 72 | 73 | $job = Install-LabSoftwarePackage -ComputerName $ComputerName -LocalPath "$($disk.DriveLetter)\$InstallExecutable" -CommandLine $InstallArguments -AsJob -PassThru -ErrorAction Stop 74 | $result = Wait-LWLabJob -Job $job -NoNewLine -ProgressIndicator 10 -PassThru -ErrorAction Stop 75 | Dismount-LabIsoImage -ComputerName $ComputerName -SupressOutput 76 | 77 | } 78 | } 79 | 80 | } 81 | 82 | $oldverbose = $VerbosePreference 83 | $VerbosePreference = 'silentlycontinue' 84 | 85 | $labName = 'CitrixLab' 86 | $labSources = Get-LabSourcesLocation 87 | 88 | New-LabDefinition -Name $LabName -DefaultVirtualizationEngine HyperV -VmPath "C:\Hyper-V\Automation-Lab" 89 | Add-LabVirtualNetworkDefinition -Name $LabName -AddressSpace 192.168.70.0/24 90 | 91 | Add-LabIsoImageDefinition -Name 'XenDesktop7.15' -Path 'C:\LabSources\ISOs\XenApp_and_XenDesktop_7_15.iso' 92 | 93 | $PSDefaultParameterValues = @{ 94 | 'Add-LabMachineDefinition:Network' = $labName 95 | 'Add-LabMachineDefinition:ToolsPath'= "$labSources\Tools" 96 | 'Add-LabMachineDefinition:DomainName' = 'citrixlab.local' 97 | 'Add-LabMachineDefinition:DnsServer1' = '192.168.70.10' 98 | 'Add-LabMachineDefinition:Processors' = '2' 99 | 'Add-LabMachineDefinition:OperatingSystem' = 'Windows Server 2016 SERVERSTANDARD' 100 | } 101 | 102 | Add-LabMachineDefinition -Name CTX-DC01 -Memory 2GB -Roles RootDC -IPAddress '192.168.70.10' 103 | #Citrix Server - Will hold all Citrix Roles 104 | Add-LabMachineDefinition -Name CTX-AP01 -Memory 6GB -Roles SQLServer2014 -IPAddress '192.168.70.20' 105 | #XenApp Server, will run user applications 106 | Add-LabMachineDefinition -Name CTX-XA01 -Memory 4GB -IPAddress '192.168.70.21' 107 | # #XenDesktop Static Workstation 108 | Add-LabMachineDefinition -Name CTX-XD01 -Memory 4GB -IPAddress '192.168.70.30' -OperatingSystem 'Windows 10 Enterprise' 109 | 110 | #Do the AL Installation goodness 111 | Install-Lab 112 | 113 | #Save a snapshot of the machines during development, remove for production deployments 114 | Checkpoint-LABVM -All -SnapshotName 'After Build' 115 | 116 | #Install the necessary Windows Features for the main citrix server 117 | Install-LabWindowsFeature -ComputerName 'CTX-AP01' -FeatureName 'NET-Framework-45-Core,GPMC,RSAT-ADDS-Tools,RDS-Licensing-UI,WAS,WAS-Process-Model,WAS-Config-APIs,Telnet-Client,Remote-Assistance,File-Services,FS-FileServer' 118 | Restart-LABVM -ComputerName 'CTX-AP01' -Wait 119 | 120 | $CitrixHost = (Get-LabMachine -ComputerName 'CTX-AP01') 121 | Install-LabWindowsFeature -ComputerName $CitrixHost -FeatureName 'Web-Server,Web-WebServer,Web-Common-Http,Web-Default-Doc,Web-Dir-Browsing,Web-Http-Errors,Web-Static-Content,Web-Http-Redirect,Web-Health,Web-Http-Logging,Web-Log-Libraries,Web-Http-Tracing' 122 | Install-LabWindowsFeature -ComputerName $CitrixHost -FeatureName 'Web-Performance' -IncludeAllSubFeature 123 | Install-LabWindowsFeature -ComputerName $CitrixHost -FeatureName 'Web-Security,Web-Filtering,Web-Basic-Auth,Web-Windows-Auth,Web-App-Dev,Web-AppInit,Web-Net-Ext45,Web-ASP,Web-Asp-Net45,Web-CGI,Web-ISAPI-Ext,Web-ISAPI-Filter,Web-Includes' 124 | Install-LabWindowsFeature -ComputerName $CitrixHost -FeatureName 'Web-Mgmt-Tools,Web-Mgmt-Console,Web-Mgmt-Compat,Web-Metabase,Web-Lgcy-Mgmt-Console,Web-Lgcy-Scripting,Web-WMI,Web-Scripting-Tools,NET-Framework-45-ASPNET,NET-WCF-HTTP-Activation45' 125 | Restart-LabVM -ComputerName 'CTX-AP01' -Wait 126 | 127 | Install-Application -ComputerName $CitrixHost -DirectoryPath "$labSources\SoftwarePackages\Frameworks\Microsoft Visual C++ 2013 Redistributable (x86)" -InstallExecutable "Microsoft Visual C++ 2013 Redistributable (x86)\vcredist_x86.exe" -InstallArguments "/Q" 128 | Install-Application -ComputerName $CitrixHost -DirectoryPath "$labSources\SoftwarePackages\Frameworks\Microsoft Visual C++ 2013 Redistributable (x64)" -InstallExecutable "Microsoft Visual C++ 2013 Redistributable (x64)\vcredist_x64.exe" -InstallArguments "/Q" 129 | Install-Application -ComputerName $CitrixHost -DirectoryPath "$labSources\SoftwarePackages\Frameworks\Microsoft Visual C++ 2015 Redistributable (x64)" -InstallExecutable "Microsoft Visual C++ 2015 Redistributable (x64)\vc_redist.x64.exe" -InstallArguments "/Q" 130 | Install-Application -ComputerName $CitrixHost -DirectoryPath "$labSources\SoftwarePackages\Frameworks\Microsoft Visual C++ 2015 Redistributable (x86)" -InstallExecutable "Microsoft Visual C++ 2015 Redistributable (x86)\vc_redist.x86.exe" -InstallArguments "/Q" 131 | Restart-LabVM -ComputerName 'CTX-AP01' -Wait 132 | 133 | $disk = Mount-LabIsoImage -ComputerName 'CTX-AP01' -ISOPath (Get-LabIsoImageDefinition | Where-Object { $_.Name -eq 'XenDesktop7.15'}).Path -PassThru -SupressOutput 134 | Install-Application -ComputerName $CitrixHost -NoCopy -DirectoryPath "$($disk.DriveLetter)\Support\SQLLocalDB2014\x64" -InstallExecutable "sqllocaldb.msi" -InstallArguments '/quiet /norestart /log SQLLOCALDB.LOG IACCEPTSQLLOCALDBLICENSETERMS=YES' 135 | Restart-LabVM -ComputerName 'CTX-AP01' -Wait 136 | Install-Application -ComputerName $CitrixHost -NoCopy -DirectoryPath "$($disk.DriveLetter)\Support\SharedManagementObjects\x86" -InstallExecutable "SQLSysClrTypes.msi" -InstallArguments '/lv "C:\SQLSysClrTypes-x86.log" /quiet INSTALLLOCATION="C:\Program Files\Citrix" ARPSYSTEMCOMPONENT="1" MSIFASTINSTALL="1" MSIRMSHUTDOWN="2" METAINSTALLER="1" CLOUD=False REBOOT=ReallySuppress' 137 | Install-Application -ComputerName $CitrixHost -NoCopy -DirectoryPath "$($disk.DriveLetter)\Support\SharedManagementObjects\x86" -InstallExecutable "SharedManagementObjects.msi" -InstallArguments '/lv "C:\SharedManagementObjects-x86.log" /quiet INSTALLLOCATION="C:\Program Files\Citrix" ARPSYSTEMCOMPONENT="1" MSIFASTINSTALL="1" MSIRMSHUTDOWN="2" METAINSTALLER="1" CLOUD=False REBOOT=ReallySuppress' 138 | Install-Application -ComputerName $CitrixHost -NoCopy -DirectoryPath "$($disk.DriveLetter)\Support\SharedManagementObjects\x64" -InstallExecutable "SQLSysClrTypes.msi" -InstallArguments '/lv "C:\SQLSysClrTypes-x64.log" /quiet INSTALLLOCATION="C:\Program Files\Citrix" ARPSYSTEMCOMPONENT="1" MSIFASTINSTALL="1" MSIRMSHUTDOWN="2" METAINSTALLER="1" CLOUD=False REBOOT=ReallySuppress' 139 | Install-Application -ComputerName $CitrixHost -NoCopy -DirectoryPath "$($disk.DriveLetter)\Support\SharedManagementObjects\x64" -InstallExecutable "SharedManagementObjects.msi" -InstallArguments '/lv "C:\SharedManagementObjects-x64.log" /quiet INSTALLLOCATION="C:\Program Files\Citrix" ARPSYSTEMCOMPONENT="1" MSIFASTINSTALL="1" MSIRMSHUTDOWN="2" METAINSTALLER="1" CLOUD=False REBOOT=ReallySuppress' 140 | Restart-LabVM -ComputerName 'CTX-AP01' -Wait 141 | 142 | #Install the Main Citrix XenDesktop Components 143 | Install-Application -ComputerName $CitrixHost -NoCopy -DirectoryPath "$($disk.DriveLetter)\x64\XenDesktop Setup" -InstallExecutable "XenDesktopServerSetup.exe" -InstallArguments '/configure_firewall /noreboot /quiet' 144 | Restart-LabVM -ComputerName 'CTX-AP01' -Wait 145 | 146 | 147 | Dismount-LabIsoImage -ComputerName $CitrixHost 148 | 149 | #The the necessary apps installed on the machines 150 | $InstallHosts = @() 151 | $InstallHosts += (Get-LabMachine -ComputerName 'CTX-XA01') 152 | # $InstallHosts += (Get-LabMachine -ComputerName 'CTX-XD01') 153 | 154 | # #Install Office VL Edition on both the XA and XD machines 155 | Install-Application -ComputerName $InstallHosts -URL 'https://ftp.mozilla.org/pub/firefox/releases/57.0/win64/en-US/Firefox%20Setup%2057.0.exe' -InstallArguments '-ms' 156 | Install-Application -ComputerName $InstallHosts -DirectoryPath "$labSources\SoftwarePackages\Microsoft Office Pro Plus 2016" -InstallExecutable "Microsoft Office Pro Plus 2016\Setup.exe" -InstallArguments "/adminfile Office_R2.MSP" 157 | 158 | # #Install the compontents required on the XenApp host 159 | Install-LabWindowsFeature -ComputerName 'CTX-XA01' -FeatureName 'Remote-Desktop-Services,RDS-RD-Server,NET-Framework-45-Core,Remote-Assistance,Server-Media-Foundation,FileAndStorage-Services,Storage-Services' 160 | Restart-LabVM -ComputerName 'CTX-XA01' -Wait 161 | 162 | #Install the Visual C++ Runtimes 163 | Install-Application -ComputerName (Get-LabMachine -ComputerName 'CTX-XA01') -DirectoryPath "$labSources\SoftwarePackages\Frameworks\Microsoft Visual C++ 2013 Redistributable (x86)" -InstallExecutable "Microsoft Visual C++ 2013 Redistributable (x86)\vcredist_x86.exe" -InstallArguments "/Q" 164 | Install-Application -ComputerName (Get-LabMachine -ComputerName 'CTX-XA01') -DirectoryPath "$labSources\SoftwarePackages\Frameworks\Microsoft Visual C++ 2013 Redistributable (x64)" -InstallExecutable "Microsoft Visual C++ 2013 Redistributable (x64)\vcredist_x64.exe" -InstallArguments "/Q" 165 | Install-Application -ComputerName (Get-LabMachine -ComputerName 'CTX-XA01') -DirectoryPath "$labSources\SoftwarePackages\Frameworks\Microsoft Visual C++ 2015 Redistributable (x64)" -InstallExecutable "Microsoft Visual C++ 2015 Redistributable (x64)\vc_redist.x64.exe" -InstallArguments "/Q" 166 | Install-Application -ComputerName (Get-LabMachine -ComputerName 'CTX-XA01') -DirectoryPath "$labSources\SoftwarePackages\Frameworks\Microsoft Visual C++ 2015 Redistributable (x86)" -InstallExecutable "Microsoft Visual C++ 2015 Redistributable (x86)\vc_redist.x86.exe" -InstallArguments "/Q" 167 | Restart-LabVM -ComputerName 'CTX-XA01' -Wait 168 | 169 | Invoke-LabCommand -ActivityName 'Create SQL Databases' -ComputerName $CitrixHost -ScriptBlock { 170 | New-XDDatabase -AllDefaultDatabases -DatabaseServer 'CTX-AP01' -SiteName Default 171 | } 172 | 173 | Invoke-LabCommand -ActivityName 'Create XenDesktop Site' -ComputerName $CitrixHost -ScriptBlock { 174 | New-XDSite -AllDefaultDatabases -DatabaseServer 'CTX-AP01' -SiteName Default 175 | } 176 | 177 | Invoke-LabCommand -ActivityName 'Configure Licensing Server' -ComputerName $CitrixHost -ScriptBlock { 178 | Set-XDLicensing -LicenseServerAddress 'CTX-AP01' -LicenseServerPort 27000 179 | } 180 | 181 | $disk = Mount-LabIsoImage -ComputerName 'CTX-XA01' -ISOPath (Get-LabIsoImageDefinition | Where-Object { $_.Name -eq 'XenDesktop7.15'}).Path -PassThru -SupressOutput 182 | Install-Application -ComputerName (Get-LabMachine -ComputerName 'CTX-XA01') -NoCopy -DirectoryPath "$($disk.DriveLetter)\x64\XenDesktop Setup" -InstallExecutable "XenDesktopVDASetup.exe" -InstallArguments '/quiet /noreboot /components vda,plugins /controllers "CTX-AP01.citrixlab.local" /enable_hdx_ports /enable_remote_assistance' 183 | #Installation is not completed at this point, server requires a reboot and re-execution of the install to complete. Need to pull install apart a bit more to remove this "unmanaged" restart requirement. 184 | Restart-LabVM -ComputerName 'CTX-XA01' -Wait 185 | Install-Application -ComputerName (Get-LabMachine -ComputerName 'CTX-XA01') -NoCopy -DirectoryPath "$($disk.DriveLetter)\x64\XenDesktop Setup" -InstallExecutable "XenDesktopVDASetup.exe" -InstallArguments '/quiet /noreboot /components vda,plugins /controllers "CTX-AP01.citrixlab.local" /enable_hdx_ports /enable_remote_assistance' 186 | 187 | 188 | 189 | # $disk = Mount-LabIsoImage -ComputerName 'CTX-XD01' -ISOPath (Get-LabIsoImageDefinition | Where-Object { $_.Name -eq 'XenDesktop7.15'}).Path -PassThru -SupressOutput 190 | # $job=Install-LabSoftwarePackage -ComputerName 'CTX-XD01'-LocalPath "$($disk.DriveLetter)\x64\XenDesktop Setup\XenDesktopVDASetup.exe" -CommandLine '/quiet /noreboot /components vda,plugins /controllers ""CTX-AP01.citrixlab.local"" /enable_hdx_ports /enable_remote_assistance /remotepc' -AsJob -PassThru -ErrorAction Stop 191 | # $result = Wait-LWLabJob -Job $job -NoNewLine -ProgressIndicator 10 -PassThru -ErrorAction Stop 192 | 193 | Show-LabDeploymentSummary -Detailed 194 | 195 | $VerbosePreference = $oldverbose -------------------------------------------------------------------------------- /Citrix Build/readme.md: -------------------------------------------------------------------------------- 1 | These scripts are designed to deploy a Citrix XenApp (Windows Server) + optionally XenDesktop (Windows Desktop) infrastructure using AutomatedLab, similar to the functionality offered by the automated installation provided as part of the XenDesktop ISO File 2 | 3 | Prerequisites: 4 | 5 | - Installed version of Automated-Lab (Tested on v4.5.0) 6 | - A Server operating system image for an AL machine deployment (Tested with Server 2016) 7 | - A Server operating system image for an XenApp machine deployment (Tested with Server 2016) 8 | - (Optional) Desktop Operating System for XenDesktop Deployment (Tested with Windows 10) 9 | 10 | Initial intent of these scripts is to deploy the following roles: 11 | 12 | - Windows Domain Controller 13 | - Citrix StoreFront + Delivery Controller + Studio + SQL 14 | - Static (non-MCS / PVS) Server image - using Citrix VDA 15 | - Static (non-MCS / PVS) Desktop image - using Citrix VDA 16 | - Utilise Citrix XenApp and XenDesktop optimization scripts to configure machines to support remote users 17 | 18 | Future capabilities: 19 | 20 | - Deployment of Machine Creation Services (MCS) XenApp (Server) and XenDesktop (Desktop) images 21 | - Deployment of Provisioning Services (PVS) XenApp (Server) and XenDesktop (Desktop) images 22 | - Integration with Citrix NetScaler Virtual Machine to provide complete end-to-end solution (requires some additional work to support non-windows machines) 23 | 24 | These scripts are a work in progress, there are some assumptions made resulting in some lack of error checking. Additional enhancements are in the pipeline, and are managed as enhancement requests within GitHub. 25 | -------------------------------------------------------------------------------- /HSD Build/HSD Build - VDI.ps1: -------------------------------------------------------------------------------- 1 | 2 | <# 3 | .SYNOPSIS 4 | This script is desgined to deploy a VDI-based Remote Desktop Solution 5 | .DESCRIPTION 6 | Windows Domain Controller, holding the RDS-LICENSING tole 7 | A Windows Server holding all other RDS roles 8 | A Nested VM acting as the virtualisation host server - BOO - See note below. 9 | No RDS Gateway Role in use 10 | 11 | .EXAMPLE 12 | PS C:\> 13 | Explanation of what the example does 14 | .INPUTS 15 | Inputs (if any) 16 | .OUTPUTS 17 | Output (if any) 18 | .NOTES 19 | 20 | BAH: Windows does NOT currently support nested virtualisation for the virtualisation host portion of an RDS VDI deployment, and also does not support Windows 10 21 | as a virtualisation host for RDS VDI. 22 | 23 | 26/12/17 - Will revisit this script when a spare virtualisation host becomes available for testing (or nested virtualisation works for RDS). 24 | 25 | #> 26 | 27 | $labName = 'VDILab' 28 | $labSources = Get-LabSourcesLocation 29 | 30 | New-LabDefinition -Name $LabName -DefaultVirtualizationEngine HyperV -VmPath "C:\Hyper-V\Automation-Lab" 31 | Add-LabVirtualNetworkDefinition -Name $LabName -AddressSpace 192.168.60.0/24 32 | 33 | $PSDefaultParameterValues = @{ 34 | 'Add-LabMachineDefinition:Network' = $labName 35 | 'Add-LabMachineDefinition:ToolsPath'= "$labSources\Tools" 36 | 'Add-LabMachineDefinition:DnsServer1' = '192.168.60.10' 37 | 'Add-LabMachineDefinition:OperatingSystem' = 'Windows Server 2016 SERVERSTANDARD' 38 | } 39 | 40 | 41 | Add-LabMachineDefinition -Name VDI-DC01 -Memory 2GB -Roles RootDC -IPAddress '192.168.60.10' -DomainName 'vdilab.local' 42 | #Add a host that will run all the roles. Since we want to demonstrate both published desktops and apps, install Office 43 | Add-LabMachineDefinition -Name VDI-HSD1 -Memory 4GB -IPAddress '192.168.60.20' -DomainName 'vdilab.local' 44 | #Add a hoist for the nested virtualisation 45 | Add-LabMachineDefinition -Name VDI-HV01 -Memory 4GB -IPAddress '192.168.60.30' -DomainName 'vdilab.local' 46 | #Add a non-domained joined machine which will become the master image for guest virtual machines 47 | Add-LabMachineDefinition -Name VDI-VDI-Master -Memory 2GB -IPAddress '192.168.60.100' -OperatingSystem 'Windows 10 Enterprise' -OperatingSystemVersion '10.0.14393.0' 48 | 49 | Install-Lab 50 | 51 | #Get the OS version of the host, we need Windows 2016 or Windows 10 to enable nested virtualisation 52 | $hostOsVersion = [System.Version]((Get-CimInstance -ClassName Win32_OperatingSystem).Version) 53 | 54 | if ($hostOsVersion -lt [System.Version]'10.0') { 55 | Write-Verbose -Message "Host OS version is '$($hostOsVersion)' which is insufficient to run nested virtualisation, exiting" 56 | return 57 | } else { 58 | Write-Verbose -Message "Host OS version is '$($hostOsVersion)' which supports nested virtualisation, continuting" 59 | #Need to shut down the VM to enable virtualisation extensions 60 | Stop-LabVM -ComputerName 'VDI-HV01' -Wait 61 | #Enable Virtualisation Extensions on the Virtual Machine 62 | Set-VMProcessor -VMName 'VDI-HV01' -ExposeVirtualizationExtensions $true -EnableHostResourceProtection 63 | #Add a secondary NIC, which will be the one used by Guests, connected to the same lab virtual switch 64 | Add-VMNetworkAdapter -VMName 'VDI-HV01' -SwitchName $labName -Name 'Guest Access' 65 | #Enable MAC address spoofing on the guest access network adapter 66 | Get-VMNetworkAdapter -VMName 'VDI-HV01' -Name 'Guest Access' | Set-VMNetworkAdapter -MacAddressSpoofing On 67 | #Start the VM 68 | Start-LabVM -ComputerName 'VDI-HV01' -Wait 69 | #Install Hyper-V role with management tools 70 | Install-LabWindowsFeature -ComputerName 'VDI-HV01' -FeatureName 'Hyper-V' -IncludeAllSubFeature -IncludeManagementTools 71 | #Restart the VM to complete installation 72 | Restart-LabVM -ComputerName 'VDI-HV01' -Wait 73 | #Since Hyper-V install restarts the computer a second time, wait for 30 seconds for this to occur before continuing 74 | Start-Sleep -Seconds 30 75 | 76 | #Now Create the virtual switch the guests will use 77 | Invoke-LabCommand -ActivityName 'Configure Hyper-V' -ComputerName 'VDI-HV01' -ScriptBlock { 78 | Get-NetAdapter -Name 'Ethernet 2' | Rename-NetAdapter -NewName 'Guest Access' 79 | New-VMSwitch -Name 'Guest Access' -NetAdapterName 'Guest Access' -AllowManagementOS $false 80 | } 81 | 82 | #Now, prepare the VDI guest. 83 | <# 84 | Steps: 85 | Perform a sysprep on the machine 86 | Shut it Down 87 | Merge the differencing disk back into a master 88 | Copy the master disk into the Hyper-V host 89 | Use this image as a master inage for VDI 90 | #> 91 | 92 | Stop-LabVM -ComputerName 'VDI-VDI-MASTER' -Wait 93 | #Get the VHD atteched to the Desktp VM 94 | $DriveConfig = Get-VMHardDiskDrive -VMName 'VDI-VDI-Master' | Get-VHD 95 | #merge the existing parent and chiuld into a new standalone image 96 | Convert-VHD -Path $DriveConfig.Path -DestinationPath "$labSources\SoftwarePackages\VDI-MASTER.vhdx" -VHDType Dynamic 97 | Copy-LabFileItem -Path "$labSources\SoftwarePackages\VDI-MASTER.vhdx" -DestinationFolderPath 'C:\Hyper-V' -ComputerName 'VDI-HV01' 98 | 99 | #Test: Create a test VM and vlidate the disk copy 100 | # Invoke-LabCommand -ActivityName 'Create Guest Machine' -ComputerName 'VDI-HV01' -ScriptBlock { 101 | # New-VM -Name Win10VM -MemoryStartupBytes 2GB -BootDevice VHD -VHDPath 'C:\Hyper-V\VDI-MASTER.VHDX' -Path 'C:\Hyper-V' -Generation 2 -Switch 'Guest Access' 102 | 103 | # } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /HSD Build/HSDBuild - Multiple HSD No Apps.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | This is an example lab using AL that performs the following activites: 3 | 1. Creates a single DC and Multiple RDS Session Host lab 4 | 2. Uses AutomationLab to build the Lab Machines 5 | 3. Installs RemoteDesktop Services 6 | 4. Publishes the Full Desktop 7 | #> 8 | 9 | $oldverbose = $VerbosePreference 10 | $VerbosePreference = 'continue' 11 | 12 | #Import the RDS mode, assumed to be in the same directory as this script 13 | Import-Module .\InstallRDS.psm1 14 | 15 | $labName = 'HSDMultiHost' 16 | $labSources = Get-LabSourcesLocation 17 | 18 | New-LabDefinition -Name $LabName -DefaultVirtualizationEngine HyperV -VmPath "C:\Hyper-V\Automation-Lab" 19 | Add-LabVirtualNetworkDefinition -Name $LabName -AddressSpace 192.168.50.0/24 20 | 21 | $PSDefaultParameterValues = @{ 22 | 'Add-LabMachineDefinition:Network' = $labName 23 | 'Add-LabMachineDefinition:ToolsPath'= "$labSources\Tools" 24 | 'Add-LabMachineDefinition:DomainName' = 'hsdminlab.local' 25 | 'Add-LabMachineDefinition:DnsServer1' = '192.168.50.10' 26 | 'Add-LabMachineDefinition:OperatingSystem' = 'Windows Server 2016 SERVERSTANDARD' 27 | } 28 | 29 | Add-LabMachineDefinition -Name MUL-DC01 -Memory 2GB -Roles RootDC -IPAddress '192.168.50.10' 30 | #Add a host that will run all the roles. 31 | Add-LabMachineDefinition -Name MUL-HSD1 -Memory 4GB -IPAddress '192.168.50.20' 32 | Add-LabMachineDefinition -Name MUL-HSD2 -Memory 4GB -IPAddress '192.168.50.21' 33 | Add-LabMachineDefinition -Name MUL-HSD3 -Memory 4GB -IPAddress '192.168.50.22' 34 | Add-LabMachineDefinition -Name MUL-HSD4 -Memory 4GB -IPAddress '192.168.50.23' 35 | 36 | #Do the AL Installation goodness 37 | Install-Lab 38 | 39 | $SessionHostList = @() 40 | $SessionHostList += (Get-LabMachine -ComputerName 'MUL-HSD1') 41 | $SessionHostList += (Get-LabMachine -ComputerName 'MUL-HSD2') 42 | $SessionHostList += (Get-LabMachine -ComputerName 'MUL-HSD3') 43 | $SessionHostList += (Get-LabMachine -ComputerName 'MUL-HSD4') 44 | 45 | #Install Remote Desktop Services in Session Deployment Mode 46 | Install-RDS -ConnectionBroker (Get-LabMachine -ComputerName 'MUL-HSD1') -WebAccessServer (Get-LabMachine -ComputerName 'MUL-HSD1') -SessionHost $SessionHostList -LicensingServer (Get-LabMachine -Role 'RootDC') -SessionDeployment 47 | 48 | #Republish the Full Desktop into the web access site so at least there is something to test (defaults to off) 49 | Publish-RDSDesktop -SessionHost (Get-LabMachine -ComputerName 'MUL-HSD1') 50 | 51 | Show-LabDeploymentSummary -Detailed 52 | 53 | $VerbosePreference = $oldverbose 54 | -------------------------------------------------------------------------------- /HSD Build/HSDBuild - Multiple HSD with Apps.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | This is an example lab using AL that performs the following activites: 3 | 1. Creates a single DC and Multiple RDS Session Host lab 4 | 2. Uses AutomationLab to build the Lab Machines 5 | 3. Installs RemoteDesktop Services 6 | 4. Publishes the Full Desktop 7 | #> 8 | 9 | $oldverbose = $VerbosePreference 10 | $VerbosePreference = 'silentlycontinue' 11 | 12 | #Import the RDS mode, assumed to be in the same directory as this script 13 | Import-Module .\InstallRDS.psm1 14 | 15 | $labName = 'HSDMultiHost' 16 | $labSources = Get-LabSourcesLocation 17 | 18 | New-LabDefinition -Name $LabName -DefaultVirtualizationEngine HyperV -VmPath "C:\Hyper-V\Automation-Lab" 19 | Add-LabVirtualNetworkDefinition -Name $LabName -AddressSpace 192.168.50.0/24 20 | 21 | $PSDefaultParameterValues = @{ 22 | 'Add-LabMachineDefinition:Network' = $labName 23 | 'Add-LabMachineDefinition:ToolsPath'= "$labSources\Tools" 24 | 'Add-LabMachineDefinition:DomainName' = 'hsdminlab.local' 25 | 'Add-LabMachineDefinition:DnsServer1' = '192.168.50.10' 26 | 'Add-LabMachineDefinition:OperatingSystem' = 'Windows Server 2016 SERVERSTANDARD' 27 | } 28 | 29 | Add-LabMachineDefinition -Name MUL-DC01 -Memory 2GB -Roles RootDC -IPAddress '192.168.50.10' 30 | #Add a host that will run all the roles. 31 | Add-LabMachineDefinition -Name MUL-HSD1 -Memory 2GB -IPAddress '192.168.50.20' 32 | Add-LabMachineDefinition -Name MUL-HSD2 -Memory 2GB -IPAddress '192.168.50.21' 33 | Add-LabMachineDefinition -Name MUL-HSD3 -Memory 2GB -IPAddress '192.168.50.22' 34 | Add-LabMachineDefinition -Name MUL-HSD4 -Memory 2GB -IPAddress '192.168.50.23' 35 | 36 | #Do the AL Installation goodness 37 | Install-Lab 38 | 39 | $SessionHostList = @() 40 | $SessionHostList += (Get-LabMachine -ComputerName 'MUL-HSD1') 41 | $SessionHostList += (Get-LabMachine -ComputerName 'MUL-HSD2') 42 | $SessionHostList += (Get-LabMachine -ComputerName 'MUL-HSD3') 43 | $SessionHostList += (Get-LabMachine -ComputerName 'MUL-HSD4') 44 | 45 | #Install Remote Desktop Services in Session Deployment Mode 46 | Install-RDS -ConnectionBroker (Get-LabMachine -ComputerName 'MUL-HSD1') -WebAccessServer (Get-LabMachine -ComputerName 'MUL-HSD1') -SessionHost $SessionHostList -LicensingServer (Get-LabMachine -Role 'RootDC') -SessionDeployment 47 | 48 | Install-RDSApplication -SessionHost $SessionHostList -URL 'https://ftp.mozilla.org/pub/firefox/releases/57.0/win64/en-US/Firefox%20Setup%2057.0.exe' -InstallArguments '-ms' 49 | Publish-RDSApplication -Alias 'FireFox' -DisplayName 'FireFox' -FilePath "C:\Program Files\Mozilla Firefox\firefox.exe" -ConnectionBroker (Get-LabMachine -ComputerName 'MUL-HSD1') 50 | 51 | Install-RDSApplication -SessionHost $SessionHostList -DirectoryPath "$labSources\SoftwarePackages\Microsoft Office Pro Plus 2016" -InstallExecutable "Microsoft Office Pro Plus 2016\Setup.exe" -InstallArguments "/adminfile Office_R2.MSP" 52 | Publish-RDSApplication -Alias 'Microsoft Word' -DisplayName 'Microsoft Word' -FilePath "C:\Program Files (x86)\Microsoft Office\Office16\WINWORD.EXE" -ConnectionBroker (Get-LabMachine -ComputerName 'MUL-HSD1') 53 | Publish-RDSApplication -Alias 'Microsoft Excel' -DisplayName 'Microsoft Excel' -FilePath "C:\Program Files (x86)\Microsoft Office\Office16\EXCEL.EXE" -ConnectionBroker (Get-LabMachine -ComputerName 'MUL-HSD1') 54 | 55 | #Republish the Full Desktop into the web access site (turns off once apps are published) 56 | Publish-RDSDesktop -ConnectionBroker (Get-LabMachine -ComputerName 'MUL-HSD1') 57 | 58 | Show-LabDeploymentSummary -Detailed 59 | 60 | $VerbosePreference = $oldverbose 61 | -------------------------------------------------------------------------------- /HSD Build/HSDBuild - Single HSD Mutiple Apps.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | This is an example lab using AL that performs the folliwng activites: 3 | 1. Creates a single DC and multiple RDS Session Hosts 4 | 2. Uses AutomationLab to build the Lab Machines 5 | 3. Installs RemoteDesktop Services 6 | 4. Publishes the standard wordpad application 7 | 5. Installs Firefox via an internet download, and Publishes the application 8 | 6. Installs a VL edition of Office 2016 and Publishes Word and Excel 9 | 7. Publishes the Full Desktop RemoteApp 10 | 11 | Note: VL Editions of Office are required as non-VL editions immediately raise errors on Session Hosts regarding an unsupported configuration (licensing issue essentially) 12 | #> 13 | 14 | $oldverbose = $VerbosePreference 15 | $VerbosePreference = 'continue' 16 | 17 | #Import the RDS mode, assumed to be in the same directory as this script 18 | Import-Module .\InstallRDS.psm1 19 | 20 | $labName = 'HSDModularLab' 21 | $labSources = Get-LabSourcesLocation 22 | 23 | New-LabDefinition -Name $LabName -DefaultVirtualizationEngine HyperV -VmPath "C:\Hyper-V\Automation-Lab" 24 | Add-LabVirtualNetworkDefinition -Name $LabName -AddressSpace 192.168.70.0/24 25 | 26 | $PSDefaultParameterValues = @{ 27 | 'Add-LabMachineDefinition:Network' = $labName 28 | 'Add-LabMachineDefinition:ToolsPath'= "$labSources\Tools" 29 | 'Add-LabMachineDefinition:DomainName' = 'hsdlab.local' 30 | 'Add-LabMachineDefinition:DnsServer1' = '192.168.70.10' 31 | 'Add-LabMachineDefinition:OperatingSystem' = 'Windows Server 2016 SERVERSTANDARD' 32 | } 33 | 34 | Add-LabMachineDefinition -Name MOD-DC01 -Memory 2GB -Roles RootDC -IPAddress '192.168.70.10' 35 | #Add a host that will run all the roles. Since we want to demonstrate both published desktops and apps, install Office 36 | Add-LabMachineDefinition -Name MOD-HSD1 -Memory 4GB -IPAddress '192.168.70.20' 37 | 38 | #Do the AL Installation goodness 39 | Install-Lab 40 | 41 | #Install Remote Desktop Services in Session Deployment Mode 42 | Install-RDS -ConnectionBroker (Get-LabMachine -ComputerName 'MOD-HSD1') -WebAccessServer (Get-LabMachine -ComputerName 'MOD-HSD1') -SessionHost (Get-LabMachine -ComputerName 'MOD-HSD1') -LicensingServer (Get-LabMachine -Role 'RootDC') -SessionDeployment 43 | 44 | #Publish the Wordpad executable built into all Servers 45 | Publish-RDSApplication -Alias 'WordPad' -DisplayName 'WordPad' -FilePath "C:\Program Files\Windows NT\Accessories\wordpad.exe" -ConnectionBroker (Get-LabMachine -ComputerName 'MOD-HSD1') 46 | 47 | #Install Firefox onto the Session Server, and publish the firefox app 48 | Install-RDSApplication -SessionHost (Get-LabMachine -ComputerName 'MOD-HSD1') -URL 'https://ftp.mozilla.org/pub/firefox/releases/57.0/win64/en-US/Firefox%20Setup%2057.0.exe' -InstallArguments '-ms' 49 | Publish-RDSApplication -Alias 'FireFox' -DisplayName 'FireFox' -FilePath "C:\Program Files\Mozilla Firefox\firefox.exe" -ConnectionBroker (Get-LabMachine -ComputerName 'MOD-HSD1') 50 | 51 | #Install VL Edition of Office Professional Plus 2016 onto the Server, and Publish Word + Excel 52 | Install-RDSApplication -SessionHost (Get-LabMachine -ComputerName 'MOD-HSD1') -DirectoryPath "$labSources\SoftwarePackages\Microsoft Office Pro Plus 2016" -InstallExecutable "Microsoft Office Pro Plus 2016\Setup.exe" -InstallArguments "/adminfile Office_R2.MSP" 53 | Publish-RDSApplication -Alias 'Microsoft Word' -DisplayName 'Microsoft Word' -FilePath "C:\Program Files (x86)\Microsoft Office\Office16\WINWORD.EXE" -ConnectionBroker (Get-LabMachine -ComputerName 'MOD-HSD1') 54 | Publish-RDSApplication -Alias 'Microsoft Excel' -DisplayName 'Microsoft Excel' -FilePath "C:\Program Files (x86)\Microsoft Office\Office16\EXCEL.EXE" -ConnectionBroker (Get-LabMachine -ComputerName 'MOD-HSD1') 55 | 56 | #Republish the Full Desktop into the web access site (defaults to off) 57 | Publish-RDSDesktop -SessionHost (Get-LabMachine -ComputerName 'MOD-HSD1') 58 | 59 | Show-LabDeploymentSummary -Detailed 60 | 61 | $VerbosePreference = $oldverbose 62 | -------------------------------------------------------------------------------- /HSD Build/HSDBuild - Single HSD No Apps.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | This is an example lab using AL that performs the folliwng activites: 3 | 1. Creates a single DC and RDS Session Host 4 | 2. Uses AutomationLab to build the Lab Machines 5 | 3. Installs RemoteDesktop Services 6 | 4. Publishes the Full Desktop 7 | #> 8 | 9 | $oldverbose = $VerbosePreference 10 | $VerbosePreference = 'continue' 11 | 12 | #Import the RDS mode, assumed to be in the same directory as this script 13 | Import-Module .\InstallRDS.psm1 14 | 15 | $labName = 'HSDMinimal' 16 | $labSources = Get-LabSourcesLocation 17 | 18 | New-LabDefinition -Name $LabName -DefaultVirtualizationEngine HyperV -VmPath "C:\Hyper-V\Automation-Lab" 19 | Add-LabVirtualNetworkDefinition -Name $LabName -AddressSpace 192.168.60.0/24 20 | 21 | $PSDefaultParameterValues = @{ 22 | 'Add-LabMachineDefinition:Network' = $labName 23 | 'Add-LabMachineDefinition:ToolsPath'= "$labSources\Tools" 24 | 'Add-LabMachineDefinition:DomainName' = 'hsdminlab.local' 25 | 'Add-LabMachineDefinition:DnsServer1' = '192.168.60.10' 26 | 'Add-LabMachineDefinition:OperatingSystem' = 'Windows Server 2016 SERVERSTANDARD' 27 | } 28 | 29 | Add-LabMachineDefinition -Name MIN-DC01 -Memory 2GB -Roles RootDC -IPAddress '192.168.60.10' 30 | #Add a host that will run all the roles. 31 | Add-LabMachineDefinition -Name MIN-HSD1 -Memory 4GB -IPAddress '192.168.60.20' 32 | 33 | #Do the AL Installation goodness 34 | Install-Lab 35 | 36 | #Install Remote Desktop Services in Session Deployment Mode 37 | Install-RDS -ConnectionBroker (Get-LabMachine -ComputerName 'MIN-HSD1') -WebAccessServer (Get-LabMachine -ComputerName 'MIN-HSD1') -SessionHost (Get-LabMachine -ComputerName 'MIN-HSD1') -LicensingServer (Get-LabMachine -Role 'RootDC') -SessionDeployment 38 | 39 | #Republish the Full Desktop into the web access site so at least there is something to test (defaults to off) 40 | Publish-RDSDesktop -SessionHost (Get-LabMachine -ComputerName 'MIN-HSD1') 41 | 42 | Show-LabDeploymentSummary -Detailed 43 | 44 | $VerbosePreference = $oldverbose 45 | -------------------------------------------------------------------------------- /HSD Build/InstallRDS.psm1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | This module contains the Remote Desktop Services Fucntions to Install a funtioning RDS Lab in concert with AutomatedLab 4 | .DESCRIPTION 5 | Author: Glenn Corbett (@GlennJC) 6 | Version 1.0.20171227.1256 7 | .NOTES 8 | This is the initial version. 9 | TODO: 10 | Additional Error checking for all calls 11 | Additional Range Checking for passed in values 12 | Additional Error Checking for file existence for Install-RDSApplication 13 | Version History: 14 | 1.0.20171226.1938 - Initial Version 15 | 1.0.20171227.1256 - Updated Install-RDSApplication to better support multiple hosts + modified code to use equivalent AL cmdlets which frankly worked better 16 | - Updated function definition for Publish-RDDesktop to -ConnectionBroker rather than -SessionHost which is more reflective 17 | of the host you need to execute the action against 18 | 19 | #> 20 | 21 | Function Install-RDS { 22 | 23 | [cmdletbinding(DefaultParameterSetName='HSDDeployment')] 24 | 25 | param ( 26 | 27 | # Parameter help description 28 | [Parameter(Mandatory)] 29 | [AutomatedLab.Machine]$ConnectionBroker, 30 | 31 | [Parameter(Mandatory)] 32 | [AutomatedLab.Machine]$WebAccessServer, 33 | 34 | [Parameter(Mandatory)] 35 | [AutomatedLab.Machine]$LicensingServer, 36 | 37 | [string]$CollectionName='Pool', 38 | 39 | [Parameter(ParameterSetName='HSDDeployment')] 40 | [switch]$SessionDeployment, 41 | 42 | [Parameter(Mandatory, ParameterSetName='HSDDeployment')] 43 | [AutomatedLab.Machine[]]$SessionHost, 44 | 45 | [Parameter(ParameterSetName='VDIDeployment')] 46 | [switch]$VDIDeployment, 47 | 48 | #Name of the host server that will host the VDI images 49 | [Parameter(Mandatory, ParameterSetName='VDIDeployment')] 50 | [string]$VirtualizationHost, 51 | 52 | [Parameter(Mandatory, ParameterSetName='VDIDeployment')] 53 | [string]$VDITemplateName, 54 | 55 | #Limit the number of VDI Instances between 1 and 20 56 | [ValidateRange(1,20)] 57 | [Parameter(ParameterSetName='VDIDeployment')] 58 | [int]$MaxInstances=1 59 | ) 60 | 61 | #RDS Needs FQDNs to access lab resources from the host. 62 | #Add fully qualified host names to the hosts file (otherwise apps launched via RemoteApp from the host will fail since it launches using the FQDN for the Remote Desktop Client Session) 63 | #NOTE: This issue has been fixed in AutomatedLab.psm1 as at 23/12/17 (#206), can be removed once committed in next public release of AL. 64 | $machines = Get-LabMachine 65 | $hostFileAddedEntries = 0 66 | $labname = (Get-Lab).Name 67 | 68 | #Modified code from AutomatedLab.psm1 to add host entries, modified to add FQDN names (otherwise apps launched via RemoteApp from the host will fail) 69 | #entries are added to the existing section created by AL, so will be removed when the Remove-Lab command is executed. 70 | Foreach ($machine in $machines) 71 | { 72 | if ($machine.Hosttype -eq 'HyperV' -and $machine.NetworkAdapters[0].Ipv4Address) 73 | { 74 | $hostFileAddedEntries += Add-HostEntry -HostName $machine.FQDN -IpAddress $machine.IpV4Address -Section $labname 75 | } 76 | } 77 | 78 | if ($hostFileAddedEntries) 79 | { 80 | Write-ScreenInfo -Message "$hostFileAddedEntries records have been added to the hosts using machine FQDNs. Clean them up using 'Remove-Lab' or manually if needed" -Type Warning 81 | } 82 | 83 | #Find the Root Domain Controller role, we will use this to execute the commands against the RDConnection Broker Server. We are unable to perform a number of commands directly on the Connection Broker 84 | # itself (such as the initial install) as the connection broker is restarted during installation 85 | $RootDC = Get-LabMachine -Role RootDC 86 | 87 | switch ($PSCmdlet.ParameterSetName) { 88 | 'HSDDeployment' { 89 | 90 | #We need to use FQDN host names for RD activities, so make up an FQDN collection for the passed in session host(s) 91 | $SessionHostGroup = @() 92 | foreach ($SingleHost in $SessionHost) { 93 | $SessionHostGroup += $SingleHost.FQDN 94 | } 95 | 96 | Invoke-LabCommand -ActivityName 'Install Remote Desktop Services in HSD Deployment Mode' -ComputerName $RootDC -ScriptBlock { 97 | 98 | param( 99 | [Parameter(Mandatory)] 100 | [string]$ConnectionBrokerFQDN, 101 | 102 | [Parameter(Mandatory)] 103 | [string]$WebAccessServerFQDN, 104 | 105 | [Parameter(Mandatory)] 106 | [string[]]$SessionHostFQDN 107 | ) 108 | 109 | Import-Module RemoteDesktop 110 | New-RDSessionDeployment -ConnectionBroker $ConnectionBrokerFQDN -WebAccessServer $WebAccessServerFQDN -SessionHost $SessionHostFQDN 111 | 112 | } -ArgumentList $ConnectionBroker.FQDN, $WebAccessServer.FQDN, $SessionHostGroup 113 | 114 | #Wait for the Connection Broker Service to become available, as New-RDSessionDeployment does a machine restart during the activity 115 | Write-ScreenInfo -Message "Waiting for Connection Broker on '$ConnectionBroker' to become available " -NoNewline 116 | 117 | $totalretries = 20 118 | $retries=0 119 | 120 | do { 121 | $result = Invoke-LabCommand -ComputerName $RootDC -ScriptBlock { 122 | 123 | param( 124 | [Parameter(Mandatory)] 125 | [string]$ConnectionBrokerFQDN 126 | ) 127 | 128 | Get-RDServer -ConnectionBroker $ConnectionBrokerFQDN -ErrorAction SilentlyContinue 129 | } -ArgumentList $ConnectionBroker.FQDN -PassThru -NoDisplay 130 | 131 | $retries++ 132 | Write-ScreenInfo '.' -NoNewLine 133 | Start-Sleep -Seconds 15 134 | 135 | } until (($result) -or ($retries -ge $totalretries)) 136 | 137 | Write-ScreenInfo 'Done' 138 | 139 | Invoke-LabCommand -ActivityName 'Configure Remote Desktop Services' -ComputerName $RootDC -ScriptBlock { 140 | 141 | param( 142 | [Parameter(Mandatory)] 143 | [string]$ConnectionBrokerFQDN, 144 | 145 | [Parameter(Mandatory)] 146 | [string]$LicensingServerFQDN, 147 | 148 | [Parameter(Mandatory)] 149 | [string[]]$SessionHostFQDN, 150 | 151 | [Parameter(Mandatory)] 152 | [string]$CollectionName 153 | ) 154 | 155 | Import-Module RemoteDesktop 156 | Import-Module ActiveDirectory 157 | 158 | Add-RDServer -Server $LicensingServerFQDN -Role RDS-LICENSING -ConnectionBroker $ConnectionBrokerFQDN 159 | Set-RDLicenseConfiguration -LicenseServer $LicensingServerFQDN -Mode PerUser -ConnectionBroker $ConnectionBrokerFQDN -Force 160 | #Need to add the License server to the 'Terminal Server License Servers' group in AD, we need to use the non-fqdn version of the name 161 | $LicensingServerHostName= $(Get-ADComputer -LDAPFilter "(dNSHostName=$LicensingServerFQDN)").Name 162 | 163 | if ($LicensingServerHostName) { 164 | Add-ADGroupMember 'Terminal Server License Servers' "$LicensingServerHostName`$" 165 | } 166 | else { 167 | Write-Error "Error locating dnsHostName for '$LicensingServerFQDN', server will need to be manually added to 'Terminal Server License Servers' group" 168 | } 169 | 170 | #create a new session collection, using the passed in single or multiple session hosts 171 | New-RDSessionCollection -CollectionName $CollectionName -SessionHost $SessionHostFQDN -ConnectionBroker $ConnectionBrokerFQDN -PooledUnmanaged 172 | 173 | } -ArgumentList $ConnectionBroker.FQDN, $LicensingServer.FQDN, $SessionHostGroup, $CollectionName 174 | 175 | } #switch HSDDeployment 176 | 177 | 'VDIDeployment' { 178 | Write-ScreenInfo 'VDI Deployment Scenario Not Implemented Yet' 179 | } #switch VDI Deployment 180 | 181 | } 182 | 183 | } 184 | 185 | function Install-RDSApplication { 186 | 187 | param ( 188 | 189 | #Session hosts to install the application on 190 | [Parameter(Mandatory)] 191 | [AutomatedLab.Machine[]]$SessionHost, 192 | 193 | #URL for the application to be downloaded 194 | [Parameter(ParameterSetName='ByURL')] 195 | [string]$URL, 196 | 197 | #ISO Path for the installation ISO 198 | [Parameter(ParameterSetName='ByISO')] 199 | [string]$ISOPath, 200 | 201 | #Folder where existing installation files are located 202 | [Parameter(ParameterSetName='ByPath')] 203 | [string]$DirectoryPath, 204 | 205 | #Path relative to source media where installation executable is located. If a URL was provided, it is assumed the InstallExecutable is the last segment in the URL name 206 | [parameter(Mandatory, ParameterSetName='ByISO')] 207 | [parameter(Mandatory, ParameterSetName='ByPath')] 208 | [ValidateNotNullOrEmpty()] 209 | [string]$InstallExecutable, 210 | 211 | #Required arguments for the installation 212 | [parameter(Mandatory)] 213 | [ValidateNotNullOrEmpty()] 214 | [string]$InstallArguments 215 | ) 216 | 217 | switch ($PSCmdlet.ParameterSetName) { 218 | 'ByURL' { 219 | #We were passed a URL of the application to install, download if necessary 220 | $downloadTargetFolder = Join-Path -Path $labSources -ChildPath SoftwarePackages 221 | $internalUri = New-Object System.Uri($URL) 222 | Get-LabInternetFile -Uri $internalUri -Path $downloadTargetFolder -ErrorAction Stop 223 | $DownloadedFileName = $internalUri.Segments[$internalUri.Segments.Count-1] 224 | Write-ScreenInfo 'Copying source files to Target Servers' -TaskStart 225 | Copy-LabFileItem -Path (Join-Path -Path $downloadTargetFolder -ChildPath $DownloadedFileName) -DestinationFolderPath C:\Install -ComputerName $SessionHost 226 | Write-ScreenInfo 'Finished Copying Files' -TaskEnd 227 | 228 | $job = Install-LabSoftwarePackage -ComputerName $SessionHost -LocalPath "C:\Install\$DownloadedFileName" -CommandLine $InstallArguments -AsJob -PassThru -ErrorAction Stop 229 | $result = Wait-LWLabJob -Job $job -NoNewLine -ProgressIndicator 10 -PassThru -ErrorAction Stop 230 | } 231 | 'ByPath' { 232 | Write-ScreenInfo 'Copying source directories to Target Servers' -TaskStart 233 | Copy-LabFileItem -Path $DirectoryPath -DestinationFolderPath 'C:\Install' -ComputerName $SessionHost -Recurse 234 | Write-ScreenInfo 'Finished Copying Files' -TaskEnd 235 | $job = Install-LabSoftwarePackage -ComputerName $SessionHost -LocalPath "C:\Install\$InstallExecutable" -CommandLine $InstallArguments -AsJob -PassThru -ErrorAction Stop 236 | $result = Wait-LWLabJob -Job $job -NoNewLine -ProgressIndicator 10 -PassThru -ErrorAction Stop 237 | } 238 | 'ByISO' { 239 | Write-ScreenInfo 'Mounting ISO on target servers' -TaskStart 240 | $disk = Mount-LabIsoImage -ComputerName $SessionHost -IsoPath $ISOPath -PassThru -SupressOutput 241 | Write-ScreenInfo 'Finished' -TaskEnd 242 | 243 | $job = Install-LabSoftwarePackage -ComputerName $SessionHost -LocalPath "$($disk.DriveLetter)\$InstallExecutable" -CommandLine $InstallArguments -AsJob -PassThru -ErrorAction Stop 244 | $result = Wait-LWLabJob -Job $job -NoNewLine -ProgressIndicator 10 -PassThru -ErrorAction Stop 245 | Dismount-LabIsoImage -ComputerName $SessionHost -SupressOutput 246 | 247 | } 248 | } 249 | 250 | } 251 | 252 | function Publish-RDSApplication { 253 | 254 | param ( 255 | 256 | [Parameter(Mandatory)] 257 | [AutomatedLab.Machine]$ConnectionBroker, 258 | 259 | [string]$CollectionName='Pool', 260 | 261 | [Parameter(Mandatory)] 262 | [string]$Alias, 263 | 264 | [Parameter(Mandatory)] 265 | [string]$DisplayName, 266 | 267 | [Parameter(Mandatory)] 268 | [string]$FilePath 269 | ) 270 | 271 | 272 | Invoke-LabCommand -ActivityName "Publish '$Alias' to Collection '$CollectionName'" -ComputerName $ConnectionBroker -ScriptBlock { 273 | param ( 274 | 275 | [Parameter(Mandatory)] 276 | [string]$ConnectionBroker, 277 | 278 | [Parameter(Mandatory)] 279 | [string]$CollectionName, 280 | 281 | [Parameter(Mandatory)] 282 | [string]$Alias, 283 | 284 | [Parameter(Mandatory)] 285 | [string]$DisplayName, 286 | 287 | [Parameter(Mandatory)] 288 | [string]$FilePath 289 | ) 290 | 291 | New-RDRemoteapp -Alias $Alias -DisplayName $DisplayName -FilePath $FilePath -ShowInWebAccess 1 -CollectionName $CollectionName -ConnectionBroker $ConnectionBroker 292 | 293 | } -ArgumentList $ConnectionBroker.FQDN, $CollectionName, $Alias, $DisplayName, $FilePath 294 | 295 | } 296 | 297 | function Publish-RDSDesktop { 298 | 299 | param ( 300 | 301 | [Parameter(Mandatory)] 302 | [AutomatedLab.Machine]$ConnectionBroker, 303 | 304 | [string]$CollectionName='Pool' 305 | ) 306 | 307 | #This will run on each of the session hosts and re-enable the Full Desktop RemoteApp 308 | Invoke-LabCommand -ActivityName 'Republish Full Desktop' -ComputerName $ConnectionBroker -ScriptBlock { 309 | 310 | param( 311 | [Parameter(Mandatory)] 312 | [string]$CollectionName 313 | ) 314 | 315 | #Registry Keys for Collections are based on the first 16 characters of the Collection Name 316 | If ($CollectionName.Length -gt 16) { 317 | $RegistryCollName = $CollectionName.Substring(0,16) 318 | } 319 | else { 320 | $RegistryCollName = $CollectionName 321 | } 322 | 323 | Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\CentralPublishedResources\PublishedFarms\$RegistryCollName\RemoteDesktops\$RegistryCollName" -Name 'Name' -Value 'Full Desktop' 324 | Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\CentralPublishedResources\PublishedFarms\$RegistryCollName\RemoteDesktops\$RegistryCollName" -Name 'ShowInPortal' -Value 1 325 | 326 | } -ArgumentList $CollectionName 327 | 328 | } 329 | 330 | Export-ModuleMember -Function Install-RDS 331 | Export-ModuleMember -Function Install-RDSApplication 332 | Export-ModuleMember -Function Publish-RDSApplication 333 | Export-ModuleMember -Function Publish-RDSDesktop 334 | -------------------------------------------------------------------------------- /HSD Build/readme.md: -------------------------------------------------------------------------------- 1 | These scripts are designed to deploy a Hosted Shared Desktop (HSD) aka Server Based Computing (SBC) using AutomatedLab, similar to the functionality offered by the Server Manager "Remote Desktop Services" wizard. 2 | 3 | Future intent is to expand these scripts to support deploying Citrix XenDesktop (7.14 or better is the target) ontop of the initial AL Deployed Lab. 4 | 5 | Prerequisites: 6 | 7 | - Installed version of Automated-Lab (Tested on v4.5.0) 8 | - A Server operating system image for an AL machine deployment (Tested with Server 2016) 9 | - (Optional) Desktop Operating System for VDI Deployment - see notes below 10 | 11 | Intent of these scripts is to deploy the following roles: 12 | 13 | - Windows Domain Controller 14 | - Remote Desktop Connection Broker 15 | - Remote Desktop Web Access Portal 16 | - Remote Desktop Session Host (HSD/SBC) 17 | - VDI Session Host - see notes below 18 | 19 | These scripts are a work in progress, there are some assumptions made resulting in some lack of error checking. Additional enhancements are in the pipeline, and are managed as enhancement requests within GitHub. 20 | 21 | Current Scripts: 22 | - **InstallRDS.psm1** - Powershell module containing the developed functions for managing an RDS install in concert with AutomatedLab 23 | 24 | - **HSDBuild - Single HSD No Apps.ps1** - Sample script to deploy a single DC + Session Host 25 | 26 | - **HSDBuild - Single HSD Mutiple Apps.ps1** - Sample script deploying a single DC + Session Host + Installing and publishing Firefox + Office 2016 27 | 28 | - **HSDBuild - Multiple HSD No Apps.ps1** - Sample script deploying a DC + 4 Server Session Host Lab 29 | 30 | Note: 31 | VDI development is currently (26.12.17) on hold due to some limitations: 32 | - Remote Desktop Services does not currently support nested (ie Hyper-V on Hyper-V) virtualisation for VDI Virtualisation Hosts 33 | - Remote Desktop Services does not currently support using Windows 10 for VDI Virtualisation hosts 34 | -------------------------------------------------------------------------------- /MDT Build/AL Custom Role/DownloadAdk.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory)] 3 | [string]$AdkDownloadPath 4 | ) 5 | 6 | $windowsAdkUrl = 'http://download.microsoft.com/download/3/1/E/31EC1AAF-3501-4BB4-B61C-8BD8A07B4E8A/adk/adksetup.exe' 7 | $adkSetup = Get-LabInternetFile -Uri $windowsAdkUrl -Path $labSources\SoftwarePackages -PassThru 8 | 9 | if (-not (Test-Path -Path $AdkDownloadPath)) 10 | { 11 | $p = Start-Process -FilePath $adkSetup.FullName -ArgumentList "/quiet /layout $AdkDownloadPath" -PassThru 12 | Write-ScreenInfo "Waiting for ADK to download files" -NoNewLine 13 | while (-not $p.HasExited) { 14 | Write-ScreenInfo '.' -NoNewLine 15 | Start-Sleep -Seconds 10 16 | } 17 | Write-ScreenInfo 'finished' 18 | } 19 | else 20 | { 21 | Write-ScreenInfo "ADK folder does already exist, skipping the download. Delete the folder '$AdkDownloadPath' if you want to download again." 22 | } -------------------------------------------------------------------------------- /MDT Build/AL Custom Role/HostInit.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [string]$DeploymentFolderLocation = 'C:\DeploymentShare', 3 | 4 | [string]$InstallUserID = 'MdtService', 5 | 6 | [string]$InstallPassword = 'Somepass1', 7 | 8 | [Parameter(Mandatory)] 9 | [string]$ComputerName, 10 | 11 | [string[]]$OperatingSystems, 12 | 13 | [ValidateSet('True','False')] 14 | [string]$CreateTaskSequences = 'True', 15 | 16 | [string]$AdkDownloadPath = "$labSources\SoftwarePackages\ADK" 17 | ) 18 | 19 | $script = Get-Command -Name $PSScriptRoot\DownloadAdk.ps1 20 | $param = Sync-Parameter -Command $script -Parameters $PSBoundParameters 21 | & $PSScriptRoot\DownloadAdk.ps1 @param 22 | 23 | $script = Get-Command -Name $PSScriptRoot\InstallMDT.ps1 24 | $param = Sync-Parameter -Command $script -Parameters $PSBoundParameters 25 | & $PSScriptRoot\InstallMDT.ps1 @param -------------------------------------------------------------------------------- /MDT Build/AL Custom Role/MDTApplications.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | https://download.microsoft.com/download/e/1/c/e1c773de-73ba-494a-a5ba-f24906ecf088/vcredist_x86.exe 4 | Frameworks 5 | True 6 | True 7 | Microsoft Visual C++ 2005 Redistributable (x86) 8 | 9 | Microsoft 10 | 11 | vcredist_x86.exe /Q 12 | 13 | 14 | 15 | https://download.microsoft.com/download/d/4/1/d41aca8a-faa5-49a7-a5f2-ea0aa4587da0/vcredist_x64.exe 16 | Frameworks 17 | True 18 | True 19 | Microsoft Visual C++ 2005 Redistributable (x64) 20 | 21 | Microsoft 22 | 23 | vcredist_x64.exe /Q 24 | 25 | 26 | 27 | https://download.microsoft.com/download/d/d/9/dd9a82d0-52ef-40db-8dab-795376989c03/vcredist_x86.exe 28 | Frameworks 29 | True 30 | True 31 | Microsoft Visual C++ 2008 Redistributable (x86) 32 | 33 | Microsoft 34 | 35 | vcredist_x86.exe /Q 36 | 37 | 38 | 39 | https://download.microsoft.com/download/2/d/6/2d61c766-107b-409d-8fba-c39e61ca08e8/vcredist_x64.exe 40 | Frameworks 41 | True 42 | True 43 | Microsoft Visual C++ 2008 Redistributable (x64) 44 | 45 | Microsoft 46 | 47 | vcredist_x64.exe /Q 48 | 49 | 50 | 51 | https://download.microsoft.com/download/C/6/D/C6D0FD4E-9E53-4897-9B91-836EBA2AACD3/vcredist_x86.exe 52 | Frameworks 53 | True 54 | True 55 | Microsoft Visual C++ 2010 Redistributable (x86) 56 | 57 | Microsoft 58 | 59 | vcredist_x86.exe /Q 60 | 61 | 62 | 63 | https://download.microsoft.com/download/A/8/0/A80747C3-41BD-45DF-B505-E9710D2744E0/vcredist_x64.exe 64 | Frameworks 65 | True 66 | True 67 | Microsoft Visual C++ 2010 Redistributable (x64) 68 | 69 | Microsoft 70 | 71 | vcredist_x64.exe /Q 72 | 73 | 74 | 75 | https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x86.exe 76 | Frameworks 77 | True 78 | True 79 | Microsoft Visual C++ 2012 Redistributable (x86) 80 | 81 | Microsoft 82 | 83 | vcredist_x86.exe /Q 84 | 85 | 86 | 87 | https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe 88 | Frameworks 89 | True 90 | True 91 | Microsoft Visual C++ 2012 Redistributable (x64) 92 | 93 | Microsoft 94 | 95 | vcredist_x64.exe /Q 96 | 97 | 98 | 99 | https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x86.exe 100 | Frameworks 101 | True 102 | True 103 | Microsoft Visual C++ 2013 Redistributable (x86) 104 | 105 | Microsoft 106 | 107 | vcredist_x86.exe /Q 108 | 109 | 110 | 111 | https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe 112 | Frameworks 113 | True 114 | True 115 | Microsoft Visual C++ 2013 Redistributable (x64) 116 | 117 | Microsoft 118 | 119 | vcredist_x64.exe /Q 120 | 121 | 122 | 123 | https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x86.exe 124 | Frameworks 125 | True 126 | True 127 | Microsoft Visual C++ 2015 Redistributable (x86) 128 | 129 | Microsoft 130 | 131 | vc_redist.x86.exe /Q 132 | 133 | 134 | 135 | https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe 136 | Frameworks 137 | True 138 | True 139 | Microsoft Visual C++ 2015 Redistributable (x64) 140 | 141 | Microsoft 142 | 143 | vc_redist.x64.exe /Q 144 | 145 | 146 | 147 | http://ardownload.adobe.com/pub/adobe/reader/win/AcrobatDC/1800920044/AcroRdrDC1800920044_en_US.exe 148 | Utilities 149 | True 150 | True 151 | Adobe Acrobat Reader 152 | 2018.009.20044 153 | Adobe 154 | English 155 | AcroRdrDC1800920044_en_US.exe /sAll /rs /l /msi /qb- /norestart EULA_ACCEPT=YES 156 | 157 | 158 | 159 | https://ftp.mozilla.org/pub/firefox/releases/59.0.2/win64/en-US/Firefox%20Setup%2059.0.2.exe 160 | Applications 161 | True 162 | True 163 | Mozilla Firefox 164 | 59.0.2 165 | Mozilla 166 | English 167 | Firefox%20Setup%2059.0.2.exe -ms 168 | 169 | 170 | 171 | https://notepad-plus-plus.org/repository/7.x/7.5.6/npp.7.5.6.Installer.exe 172 | Utilities 173 | True 174 | True 175 | Notepad Plus Plus 176 | 7.5.6 177 | 178 | English 179 | npp.7.5.6.Installer.exe /S 180 | 181 | 182 | -------------------------------------------------------------------------------- /MDT Build/MDTApplications.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Applications 5 | True 6 | True 7 | Microsoft Office Professional Plus (x86) 8 | 2016 9 | Microsoft 10 | English 11 | setup.exe /adminfile Office_R2.msp 12 | 13 | 14 | 15 | https://download.microsoft.com/download/e/1/c/e1c773de-73ba-494a-a5ba-f24906ecf088/vcredist_x86.exe 16 | Frameworks 17 | True 18 | True 19 | Microsoft Visual C++ 2005 Redistributable (x86) 20 | 21 | Microsoft 22 | 23 | vcredist_x86.exe /Q 24 | 25 | 26 | 27 | https://download.microsoft.com/download/d/4/1/d41aca8a-faa5-49a7-a5f2-ea0aa4587da0/vcredist_x64.exe 28 | Frameworks 29 | True 30 | True 31 | Microsoft Visual C++ 2005 Redistributable (x64) 32 | 33 | Microsoft 34 | 35 | vcredist_x64.exe /Q 36 | 37 | 38 | 39 | https://download.microsoft.com/download/d/d/9/dd9a82d0-52ef-40db-8dab-795376989c03/vcredist_x86.exe 40 | Frameworks 41 | True 42 | True 43 | Microsoft Visual C++ 2008 Redistributable (x86) 44 | 45 | Microsoft 46 | 47 | vcredist_x86.exe /Q 48 | 49 | 50 | 51 | https://download.microsoft.com/download/2/d/6/2d61c766-107b-409d-8fba-c39e61ca08e8/vcredist_x64.exe 52 | Frameworks 53 | True 54 | True 55 | Microsoft Visual C++ 2008 Redistributable (x64) 56 | 57 | Microsoft 58 | 59 | vcredist_x64.exe /Q 60 | 61 | 62 | 63 | https://download.microsoft.com/download/C/6/D/C6D0FD4E-9E53-4897-9B91-836EBA2AACD3/vcredist_x86.exe 64 | Frameworks 65 | True 66 | True 67 | Microsoft Visual C++ 2010 Redistributable (x86) 68 | 69 | Microsoft 70 | 71 | vcredist_x86.exe /Q 72 | 73 | 74 | 75 | https://download.microsoft.com/download/A/8/0/A80747C3-41BD-45DF-B505-E9710D2744E0/vcredist_x64.exe 76 | Frameworks 77 | True 78 | True 79 | Microsoft Visual C++ 2010 Redistributable (x64) 80 | 81 | Microsoft 82 | 83 | vcredist_x64.exe /Q 84 | 85 | 86 | 87 | https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x86.exe 88 | Frameworks 89 | True 90 | True 91 | Microsoft Visual C++ 2012 Redistributable (x86) 92 | 93 | Microsoft 94 | 95 | vcredist_x86.exe /Q 96 | 97 | 98 | 99 | https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe 100 | Frameworks 101 | True 102 | True 103 | Microsoft Visual C++ 2012 Redistributable (x64) 104 | 105 | Microsoft 106 | 107 | vcredist_x64.exe /Q 108 | 109 | 110 | 111 | https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x86.exe 112 | Frameworks 113 | True 114 | True 115 | Microsoft Visual C++ 2013 Redistributable (x86) 116 | 117 | Microsoft 118 | 119 | vcredist_x86.exe /Q 120 | 121 | 122 | 123 | https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe 124 | Frameworks 125 | True 126 | True 127 | Microsoft Visual C++ 2013 Redistributable (x64) 128 | 129 | Microsoft 130 | 131 | vcredist_x64.exe /Q 132 | 133 | 134 | 135 | https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x86.exe 136 | Frameworks 137 | True 138 | True 139 | Microsoft Visual C++ 2015 Redistributable (x86) 140 | 141 | Microsoft 142 | 143 | vc_redist.x86.exe /Q 144 | 145 | 146 | 147 | https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe 148 | Frameworks 149 | True 150 | True 151 | Microsoft Visual C++ 2015 Redistributable (x64) 152 | 153 | Microsoft 154 | 155 | vc_redist.x64.exe /Q 156 | 157 | 158 | 159 | http://ardownload.adobe.com/pub/adobe/reader/win/AcrobatDC/1800920044/AcroRdrDC1800920044_en_US.exe 160 | Utilities 161 | True 162 | True 163 | Adobe Acrobat Reader 164 | 2018.009.20044 165 | Adobe 166 | English 167 | AcroRdrDC1800920044_en_US.exe /sAll /rs /l /msi /qb- /norestart EULA_ACCEPT=YES 168 | 169 | 170 | 171 | https://ftp.mozilla.org/pub/firefox/releases/57.0/win64/en-US/Firefox%20Setup%2057.0.exe 172 | Applications 173 | True 174 | True 175 | Mozilla Firefox 176 | 57.0 177 | Mozilla 178 | English 179 | Firefox%20Setup%2057.0.exe -ms 180 | 181 | 182 | 183 | https://notepad-plus-plus.org/repository/7.x/7.5.3/npp.7.5.3.Installer.exe 184 | Utilities 185 | True 186 | True 187 | Notepad Plus Plus 188 | 7.5.3 189 | 190 | English 191 | npp.7.5.3.Installer.exe /S 192 | 193 | 194 | 195 | https://www.winpcap.org/install/bin/WinPcap_4_1_3.exe 196 | Utilities 197 | True 198 | True 199 | WinPcap 200 | 4.1.3 201 | 202 | English 203 | WinPcap_4_1_3.exe /S 204 | 205 | 206 | 207 | https://2.na.dl.wireshark.org/win64/Wireshark-win64-2.4.3.exe 208 | Utilities 209 | True 210 | True 211 | WireShark x64 212 | 2.4.3 213 | 214 | English 215 | Wireshark-win64-2.4.3.exe /S 216 | 217 | 218 | 219 | https://2.na.dl.wireshark.org/win32/Wireshark-win32-2.4.3.exe 220 | Utilities 221 | True 222 | True 223 | WireShark x86 224 | 2.4.3 225 | 226 | English 227 | Wireshark-win32-2.4.3.exe /S 228 | 229 | 230 | 231 | https://nmap.org/dist/nmap-7.60-setup.exe 232 | Utilities 233 | True 234 | True 235 | Nmap 236 | 7.60 237 | 238 | English 239 | nmap-7.60-setup.exe /S 240 | 241 | 242 | 243 | http://rm-us.palemoon.org/release/palemoon-27.6.2.win64.installer.exe 244 | Applications 245 | True 246 | True 247 | Palemoon x64 248 | 27.6.2 249 | 250 | English 251 | palemoon-27.6.2.win64.installer.exe /S 252 | 253 | 254 | 255 | https://storage-waterfox.netdna-ssl.com/releases/win64/installer/Waterfox%2056.0.1%20Setup.exe 256 | Applications 257 | True 258 | True 259 | Waterfox x64 260 | 56.0.1 261 | 262 | English 263 | Waterfox%2056.0.1%20Setup.exe /S 264 | 265 | 266 | 267 | https://www.codesector.com/files/teracopy.exe 268 | Utilities 269 | True 270 | True 271 | TeraCopy 272 | 3.2.1 273 | 274 | English 275 | teracopy.exe /S 276 | 277 | 278 | 279 | http://download1.famatech.com/download/files/ipscan25.exe 280 | Utilities 281 | True 282 | True 283 | Advanced IP Scanner 284 | 2.5 285 | 286 | English 287 | ipscan25.exe /S 288 | 289 | 290 | -------------------------------------------------------------------------------- /MDT Build/readme.md: -------------------------------------------------------------------------------- 1 | This script is designed to deploy Microsoft Deployment Toolkit (MDT) to an Automated-Lab provisioned server and result in a fully functional MDT+WDS server to deploy images 2 | 3 | Prerequisites: 4 | 5 | - Installed version of Automated-Lab (Tested on v4.5.0) 6 | - Download of the Microsoft Assessment and Deployment Kit - available here: 7 | https://developer.microsoft.com/en-us/windows/hardware/windows-assessment-deployment-kit 8 | (Tested with 1709 Version) 9 | - A Server operating system image for an AL machine deployment: 10 | Tested on Windows Server 2012 R2, and Windows Server 2016 11 | 12 | All other necessary files such as MDT are downloaded through the script. 13 | 14 | Note: Script assumes internet access is avaiable to download binary files. If no Internet access is available, at a minimum download the MDT installation files and place in the LabSources\SoftwarePackages folder, available at: https://download.microsoft.com/download/3/3/9/339BE62D-B4B8-4956-B58D-73C4685FC492/MicrosoftDeploymentToolkit_x64.msi 15 | 16 | Known Limitations: 17 | - Deployed Server can either be a member of a domain or standalone. Has not been tested where MDT is a DC. 18 | - Script assumes that MDT+ADK, WDS and DHCP all reside on the same server. 19 | 20 | This script is a work in progress, there are some assumptions made resulting in some lack of error checking. Additional enhancements are in the pipeline, and are managed as enhancement requests within GitHub 21 | 22 | Update 8/4: 23 | 24 | A version of this script is has been developed to support the AutomatedLab 'CustomRoles' feature that will released as part of Version 5.0. 25 | 26 | Scripts are located in the 'AL Custom Role' folder, and all items should be copied to the 'LabSources\CustomRoles' folder with the 'MDT' folder name, eg: 27 | 28 | ```yaml 29 | C:\LabSources\CustomRoles 30 | \MDT 31 | \DownloadADK.ps1 32 | \HostInit.ps1 33 | \InstallMDT.ps1 34 | \MDTApplications.XML 35 | ``` 36 | 37 | To use from AL: 38 | 39 | ```ps 40 | $mdtRole = Get-LabPostInstallationActivity -CustomRole MDT -Properties @{ 41 | DeploymentFolderLocation = 'D:\DeploymentShare' 42 | InstallUserID = 'MdtService' 43 | InstallPassword = 'Somepass1' 44 | OperatingSystems = 'Windows Server 2016 Datacenter (Desktop Experience)', 'Windows 10 Enterprise|10.0.10586.0|Windows 10 Enterprise 1511','Windows 10 Enterprise|10.0.15063.296|Windows 10 Enterprise 1703' 45 | AdkDownloadPath = "$labSources\SoftwarePackages\ADK" 46 | CreateTaskSequences = 'True' 47 | } 48 | 49 | Add-LabDiskDefinition -Name MDTData -DiskSizeInGb 100 50 | Add-LabMachineDefinition -Name MDT1Server -Memory 4GB -Processors 2 -DiskName MDTData -OperatingSystem 'Windows Server 2016 Datacenter (Desktop Experience)' -IpAddress 192.168.81.10 -PostInstallationActivity $mdtRole 51 | 52 | ``` 53 | 54 | A feature has been added to support direct targeting of Operating Systems using a combination of the OS name and OS version. Within the 'OperatingSystems' parameter, multiple Operating Systems can be provided, with additional supported options being: 55 | 56 | `OS Name` - System will search for an AutomatedLab Operating System name and pick the newest one of there are multiples 57 | 58 | `OS Name|OS Version` - System will search for an AutomatedLab Operating System name, with the specific version 59 | 60 | `OS Name|OS Version|Friendly Name` - System will search for an AutomatedLab Operating System name, with the specific version, and use the Friendly Name when registering the OS to MDT. 61 | 62 | Any combination of these options can be used for each item in the OperatingSystems List. 63 | 64 | Use the Get-LabAvailableOperatingSystems command provides Details on the available Operating Systems 65 | -------------------------------------------------------------------------------- /MIM Build/readme.md: -------------------------------------------------------------------------------- 1 | These scripts are designed to deploy a Microsoft Identity Manager (MIM) Lab using AutomatedLab 2 | 3 | Prerequisites: 4 | 5 | - Installed version of Automated-Lab (Tested on v4.5.0) 6 | - A Server operating system image for an AL machine deployment (Tested with Server 2016) 7 | 8 | Intent of these scripts is to deploy the following roles: 9 | 10 | - Windows Domain Controller 11 | - Microsoft Identity Manager 2016 12 | - SharePoint 2016 (to Support MIM) 13 | 14 | These scripts are a work in progress, there are some assumptions made resulting in some lack of error checking. Additional enhancements are in the pipeline, and are managed as enhancement requests within GitHub. 15 | 16 | Current Scripts: 17 | 18 | - **MIMLab.psm1** - Main Script 19 | 20 | - **UserRights.ps1** - Script by Tony Pombo to perform assignments of rights to accounts, provides the same capabilities as available via the Local GP Editor (needed to assign specific rights to MIM + SharePoint Service accounts) 21 | 22 | Notes: 23 | -------------------------------------------------------------------------------- /MS TLG/BaseConfig.ps1: -------------------------------------------------------------------------------- 1 | #Cleanup from last run 2 | Remove-Item -Path 'C:\Temp\BaseConfig.log' -Force -ErrorAction SilentlyContinue 3 | Start-Transcript -Path 'C:\Temp\BaseConfig.log' 4 | 5 | $labName = 'BaseConfig' 6 | $labSources = Get-LabSourcesLocation 7 | 8 | New-LabDefinition -Name $LabName -DefaultVirtualizationEngine HyperV -VmPath "D:\Hyper-V\Automation-Lab" 9 | Add-LabVirtualNetworkDefinition -Name 'CORPNET' -AddressSpace 10.0.0.0/24 10 | 11 | $PSDefaultParameterValues = @{ 12 | 'Add-LabMachineDefinition:Network' = $labName 13 | 'Add-LabMachineDefinition:ToolsPath'= "$labSources\Tools" 14 | 'Add-LabMachineDefinition:DomainName' = 'corp.contoso.com' 15 | 'Add-LabMachineDefinition:DnsServer1' = '10.0.0.1' 16 | 'Add-LabMachineDefinition:OperatingSystem' = 'Windows Server 2016 SERVERSTANDARD' 17 | } 18 | 19 | $DCrole = Get-LabMachineRoleDefinition -Role RootDC 20 | $CARole += Get-LabMachineRoleDefinition -Role CaRoot @{ 21 | CAType = "EnterpriseRootCA" 22 | CACommonName = "corp-DC1-CA" 23 | KeyLength = "2048" 24 | ValidityPeriod = "Years" 25 | ValidityPeriodUnits = "2" 26 | } 27 | 28 | Add-LabMachineDefinition -Name DC1 -Memory 2GB -Roles $DCRole,$CARole -IPAddress '10.0.0.1' -Network 'CORPNET' 29 | Add-LabMachineDefinition -Name APP1 -Memory 2GB -IPAddress '10.0.0.3' -Network 'CORPNET' 30 | Add-LabMachineDefinition -Name CLIENT1 -Memory 2GB -OperatingSystem 'Windows 7 PROFESSIONAL' -Network 'CORPNET' 31 | 32 | Install-Lab -NetworkSwitches -BaseImages -VMs 33 | 34 | #This sets up all domains / domain controllers 35 | Install-Lab -Domains 36 | 37 | #Install CA server(s) 38 | Install-Lab -CA 39 | 40 | #Finish off the rest 41 | Install-Lab -StartRemainingMachines 42 | 43 | #Configure the CRL Distribution Settings 44 | Invoke-LabCommand -ActivityName 'Configure the CRL Distribution Settings' -ComputerName 'DC1' -ScriptBlock { 45 | Add-CACrlDistributionPoint -Uri 'http://crl.corp.contoso.com/crld/.crl' -AddToCertificateCdp -Force 46 | Add-CACrlDistributionPoint -Uri '\\app1\crldist$\.crl' -PublishToServer -PublishDeltaToServer -Force 47 | Restart-Service -Name 'CertSvc' -Force 48 | } 49 | 50 | #Create a DNS record for crl.corp.contoso.com 51 | Invoke-LabCommand -ActivityName 'Create a DNS record for crl.corp.contoso.com' -ComputerName 'DC1' -ScriptBlock { 52 | Add-DnsServerResourceRecordA -Name "CRL" -ZoneName "corp.contoso.com" -AllowUpdateAny -IPv4Address "10.0.0.3" -TimeToLive 01:00:00 53 | } 54 | 55 | #Create a user account in Active Directory 56 | Invoke-LabCommand -ActivityName 'Create a user account in Active Directory' -ComputerName 'DC1' -ScriptBlock { 57 | New-ADUser -Name 'User1' -SamAccountName 'User1' -UserPrincipalName 'User1@corp.contoso.com' -AccountPassword (ConvertTo-SecureString -AsPlainText 'Somepass1' -Force) -ChangePasswordAtLogon $false -PasswordNeverExpires $true -Enabled $true 58 | Add-ADGroupMember 'Domain Admins' -Members 'User1' 59 | } 60 | 61 | #Configure computer certificate auto-enrollment 62 | Enable-LabCertificateAutoenrollment -Computer 63 | 64 | #Configure computer account maximum password age 65 | #TODO - Powershell Group Policy cmdlets are severely lacking in this space 66 | Invoke-LabCommand -ActivityName 'Configure computer account maximum password age' -ComputerName 'DC1' -ScriptBlock { 67 | 68 | } 69 | 70 | #Install the Web Server (IIS) role on APP1 71 | Install-LabWindowsFeature -ComputerName 'APP1' -FeatureName 'Web-WebServer,Web-Common-Http,Web-Default-Doc,Web-Dir-Browsing,Web-Http-Errors,Web-Static-Content,Web-Health,Web-Http-Logging,Web-Performance,Web-Stat-Compression,Web-Security,Web-Filtering,Web-Mgmt-Tools,Web-Mgmt-Console' 72 | 73 | #Create a web-based CRL distribution point 74 | Invoke-LabCommand -ActivityName 'Create a web-based CRL distribution point' -ComputerName 'APP1' -ScriptBlock { 75 | #Create the directory to hold the CRL 76 | New-Item -Path 'C:\CRLDist' -ItemType Directory -Force 77 | #Create a Virtual Directory in IIS 78 | New-WebVirtualDirectory -Site "Default Web Site" -Name "CRLD" -PhysicalPath "C:\CRLDIST" 79 | #Enable Directory Browsing 80 | Set-WebConfigurationProperty -filter /system.webServer/directoryBrowse -name 'enabled' -PSPath 'IIS:\Sites\Default Web Site\CRLD' -Value $true 81 | #enable request filtering 82 | Set-WebConfigurationProperty -filter /system.webServer/security/requestFiltering -name 'allowDoubleEscaping' -PSPath 'IIS:\Sites\Default Web Site\CRLD' -Value $true 83 | } 84 | 85 | #Configure the HTTPS security binding 86 | #Request a certificate for the web server 87 | $cert = Request-LabCertificate -Subject CN=app1.corp.contoso.com -TemplateName WebServer -ComputerName 'DC1' -PassThru 88 | 89 | Invoke-LabCommand -ActivityName 'Configure the HTTPS security binding' -ComputerName 'APP1' -ScriptBlock { 90 | #Enable SSL 91 | New-WebBinding -Name "Default Web Site" -IP "*" -Port 443 -Protocol https 92 | #Assign Certificate to SSL 93 | Import-Module -Name WebAdministration 94 | Get-Item -Path "Cert:\LocalMachine\My\$($args[0].Thumbprint)" | New-Item -Path IIS:\SslBindings\0.0.0.0!443 95 | } -ArgumentList $cert 96 | 97 | #Configure permissions on the CRL distribution point file share 98 | Invoke-LabCommand -ActivityName 'Configure permissions on the CRL distribution point file share' -ComputerName 'APP1' -ScriptBlock { 99 | #Create The Share, giving the Domain Controll Computer Account Full Access 100 | New-SmbShare -Name 'CRLDist$' -Path 'C:\CRLDist' -FullAccess 'CORP\DC1$' -ReadAccess 'Everyone' 101 | #Set the on-disk permissions, allowing the DC to update the CRL 102 | #Get the existing ACL 103 | $Acl = Get-Acl "C:\CRLDist" 104 | #Set up a new access rule for the DC 105 | $AccessRights = New-Object system.security.accesscontrol.filesystemaccessrule("CORP\DC1$","FullControl","Allow") 106 | #Add this access rule to the existing ACL 107 | $Acl.SetAccessRule($AccessRights) 108 | #Set this back on the folder 109 | Set-Acl "C:\CRLDist" $Acl 110 | } 111 | 112 | #Publish the CRL to APP1 from DC1 113 | #TODO 114 | Invoke-LabCommand -ActivityName 'Publish the CRL to APP1 from DC1' -ComputerName 'APP1' -ScriptBlock { 115 | 116 | } 117 | 118 | 119 | #Create a shared folder on APP1 120 | Invoke-LabCommand -ActivityName 'Create a shared folder on APP1' -ComputerName 'APP1' -ScriptBlock { 121 | #Create the path 122 | New-Item -Path 'C:\Files' -ItemType Directory -Force 123 | #Create The Share, giving the Everyone Full Access 124 | New-SmbShare -Name 'Files' -Path 'C:\Files' -FullAccess 'Everyone' 125 | #Create a text file in this folder 126 | 'This is a shared file' | Out-File 'C:\Files\example.txt' 127 | } 128 | 129 | #Verify the computer certificate 130 | $cert = Request-LabCertificate -Subject 'CN=client1.corp.contoso.com' -TemplateName Machine -ComputerName 'CLIENT1' -PassThru 131 | 132 | -------------------------------------------------------------------------------- /MS TLG/readme.md: -------------------------------------------------------------------------------- 1 | These scripts are designed to proviude an Automated-Lab approach to the Microsoft Test Lab Guides (TLG) which are used to provide examples of Microsoft Technolgies and provide a platform for detailed learning and experimentation. 2 | 3 | The test lab guides have been superceded in a large part by the TechNet Virtual Labs, however the Technet Labs are typically time limited, and designed to showcase a particular activity (such as deploying SCCM). They are not really designed to allow for an open ended freeform approach to learning which I find much more useful than following a bouncing ball. 4 | 5 | Microsoft Test Lab Guides homepage: https://social.technet.microsoft.com/wiki/contents/articles/1262.test-lab-guides.aspx 6 | 7 | Prerequisites: 8 | 9 | - Installed version of Automated-Lab (Tested on v4.5.0) 10 | - Access to the Test Lab Guides (link above) 11 | 12 | Initial intent of these scripts is to deploy the base Test Lab Guide configuration (https://www.microsoft.com/en-us/download/details.aspx?id=6815), which is then used by additional labs. 13 | 14 | Additional scripts will be developed to encompass various labs as needs require. 15 | 16 | **Note:** Due to the lack of maintenance of many labs, the base configuration lab will be updated to support more current versions of Server and Desktop Operating Systems, as well as applications (such as System Center) 17 | 18 | Where possible, AutomatedLab processes and functions will be used for deployment activities. Where deployment activities require developing powershell code, they will be organised as much as practical using the heading text within the Test Lab guide. This will allow individual activities to be isolated for performing manually via the GUI, or viewing the equivalent powershell code to perform the same activity as in the guide. 19 | 20 | Current Scripts: 21 | 22 | - **BaseConfig.ps1** - Configures the base environment for the TestLab Guides, consisting of the following: 23 | - DC1 - Domain Controller with Active Directory + DNS + Certificate Services + DHCP 24 | - APP1 - Member Server with IIS 25 | - CLIENT1 - Member Workstation 26 | - EDGE1 - Member Server acting as a router 27 | - INET1 - Standalone Server with IIS + DNS + DHCP 28 | 29 | These scripts are a work in progress, there are some assumptions made resulting in some lack of error checking. Additional enhancements are in the pipeline, and are managed as enhancement requests within GitHub. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AL-Scripts 2 | 3 | Developed Scripts for deploying various Labs using Automated-Lab 4 | 5 | -------------------------------------------------------------------------------- /SCCM Build 2/Custom Roles/SCCM/DownloadAdk.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory)] 3 | [string]$AdkDownloadPath, 4 | 5 | [Parameter(Mandatory)] 6 | [string]$AdkWinPEDownloadPath 7 | ) 8 | 9 | $windowsAdkUrl = 'https://download.microsoft.com/download/0/1/C/01CC78AA-B53B-4884-B7EA-74F2878AA79F/adk/adksetup.exe' 10 | $adkSetup = Get-LabInternetFile -Uri $windowsAdkUrl -Path $labSources\SoftwarePackages -PassThru 11 | 12 | if (-not (Test-Path -Path $AdkDownloadPath)) 13 | { 14 | $p = Start-Process -FilePath $adkSetup.FullName -ArgumentList "/quiet /layout $AdkDownloadPath" -PassThru 15 | Write-ScreenInfo "Waiting for ADK to download files" -NoNewLine 16 | while (-not $p.HasExited) { 17 | Write-ScreenInfo '.' -NoNewLine 18 | Start-Sleep -Seconds 10 19 | } 20 | Write-ScreenInfo 'finished' 21 | } 22 | else 23 | { 24 | Write-ScreenInfo "ADK folder already exists, skipping the download. Delete the folder '$AdkDownloadPath' if you want to download again." 25 | } 26 | 27 | $windowsAdkWinPEUrl = 'https://download.microsoft.com/download/D/7/E/D7E22261-D0B3-4ED6-8151-5E002C7F823D/adkwinpeaddons/adkwinpesetup.exe' 28 | $adkWinPESetup = Get-LabInternetFile -Uri $windowsAdkWinPEUrl -Path $labSources\SoftwarePackages -PassThru 29 | 30 | if (-not (Test-Path -Path $AdkWinPEDownloadPath)) 31 | { 32 | $p = Start-Process -FilePath $adkWinPESetup.FullName -ArgumentList "/quiet /layout $AdkWinPEDownloadPath" -PassThru 33 | Write-ScreenInfo "Waiting for ADK Windows PE Addons to download files" -NoNewLine 34 | while (-not $p.HasExited) { 35 | Write-ScreenInfo '.' -NoNewLine 36 | Start-Sleep -Seconds 10 37 | } 38 | Write-ScreenInfo 'finished' 39 | } 40 | else 41 | { 42 | Write-ScreenInfo "ADK Windows PE Addons folder already exists, skipping the download. Delete the folder '$AdkWinPEDownloadPath' if you want to download again." 43 | } 44 | 45 | 46 | -------------------------------------------------------------------------------- /SCCM Build 2/Custom Roles/SCCM/DownloadSccm.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory)] 3 | [string]$SccmBinariesDirectory, 4 | 5 | [Parameter(Mandatory)] 6 | [string]$SccmPreReqsDirectory 7 | ) 8 | 9 | $sccm1802URL = 'https://download.microsoft.com/download/F/C/E/FCEC70F4-168A-4D68-8B52-30913C402D5F/SC_Configmgr_SCEP_1802.exe' 10 | $sccm1702Url = 'http://download.microsoft.com/download/C/A/0/CA0CAE64-358C-49EC-9F61-8FACFEDE7083/SC_Configmgr_SCEP_1702.exe' 11 | 12 | $sccmSetup = Get-LabInternetFile -Uri $sccm1802Url -Path $labSources\SoftwarePackages -PassThru 13 | 14 | if (-not (Test-Path -Path $SccmBinariesDirectory)) 15 | { 16 | $pArgs = '/AUTO "{0}"' -f $SccmBinariesDirectory 17 | $p = Start-Process -FilePath $sccmSetup.FullName -ArgumentList $pArgs -PassThru 18 | Write-ScreenInfo "Waiting for extracting the SCCM files to '$SccmBinariesDirectory'" -NoNewLine 19 | while (-not $p.HasExited) { 20 | Write-ScreenInfo '.' -NoNewLine 21 | Start-Sleep -Seconds 10 22 | } 23 | Write-ScreenInfo 'finished' 24 | } 25 | else 26 | { 27 | Write-ScreenInfo "SCCM folder already exists, skipping the download. Delete the folder '$SccmBinariesDirectory' if you want to download again." 28 | } 29 | 30 | if (-not (Test-Path -Path $SccmPreReqsDirectory)) 31 | { 32 | $p = Start-Process -FilePath $labSources\SoftwarePackages\SCCM1802\SMSSETUP\BIN\X64\setupdl.exe -ArgumentList $SccmPreReqsDirectory -PassThru 33 | Write-ScreenInfo "Waiting for downloading the SCCM Prerequisites to '$SccmPreReqsDirectory'" -NoNewLine 34 | while (-not $p.HasExited) { 35 | Write-ScreenInfo '.' -NoNewLine 36 | Start-Sleep -Seconds 10 37 | } 38 | Write-ScreenInfo 'finished' 39 | 40 | } 41 | else 42 | { 43 | Write-ScreenInfo "SCCM Prerequisites folder already exists, skipping the download. Delete the folder '$SccmPreReqsDirectory' if you want to download again." 44 | } -------------------------------------------------------------------------------- /SCCM Build 2/Custom Roles/SCCM/HostStart.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | 3 | [Parameter(Mandatory)] 4 | [string]$ComputerName, 5 | 6 | [Parameter(Mandatory)] 7 | [string]$SccmSiteCode, 8 | 9 | [string]$SccmSiteName, 10 | 11 | [Parameter(Mandatory)] 12 | [string]$SccmBinariesDirectory, 13 | 14 | [Parameter(Mandatory)] 15 | [string]$SccmPreReqsDirectory, 16 | 17 | [string]$SccmInstallDirectory, 18 | 19 | [Parameter(Mandatory)] 20 | [string]$AdkDownloadPath, 21 | 22 | [Parameter(Mandatory)] 23 | [string]$AdkWinPEDownloadPath, 24 | 25 | [Parameter(Mandatory)] 26 | [string]$SqlServerName 27 | ) 28 | 29 | $sqlServer = Get-LabVM -Role SQLServer | Where-Object Name -eq $SqlServerName 30 | $sccmServer = Get-LabVM -ComputerName $ComputerName 31 | if (-not $sqlServer) 32 | { 33 | Write-Error "The specified SQL Server '$SqlServerName' does not exist in the lab." 34 | return 35 | } 36 | 37 | if ($sccmServer.OperatingSystem.Version -lt 10.0 -or $SqlServer.OperatingSystem.Version -lt 10.0) 38 | { 39 | Write-Error "The SCCM role requires the SCCM server and the SQL Server to be Windows 2016 or higher." 40 | return 41 | } 42 | 43 | if ($SccmSiteCode -notmatch '^[A-Za-z0-9]{3}$') 44 | { 45 | Write-Error 'The site code must have exactly three characters and it can contain only alphanumeric characters (A to Z or 0 to 9).' 46 | return 47 | } 48 | 49 | $script = Get-Command -Name $PSScriptRoot\DownloadAdk.ps1 50 | $param = Sync-Parameter -Command $script -Parameters $PSBoundParameters 51 | & $PSScriptRoot\DownloadAdk.ps1 @param 52 | 53 | $script = Get-Command -Name $PSScriptRoot\DownloadSccm.ps1 54 | $param = Sync-Parameter -Command $script -Parameters $PSBoundParameters 55 | & $PSScriptRoot\DownloadSccm.ps1 @param 56 | 57 | $script = Get-Command -Name $PSScriptRoot\InstallSCCM.ps1 58 | $param = Sync-Parameter -Command $script -Parameters $PSBoundParameters 59 | & $PSScriptRoot\InstallSCCM.ps1 @param -------------------------------------------------------------------------------- /SCCM Build 2/Custom Roles/SCCM/InstallSCCM.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Install a functional SCCM Primary Site using the Automated-Lab tookit with SCCM being installed using the "CustomRoles" approach 4 | .DESCRIPTION 5 | Long description 6 | .EXAMPLE 7 | PS C:\> 8 | Explanation of what the example does 9 | .INPUTS 10 | Inputs (if any) 11 | .OUTPUTS 12 | Output (if any) 13 | .NOTES 14 | General notes 15 | #> 16 | 17 | param( 18 | 19 | [Parameter(Mandatory)] 20 | [string]$ComputerName, 21 | 22 | [Parameter(Mandatory)] 23 | [string]$SccmBinariesDirectory, 24 | 25 | [Parameter(Mandatory)] 26 | [string]$SccmPreReqsDirectory, 27 | 28 | [Parameter(Mandatory)] 29 | [string]$SccmSiteCode, 30 | 31 | [string]$SccmSiteName, 32 | 33 | [Parameter(Mandatory)] 34 | [string]$SqlServerName, 35 | 36 | [string]$SccmInstallDirectory 37 | ) 38 | 39 | function Install-SCCM { 40 | param 41 | ( 42 | [Parameter(Mandatory)] 43 | [string]$SccmServerName, 44 | 45 | [Parameter(Mandatory)] 46 | [string]$SccmBinariesDirectory, 47 | 48 | [Parameter(Mandatory)] 49 | [string]$SccmPreReqsDirectory, 50 | 51 | [Parameter(Mandatory)] 52 | [string]$SccmSiteCode, 53 | 54 | [string]$SccmSiteName="Primary Site 1", 55 | 56 | [Parameter(Mandatory)] 57 | [string]$SqlServerName, 58 | 59 | [string]$SccmInstallDirectory='C:\Program Files\Microsoft Configuration Manager' 60 | ) 61 | 62 | $sccmServer = Get-LabVM -ComputerName $SccmServerName 63 | $sccmServerFqdn = $sccmServer.FQDN 64 | $sqlServer = Get-LabVM -Role SQLServer | Where-Object Name -eq $SqlServerName 65 | $sqlServerFqdn = $sqlServer.FQDN 66 | $rootDC = Get-LabVM -Role RootDC | Where-Object { $_.DomainName -eq $sccmServer.DomainName } 67 | 68 | if (-not $sqlServer) 69 | { 70 | Write-Error "The specified SQL Server '$SqlServerName' does not exist in the lab." 71 | return 72 | } 73 | 74 | $mdtDownloadLocation = 'https://download.microsoft.com/download/3/3/9/339BE62D-B4B8-4956-B58D-73C4685FC492/MicrosoftDeploymentToolkit_x64.msi' 75 | $downloadTargetFolder = "$labSources\SoftwarePackages" 76 | 77 | #Do Some quick checks before we get going 78 | #Check for existance of ADK Installation Files 79 | if (-not (Test-Path -Path "$downloadTargetFolder\ADK1809")) { 80 | Write-LogFunctionExitWithError -Message "ADK Installation files not located at '$downloadTargetFolder\ADK'" 81 | return 82 | } 83 | 84 | if (-not (Test-Path -Path "$downloadTargetFolder\ADK1809WinPEAddons")) { 85 | Write-LogFunctionExitWithError -Message "ADK Windows PE Addons Installation files not located at '$downloadTargetFolder\ADKWinPEAddons'" 86 | return 87 | } 88 | 89 | if (-not (Test-Path -Path $SccmBinariesDirectory)) { 90 | Write-LogFunctionExitWithError -Message "SCCM Installation files not located at '$($SccmBinariesDirectory)'" 91 | return 92 | } 93 | 94 | if (-not (Test-Path -Path $SccmPreReqsDirectory)) { 95 | Write-LogFunctionExitWithError -Message "SCCM PreRequisite files not located at '$($SccmPreReqsDirectory)'" 96 | return 97 | } 98 | 99 | #Bring all available disks online (this is to cater for any secondary drives) 100 | #Cant make the disk online and RW in the one command, need to perform two seperate actions 101 | Invoke-LabCommand -ActivityName 'Bring Disks Online' -ComputerName $SccmServerName -ScriptBlock { 102 | $dataVolume = Get-Disk | Where-Object -Property OperationalStatus -eq Offline 103 | $dataVolume | Set-Disk -IsOffline $false 104 | $dataVolume | Set-Disk -IsReadOnly $false 105 | 106 | #Add some NO_SMS_ON_DRIVE.SMS files to stop SCCM grabbing them for its use (note: this activity needs to be parameterised) 107 | Set-Content -Path C:\NO_SMS_ON_DRIVE.SMS -Value 'NO_SMS_ON_DRIVE' 108 | Set-Content -Path E:\NO_SMS_ON_DRIVE.SMS -Value 'NO_SMS_ON_DRIVE' 109 | Set-Content -Path F:\NO_SMS_ON_DRIVE.SMS -Value 'NO_SMS_ON_DRIVE' 110 | } 111 | 112 | 113 | 114 | #Copy the SCCM Binaries 115 | $SCCMSourcesDirectory = Copy-LabFileItem -Path $SccmBinariesDirectory -DestinationFolderPath C:\Install -ComputerName $SccmServerName -Recurse -PassThru 116 | #Copy the SCCM Prereqs (must have been previously downloaded) 117 | $SCCMPreReqSourcesDirectory = Copy-LabFileItem -Path $SccmPreReqsDirectory -DestinationFolderPath C:\Install -ComputerName $SccmServerName -Recurse -PassThru 118 | 119 | #Extend the AD Schema 120 | Invoke-LabCommand -ActivityName 'Extend AD Schema' -ComputerName $SccmServerName -ScriptBlock { 121 | 122 | param 123 | ( 124 | $SCCMSourcesDirectory 125 | ) 126 | 127 | "$($SCCMSourcesDirectory)\SMSSETUP\BIN\X64\extadsch.exe" 128 | 129 | } -ArgumentList $SCCMSourcesDirectory 130 | 131 | #Need to execute this command on the Domain Controller, since it has the AD Powershell cmdlets available 132 | #Create the Necessary OU and permissions for the SCCM container in AD 133 | Invoke-LabCommand -ActivityName 'Configure SCCM Systems Management Container' -ComputerName $rootDC -ScriptBlock { 134 | param 135 | ( 136 | [Parameter(Mandatory)] 137 | [string]$SCCMServerName 138 | ) 139 | 140 | Import-Module ActiveDirectory 141 | # Figure out our domain 142 | $rootDomainNc = (Get-ADRootDSE).defaultNamingContext 143 | 144 | # Get or create the System Management container 145 | $ou = $null 146 | try 147 | { 148 | $ou = Get-ADObject "CN=System Management,CN=System,$rootDomainNc" 149 | } 150 | catch 151 | { 152 | Write-Verbose "System Management container does not currently exist." 153 | $ou = New-ADObject -Type Container -name "System Management" -Path "CN=System,$rootDomainNc" -Passthru 154 | } 155 | 156 | # Get the current ACL for the OU 157 | $acl = Get-ACL -Path "ad:CN=System Management,CN=System,$rootDomainNc" 158 | 159 | # Get the computer's SID (we need to get the computer object, which is in the form $) 160 | $sccmComputer = Get-ADComputer "$SCCMServerName$" 161 | $sccmServerSId = [System.Security.Principal.SecurityIdentifier] $sccmComputer.SID 162 | 163 | $ActiveDirectoryRights = "GenericAll" 164 | $AccessControlType = "Allow" 165 | $Inherit = "SelfAndChildren" 166 | $nullGUID = [guid]'00000000-0000-0000-0000-000000000000' 167 | 168 | # Create a new access control entry to allow access to the OU 169 | $ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $sccmServerSId, $ActiveDirectoryRights, $AccessControlType, $Inherit, $nullGUID 170 | 171 | # Add the ACE to the ACL, then set the ACL to save the changes 172 | $acl.AddAccessRule($ace) 173 | Set-ACL -AclObject $acl "ad:CN=System Management,CN=System,$rootDomainNc" 174 | 175 | } -ArgumentList $SccmServerName 176 | 177 | Write-ScreenInfo -Message "Downloading MDT Installation Files from '$mdtDownloadLocation'" 178 | $mdtInstallFile = Get-LabInternetFile -Uri $mdtDownloadLocation -Path $downloadTargetFolder -ErrorAction Stop -PassThru 179 | 180 | Write-ScreenInfo "Copying MDT Install Files to server '$SccmServerName'..." 181 | Copy-LabFileItem -Path $mdtInstallFile.FullName -DestinationFolderPath C:\Install -ComputerName $SccmServerName 182 | 183 | Write-ScreenInfo "Copying ADK Install Files to server '$SccmServerName'..." 184 | Copy-LabFileItem -Path "$downloadTargetFolder\ADK1809" -DestinationFolderPath C:\Install -ComputerName $SccmServerName -Recurse 185 | 186 | Write-ScreenInfo "Copying ADK Windows PE Addons Install Files to server '$SccmServerName'..." 187 | Copy-LabFileItem -Path "$downloadTargetFolder\ADK1809WinPEAddons" -DestinationFolderPath C:\Install -ComputerName $SccmServerName -Recurse 188 | 189 | Write-ScreenInfo "Installing ADK on server '$SccmServerName'..." -NoNewLine 190 | $job = Install-LabSoftwarePackage -LocalPath C:\Install\ADK1809\adksetup.exe -CommandLine "/norestart /q /ceip off /features OptionId.DeploymentTools OptionId.UserStateMigrationTool OptionId.ImagingAndConfigurationDesigner" ` 191 | -ComputerName $SccmServerName -NoDisplay -AsJob -PassThru 192 | Wait-LWLabJob -Job $job -NoDisplay 193 | 194 | Write-ScreenInfo "Installing ADK Windows PE Addons on server '$ComputerName'..." -NoNewLine 195 | $job = Install-LabSoftwarePackage -LocalPath C:\Install\ADK1809WinPEAddons\adkwinpesetup.exe -CommandLine '/norestart /q /ceip off /features OptionId.WindowsPreinstallationEnvironment' ` 196 | -ComputerName $SccmServerName -NoDisplay -AsJob -PassThru 197 | Wait-LWLabJob -Job $job -NoDisplay 198 | 199 | Write-ScreenInfo "Installing .net 3.5 on '$SccmServerName'..." -NoNewLine 200 | $job = Install-LabWindowsFeature -ComputerName $SccmServerName -FeatureName NET-Framework-Core -NoDisplay -AsJob -PassThru 201 | Wait-LWLabJob -Job $job -NoDisplay 202 | 203 | Write-ScreenInfo "Installing WDS on '$SccmServerName'..." -NoNewLine 204 | $job = Install-LabWindowsFeature -ComputerName $SccmServerName -FeatureName WDS -NoDisplay -AsJob -PassThru 205 | Wait-LWLabJob -Job $job -NoDisplay 206 | 207 | Write-ScreenInfo "Installing 'MDT' on server '$SccmServerName'..." -NoNewLine 208 | Install-LabSoftwarePackage -ComputerName $SccmServerName -LocalPath "C:\Install\$($mdtInstallFile.FileName)" -CommandLine '/qb' -NoDisplay -AsJob -PassThru 209 | Wait-LWLabJob -Job $job -NoDisplay 210 | 211 | Invoke-LabCommand -ActivityName 'Configure WDS' -ComputerName $SccmServerName -ScriptBlock { 212 | Start-Process -FilePath "C:\Windows\System32\WDSUTIL.EXE" -ArgumentList "/Initialize-Server /RemInst:C:\RemoteInstall" -Wait 213 | Start-Sleep -Seconds 10 214 | Start-Process -FilePath "C:\Windows\System32\WDSUTIL.EXE" -ArgumentList "/Set-Server /AnswerClients:All" -Wait 215 | } 216 | 217 | #SCCM Needs a ton of additional features installed... 218 | Write-ScreenInfo "Installing a ton of additional features on server '$SccmServerName'..." -NoNewLine 219 | $job = Install-LabWindowsFeature -ComputerName $SccmServerName -FeatureName 'FS-FileServer,Web-Mgmt-Tools,Web-Mgmt-Console,Web-Mgmt-Compat,Web-Metabase,Web-WMI,Web-WebServer,Web-Common-Http,Web-Default-Doc,Web-Dir-Browsing,Web-Http-Errors,Web-Static-Content,Web-Http-Redirect,Web-Health,Web-Http-Logging,Web-Log-Libraries,Web-Request-Monitor,Web-Http-Tracing,Web-Performance,Web-Stat-Compression,Web-Dyn-Compression,Web-Security,Web-Filtering,Web-Windows-Auth,Web-App-Dev,Web-Net-Ext,Web-Net-Ext45,Web-Asp-Net,Web-Asp-Net45,Web-ISAPI-Ext,Web-ISAPI-Filter' -NoDisplay -AsJob -PassThru 220 | Wait-LWLabJob -Job $job -NoDisplay 221 | $job = Install-LabWindowsFeature -ComputerName $SccmServerName -FeatureName 'NET-HTTP-Activation,NET-Non-HTTP-Activ,NET-Framework-45-ASPNET,NET-WCF-HTTP-Activation45,BITS,RDC' -NoDisplay -AsJob -PassThru 222 | Wait-LWLabJob -Job $job -NoDisplay 223 | Write-ScreenInfo Done 224 | 225 | #Before we start the SCCM Install, restart the computer 226 | Write-ScreenInfo "Restarting server '$SccmServerName'..." -NoNewLine 227 | Restart-LabVM -ComputerName $SccmServerName -Wait -NoDisplay 228 | 229 | #Build the Installation unattended .INI file 230 | $setupConfigFileContent = @" 231 | [Identification] 232 | Action=InstallPrimarySite 233 | 234 | [Options] 235 | ProductID=EVAL 236 | SiteCode=$SccmSiteCode 237 | SiteName=$SccmSiteName 238 | SMSInstallDir=$SccmInstallDirectory 239 | SDKServer=$sccmServerFqdn 240 | RoleCommunicationProtocol=HTTPorHTTPS 241 | ClientsUsePKICertificate=0 242 | PrerequisiteComp=1 243 | PrerequisitePath=$SCCMPreReqSourcesDirectory 244 | MobileDeviceLanguage=0 245 | ManagementPoint=$sccmServerFqdn 246 | ManagementPointProtocol=HTTP 247 | DistributionPoint=$sccmServerFqdn 248 | DistributionPointProtocol=HTTP 249 | DistributionPointInstallIIS=0 250 | AdminConsole=1 251 | JoinCEIP=0 252 | 253 | [SQLConfigOptions] 254 | SQLServerName=$SqlServerFqdn 255 | DatabaseName=CM_$SccmSiteCode 256 | SQLSSBPort=4022 257 | SQLDataFilePath=C:\CMSQL\SQLDATA\ 258 | SQLLogFilePath=C:\CMSQL\SQLLOGS\ 259 | 260 | [CloudConnectorOptions] 261 | CloudConnector=0 262 | CloudConnectorServer=$sccmServerFqdn 263 | UseProxy=0 264 | 265 | [SystemCenterOptions] 266 | 267 | [HierarchyExpansionOption] 268 | "@ 269 | 270 | #Save the config file to disk, and copy it to the SCCM Server 271 | $setupConfigFileContent | Out-File -FilePath "$($lab.LabPath)\ConfigMgrUnattend.ini" -Encoding ascii 272 | 273 | Copy-LabFileItem -Path "$($lab.LabPath)\ConfigMgrUnattend.ini" -DestinationFolderPath C:\Install -ComputerName $SccmServerName 274 | 275 | $sccmComputerAccount = '{0}\{1}$' -f 276 | $sccmServer.DomainName.Substring(0, $sccmServer.DomainName.IndexOf('.')), 277 | $SccmServerName 278 | 279 | Invoke-LabCommand -ActivityName 'Create Folders for SQL DB' -ComputerName $sqlServer -ScriptBlock { 280 | #SQL Server does not like creating databases without the directories already existing, so make sure to create them first 281 | New-Item -Path 'C:\CMSQL\SQLDATA' -ItemType Directory -Force | Out-Null 282 | New-Item -Path 'C:\CMSQL\SQLLOGS' -ItemType Directory -Force | Out-Null 283 | 284 | if (-not (Get-LocalGroupMember -Group Administrators -Member $sccmComputerAccount -ErrorAction SilentlyContinue)) 285 | { 286 | Add-LocalGroupMember -Group Administrators -Member $sccmComputerAccount 287 | } 288 | } -Variable (Get-Variable -Name sccmComputerAccount) -NoDisplay 289 | 290 | Write-ScreenInfo 'Install SCCM. This step will take quite some time...' -NoNewLine 291 | $job = Install-LabSoftwarePackage -ComputerName $SccmServerName -LocalPath "$($SCCMSourcesDirectory)\SMSSETUP\BIN\X64\setup.exe" -CommandLine '/Script "C:\Install\ConfigMgrUnattend.ini" /NoUserInput' -AsJob -PassThru 292 | Wait-LWLabJob -Job $job -NoDisplay 293 | } 294 | 295 | Write-ScreenInfo '' 296 | $lab = Import-Lab -Name $data.Name -NoValidation -NoDisplay -PassThru 297 | 298 | Install-SCCM -SccmServerName $ComputerName -SccmBinariesDirectory $SCCMBinariesDirectory -SccmPreReqsDirectory $SCCMPreReqsDirectory -SccmSiteCode $SCCMSiteCode -SqlServerName $SqlServerName -SccmSiteName $SccmSiteName -------------------------------------------------------------------------------- /SCCM Build 2/Custom Roles/SCCM/Old/DownloadAdk.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory)] 3 | [string]$AdkDownloadPath 4 | ) 5 | 6 | $windowsAdkUrl = 'http://download.microsoft.com/download/3/1/E/31EC1AAF-3501-4BB4-B61C-8BD8A07B4E8A/adk/adksetup.exe' 7 | $adkSetup = Get-LabInternetFile -Uri $windowsAdkUrl -Path $labSources\SoftwarePackages -PassThru 8 | 9 | if (-not (Test-Path -Path $AdkDownloadPath)) 10 | { 11 | $p = Start-Process -FilePath $adkSetup.FullName -ArgumentList "/quiet /layout $AdkDownloadPath" -PassThru 12 | Write-ScreenInfo "Waiting for ADK to download files" -NoNewLine 13 | while (-not $p.HasExited) { 14 | Write-ScreenInfo '.' -NoNewLine 15 | Start-Sleep -Seconds 10 16 | } 17 | Write-ScreenInfo 'finished' 18 | } 19 | else 20 | { 21 | Write-ScreenInfo "ADK folder does already exist, skipping the download. Delete the folder '$AdkDownloadPath' if you want to download again." 22 | } -------------------------------------------------------------------------------- /SCCM Build 2/Custom Roles/SCCM/Old/DownloadSccm.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory)] 3 | [string]$SccmBinariesDirectory, 4 | 5 | [Parameter(Mandatory)] 6 | [string]$SccmPreReqsDirectory 7 | ) 8 | 9 | $sccm1702Url = 'http://download.microsoft.com/download/C/A/0/CA0CAE64-358C-49EC-9F61-8FACFEDE7083/SC_Configmgr_SCEP_1702.exe' 10 | $sccmSetup = Get-LabInternetFile -Uri $sccm1702Url -Path $labSources\SoftwarePackages -PassThru 11 | 12 | if (-not (Test-Path -Path $SccmBinariesDirectory)) 13 | { 14 | $pArgs = '/AUTO "{0}"' -f $SccmBinariesDirectory 15 | $p = Start-Process -FilePath $sccmSetup.FullName -ArgumentList $pArgs -PassThru 16 | Write-ScreenInfo "Waiting for extracting the SCCM files to '$SccmBinariesDirectory'" -NoNewLine 17 | while (-not $p.HasExited) { 18 | Write-ScreenInfo '.' -NoNewLine 19 | Start-Sleep -Seconds 10 20 | } 21 | Write-ScreenInfo 'finished' 22 | } 23 | else 24 | { 25 | Write-ScreenInfo "SCCM folder does already exist, skipping the download. Delete the folder '$SccmBinariesDirectory' if you want to download again." 26 | } 27 | 28 | if (-not (Test-Path -Path $SccmPreReqsDirectory)) 29 | { 30 | $p = Start-Process -FilePath $labSources\SoftwarePackages\SCCM1702\SMSSETUP\BIN\X64\setupdl.exe -ArgumentList $SccmPreReqsDirectory -PassThru 31 | Write-ScreenInfo "Waiting for downloading the SCCM Prerequisites to '$SccmPreReqsDirectory'" -NoNewLine 32 | while (-not $p.HasExited) { 33 | Write-ScreenInfo '.' -NoNewLine 34 | Start-Sleep -Seconds 10 35 | } 36 | Write-ScreenInfo 'finished' 37 | 38 | } 39 | else 40 | { 41 | Write-ScreenInfo "SCCM Prerequisites folder does already exist, skipping the download. Delete the folder '$SccmPreReqsDirectory' if you want to download again." 42 | } -------------------------------------------------------------------------------- /SCCM Build 2/Custom Roles/SCCM/Old/HostStart.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | 3 | [Parameter(Mandatory)] 4 | [string]$ComputerName, 5 | 6 | [Parameter(Mandatory)] 7 | [string]$SccmSiteCode, 8 | 9 | [Parameter(Mandatory)] 10 | [string]$SccmBinariesDirectory, 11 | 12 | [Parameter(Mandatory)] 13 | [string]$SccmPreReqsDirectory, 14 | 15 | [Parameter(Mandatory)] 16 | [string]$AdkDownloadPath, 17 | 18 | [Parameter(Mandatory)] 19 | [string]$SqlServerName 20 | ) 21 | 22 | $sqlServer = Get-LabVM -Role SQLServer | Where-Object Name -eq $SqlServerName 23 | $sccmServer = Get-LabVM -ComputerName $ComputerName 24 | if (-not $sqlServer) 25 | { 26 | Write-Error "The specified SQL Server '$SqlServerName' does not exist in the lab." 27 | return 28 | } 29 | 30 | if ($sccmServer.OperatingSystem.Version -lt 10.0 -or $SqlServer.OperatingSystem.Version -lt 10.0) 31 | { 32 | Write-Error "The SCCM role requires the SCCM server and the SQL Server to be Windows 2016 or higher." 33 | return 34 | } 35 | 36 | if ($SccmSiteCode -notmatch '^[A-Za-z0-9]{3}$') 37 | { 38 | Write-Error 'The site code must have exactly three characters and it can contain only alphanumeric characters (A to Z or 0 to 9).' 39 | return 40 | } 41 | 42 | $script = Get-Command -Name $PSScriptRoot\DownloadAdk.ps1 43 | $param = Sync-Parameter -Command $script -Parameters $PSBoundParameters 44 | & $PSScriptRoot\DownloadAdk.ps1 @param 45 | 46 | $script = Get-Command -Name $PSScriptRoot\DownloadSccm.ps1 47 | $param = Sync-Parameter -Command $script -Parameters $PSBoundParameters 48 | & $PSScriptRoot\DownloadSccm.ps1 @param 49 | 50 | $script = Get-Command -Name $PSScriptRoot\InstallSCCM.ps1 51 | $param = Sync-Parameter -Command $script -Parameters $PSBoundParameters 52 | & $PSScriptRoot\InstallSCCM.ps1 @param -------------------------------------------------------------------------------- /SCCM Build 2/Custom Roles/SCCM/Old/InstallSCCM.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Install a functional SCCM Primary Site using the Automated-Lab tookit with SCCM being installed using the "CustomRoles" approach 4 | .DESCRIPTION 5 | Long description 6 | .EXAMPLE 7 | PS C:\> 8 | Explanation of what the example does 9 | .INPUTS 10 | Inputs (if any) 11 | .OUTPUTS 12 | Output (if any) 13 | .NOTES 14 | General notes 15 | #> 16 | 17 | param( 18 | 19 | [Parameter(Mandatory)] 20 | [string]$ComputerName, 21 | 22 | [Parameter(Mandatory)] 23 | [string]$SccmBinariesDirectory, 24 | 25 | [Parameter(Mandatory)] 26 | [string]$SccmPreReqsDirectory, 27 | 28 | [Parameter(Mandatory)] 29 | [string]$SccmSiteCode, 30 | 31 | [Parameter(Mandatory)] 32 | [string]$SqlServerName 33 | ) 34 | 35 | function Install-SCCM { 36 | param 37 | ( 38 | [Parameter(Mandatory)] 39 | [string]$SccmServerName, 40 | 41 | [Parameter(Mandatory)] 42 | [string]$SccmBinariesDirectory, 43 | 44 | [Parameter(Mandatory)] 45 | [string]$SccmPreReqsDirectory, 46 | 47 | [Parameter(Mandatory)] 48 | [string]$SccmSiteCode, 49 | 50 | [Parameter(Mandatory)] 51 | [string]$SqlServerName 52 | ) 53 | 54 | $sccmServer = Get-LabVM -ComputerName $SccmServerName 55 | $sccmServerFqdn = $sccmServer.FQDN 56 | $sqlServer = Get-LabVM -Role SQLServer | Where-Object Name -eq $SqlServerName 57 | $sqlServerFqdn = $sqlServer.FQDN 58 | $rootDC = Get-LabVM -Role RootDC | Where-Object { $_.DomainName -eq $sccmServer.DomainName } 59 | 60 | if (-not $sqlServer) 61 | { 62 | Write-Error "The specified SQL Server '$SqlServerName' does not exist in the lab." 63 | return 64 | } 65 | 66 | $mdtDownloadLocation = 'https://download.microsoft.com/download/3/3/9/339BE62D-B4B8-4956-B58D-73C4685FC492/MicrosoftDeploymentToolkit_x64.msi' 67 | $downloadTargetFolder = "$labSources\SoftwarePackages" 68 | 69 | #Do Some quick checks before we get going 70 | #Check for existance of ADK Installation Files 71 | if (-not (Test-Path -Path "$downloadTargetFolder\ADK")) { 72 | Write-LogFunctionExitWithError -Message "ADK Installation files not located at '$downloadTargetFolder\ADK'" 73 | return 74 | } 75 | 76 | if (-not (Test-Path -Path $SccmBinariesDirectory)) { 77 | Write-LogFunctionExitWithError -Message "SCCM Installation files not located at '$($SccmBinariesDirectory)'" 78 | return 79 | } 80 | 81 | if (-not (Test-Path -Path $SccmPreReqsDirectory)) { 82 | Write-LogFunctionExitWithError -Message "SCCM PreRequisite files not located at '$($SccmPreReqsDirectory)'" 83 | return 84 | } 85 | 86 | #Bring all available disks online (this is to cater for the secondary drive) 87 | #For some reason, cant make the disk online and RW in the one command, need to perform two seperate actions 88 | Invoke-LabCommand -ActivityName 'Bring Disks Online' -ComputerName $SccmServerName -ScriptBlock { 89 | $dataVolume = Get-Disk | Where-Object -Property OperationalStatus -eq Offline 90 | $dataVolume | Set-Disk -IsOffline $false 91 | $dataVolume | Set-Disk -IsReadOnly $false 92 | } 93 | 94 | #Copy the SCCM Binaries 95 | Copy-LabFileItem -Path $SccmBinariesDirectory -DestinationFolderPath C:\Install -ComputerName $SccmServerName -Recurse 96 | #Copy the SCCM Prereqs (must have been previously downloaded) 97 | Copy-LabFileItem -Path $SccmPreReqsDirectory -DestinationFolderPath C:\Install -ComputerName $SccmServerName -Recurse 98 | 99 | #Extend the AD Schema 100 | Invoke-LabCommand -ActivityName 'Extend AD Schema' -ComputerName $SccmServerName -ScriptBlock { 101 | C:\Install\SCCM1702\SMSSETUP\BIN\X64\extadsch.exe 102 | } 103 | 104 | #Need to execute this command on the Domain Controller, since it has the AD Powershell cmdlets available 105 | #Create the Necessary OU and permissions for the SCCM container in AD 106 | Invoke-LabCommand -ActivityName 'Configure SCCM Systems Management Container' -ComputerName $rootDC -ScriptBlock { 107 | param 108 | ( 109 | [Parameter(Mandatory)] 110 | [string]$SCCMServerName 111 | ) 112 | 113 | Import-Module ActiveDirectory 114 | # Figure out our domain 115 | $rootDomainNc = (Get-ADRootDSE).defaultNamingContext 116 | 117 | # Get or create the System Management container 118 | $ou = $null 119 | try 120 | { 121 | $ou = Get-ADObject "CN=System Management,CN=System,$rootDomainNc" 122 | } 123 | catch 124 | { 125 | Write-Verbose "System Management container does not currently exist." 126 | $ou = New-ADObject -Type Container -name "System Management" -Path "CN=System,$rootDomainNc" -Passthru 127 | } 128 | 129 | # Get the current ACL for the OU 130 | $acl = Get-ACL -Path "ad:CN=System Management,CN=System,$rootDomainNc" 131 | 132 | # Get the computer's SID (we need to get the computer object, which is in the form $) 133 | $sccmComputer = Get-ADComputer "$SCCMServerName$" 134 | $sccmServerSId = [System.Security.Principal.SecurityIdentifier] $sccmComputer.SID 135 | 136 | $ActiveDirectoryRights = "GenericAll" 137 | $AccessControlType = "Allow" 138 | $Inherit = "SelfAndChildren" 139 | $nullGUID = [guid]'00000000-0000-0000-0000-000000000000' 140 | 141 | # Create a new access control entry to allow access to the OU 142 | $ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $sccmServerSId, $ActiveDirectoryRights, $AccessControlType, $Inherit, $nullGUID 143 | 144 | # Add the ACE to the ACL, then set the ACL to save the changes 145 | $acl.AddAccessRule($ace) 146 | Set-ACL -AclObject $acl "ad:CN=System Management,CN=System,$rootDomainNc" 147 | 148 | } -ArgumentList $SccmServerName 149 | 150 | Write-ScreenInfo -Message "Downloading MDT Installation Files from '$mdtDownloadLocation'" 151 | $mdtInstallFile = Get-LabInternetFile -Uri $mdtDownloadLocation -Path $downloadTargetFolder -ErrorAction Stop -PassThru 152 | 153 | Write-ScreenInfo "Copying MDT Install Files to server '$SccmServerName'..." 154 | Copy-LabFileItem -Path $mdtInstallFile.FullName -DestinationFolderPath C:\Install -ComputerName $SccmServerName 155 | 156 | Write-ScreenInfo "Copying ADK Install Files to server '$SccmServerName'..." 157 | Copy-LabFileItem -Path "$downloadTargetFolder\ADK" -DestinationFolderPath C:\Install -ComputerName $SccmServerName -Recurse 158 | 159 | Write-ScreenInfo "Installing ADK on server '$SccmServerName'..." -NoNewLine 160 | $job = Install-LabSoftwarePackage -LocalPath C:\Install\ADK\adksetup.exe -CommandLine "/norestart /q /ceip off /features OptionId.WindowsPreinstallationEnvironment OptionId.DeploymentTools OptionId.UserStateMigrationTool OptionId.ImagingAndConfigurationDesigner" ` 161 | -ComputerName $SccmServerName -NoDisplay -AsJob -PassThru 162 | Wait-LWLabJob -Job $job -NoDisplay 163 | 164 | Write-ScreenInfo "Installing .net 3.5 on '$SccmServerName'..." -NoNewLine 165 | $job = Install-LabWindowsFeature -ComputerName $SccmServerName -FeatureName NET-Framework-Core -NoDisplay -AsJob -PassThru 166 | Wait-LWLabJob -Job $job -NoDisplay 167 | 168 | Write-ScreenInfo "Installing WDS on '$SccmServerName'..." -NoNewLine 169 | $job = Install-LabWindowsFeature -ComputerName $SccmServerName -FeatureName WDS -NoDisplay -AsJob -PassThru 170 | Wait-LWLabJob -Job $job -NoDisplay 171 | 172 | Write-ScreenInfo "Installing 'MDT' on server '$SccmServerName'..." -NoNewLine 173 | Install-LabSoftwarePackage -ComputerName $SccmServerName -LocalPath "C:\Install\$($mdtInstallFile.FileName)" -CommandLine '/qb' -NoDisplay -AsJob -PassThru 174 | Wait-LWLabJob -Job $job -NoDisplay 175 | 176 | Invoke-LabCommand -ActivityName 'Configure WDS' -ComputerName $SccmServerName -ScriptBlock { 177 | Start-Process -FilePath "C:\Windows\System32\WDSUTIL.EXE" -ArgumentList "/Initialize-Server /RemInst:C:\RemoteInstall" -Wait 178 | Start-Sleep -Seconds 10 179 | Start-Process -FilePath "C:\Windows\System32\WDSUTIL.EXE" -ArgumentList "/Set-Server /AnswerClients:All" -Wait 180 | } 181 | 182 | #SCCM Needs a ton of additional features installed... 183 | Write-ScreenInfo "Installing a ton of additional features on server '$SccmServerName'..." -NoNewLine 184 | $job = Install-LabWindowsFeature -ComputerName $SccmServerName -FeatureName 'FS-FileServer,Web-Mgmt-Tools,Web-Mgmt-Console,Web-Mgmt-Compat,Web-Metabase,Web-WMI,Web-WebServer,Web-Common-Http,Web-Default-Doc,Web-Dir-Browsing,Web-Http-Errors,Web-Static-Content,Web-Http-Redirect,Web-Health,Web-Http-Logging,Web-Log-Libraries,Web-Request-Monitor,Web-Http-Tracing,Web-Performance,Web-Stat-Compression,Web-Dyn-Compression,Web-Security,Web-Filtering,Web-Windows-Auth,Web-App-Dev,Web-Net-Ext,Web-Net-Ext45,Web-Asp-Net,Web-Asp-Net45,Web-ISAPI-Ext,Web-ISAPI-Filter' -NoDisplay -AsJob -PassThru 185 | Wait-LWLabJob -Job $job -NoDisplay 186 | Write-ScreenInfo done 187 | 188 | $job = Install-LabWindowsFeature -ComputerName $SccmServerName -FeatureName 'NET-HTTP-Activation,NET-Non-HTTP-Activ,NET-Framework-45-ASPNET,NET-WCF-HTTP-Activation45,BITS,RDC' -NoDisplay -AsJob -PassThru 189 | Wait-LWLabJob -Job $job -NoDisplay 190 | Write-ScreenInfo done 191 | 192 | #Before we start the SCCM Install, restart the computer 193 | Write-ScreenInfo "Restarting server '$SccmServerName'..." -NoNewLine 194 | Restart-LabVM -ComputerName $SccmServerName -Wait -NoDisplay 195 | 196 | #Build the Installation unattended .INI file 197 | $setupConfigFileContent = @" 198 | [Identification] 199 | Action=InstallPrimarySite 200 | 201 | [Options] 202 | ProductID=EVAL 203 | SiteCode=$SccmSiteCode 204 | SiteName=Primary Site 1 205 | SMSInstallDir=C:\Program Files\Microsoft Configuration Manager 206 | SDKServer=$sccmServerFqdn 207 | RoleCommunicationProtocol=HTTPorHTTPS 208 | ClientsUsePKICertificate=0 209 | PrerequisiteComp=1 210 | PrerequisitePath=C:\Install\SCCMPreReqs 211 | MobileDeviceLanguage=0 212 | ManagementPoint=$sccmServerFqdn 213 | ManagementPointProtocol=HTTP 214 | DistributionPoint=$sccmServerFqdn 215 | DistributionPointProtocol=HTTP 216 | DistributionPointInstallIIS=0 217 | AdminConsole=1 218 | JoinCEIP=0 219 | 220 | [SQLConfigOptions] 221 | SQLServerName=$SqlServerFqdn 222 | DatabaseName=CM_$SccmSiteCode 223 | SQLSSBPort=4022 224 | SQLDataFilePath=C:\CMSQL\SQLDATA\ 225 | SQLLogFilePath=C:\CMSQL\SQLLOGS\ 226 | 227 | [CloudConnectorOptions] 228 | CloudConnector=0 229 | CloudConnectorServer=$sccmServerFqdn 230 | UseProxy=0 231 | 232 | [SystemCenterOptions] 233 | 234 | [HierarchyExpansionOption] 235 | "@ 236 | 237 | #Save the config file to disk, and copy it to the SCCM Server 238 | $setupConfigFileContent | Out-File -FilePath "$($lab.LabPath)\ConfigMgrUnattend.ini" -Encoding ascii 239 | 240 | Copy-LabFileItem -Path "$($lab.LabPath)\ConfigMgrUnattend.ini" -DestinationFolderPath C:\Install -ComputerName $SccmServerName 241 | 242 | $sccmComputerAccount = '{0}\{1}$' -f 243 | $sccmServer.DomainName.Substring(0, $sccmServer.DomainName.IndexOf('.')), 244 | $SccmServerName 245 | 246 | Invoke-LabCommand -ActivityName 'Create Folders for SQL DB' -ComputerName $sqlServer -ScriptBlock { 247 | #SQL Server does not like creating databases without the directories already existing, so make sure to create them first 248 | New-Item -Path 'C:\CMSQL\SQLDATA' -ItemType Directory -Force | Out-Null 249 | New-Item -Path 'C:\CMSQL\SQLLOGS' -ItemType Directory -Force | Out-Null 250 | 251 | if (-not (Get-LocalGroupMember -Group Administrators -Member $sccmComputerAccount -ErrorAction SilentlyContinue)) 252 | { 253 | Add-LocalGroupMember -Group Administrators -Member $sccmComputerAccount 254 | } 255 | } -Variable (Get-Variable -Name sccmComputerAccount) -NoDisplay 256 | 257 | Write-ScreenInfo 'Install SCCM. This step will take quite some time...' -NoNewLine 258 | $job = Install-LabSoftwarePackage -ComputerName $SccmServerName -LocalPath C:\Install\SCCM1702\SMSSETUP\BIN\X64\setup.exe -CommandLine '/Script "C:\Install\ConfigMgrUnattend.ini" /NoUserInput' -AsJob -PassThru 259 | Wait-LWLabJob -Job $job -NoDisplay 260 | } 261 | 262 | Write-ScreenInfo '' 263 | $lab = Import-Lab -Name $data.Name -NoValidation -NoDisplay -PassThru 264 | 265 | Install-SCCM -SccmServerName $ComputerName -SccmBinariesDirectory $SCCMBinariesDirectory -SccmPreReqsDirectory $SCCMPreReqsDirectory -SccmSiteCode $SCCMSiteCode -SqlServerName $SqlServerName -------------------------------------------------------------------------------- /SCCM Build 2/Custom Roles/SCCM/README.md: -------------------------------------------------------------------------------- 1 | # SCCM 2 | 3 | ## Defining the role 4 | 5 | ``` PowerShell 6 | $sccmRole = Get-LabPostInstallationActivity -CustomRole SCCM -Properties @{ 7 | SccmSiteCode = "CM1" 8 | SccmBinariesDirectory = "$labSources\SoftwarePackages\SCCM1702" 9 | SccmPreReqsDirectory = "$labSources\SoftwarePackages\SCCMPreReqs" 10 | AdkDownloadPath = "$labSources\SoftwarePackages\ADK" 11 | SqlServerName = 'SQL1' 12 | } 13 | 14 | Add-LabMachineDefinition -Name SCCM1 -Memory 4GB -OperatingSystem 'Windows Server 2016 Datacenter (Desktop Experience)' -DomainName contoso.com -PostInstallationActivity $sccmRole 15 | ``` 16 | 17 | Requires a SQL Server with collation 'SQL_Latin1_General_CP1_CI_AS' 18 | 19 | ``` PowerShell 20 | $sqlRole = Get-LabMachineRoleDefinition -Role SQLServer2017 -Properties @{ Collation = 'SQL_Latin1_General_CP1_CI_AS' } 21 | Add-LabMachineDefinition -Name SQL1 -Memory 2GB -OperatingSystem 'Windows Server 2016 Datacenter (Desktop Experience)' -DomainName contoso.com -Roles $sqlRole 22 | ``` -------------------------------------------------------------------------------- /SCCM Build 2/Props.ps1: -------------------------------------------------------------------------------- 1 | $LabProperties = @{ 2 | LabProps = @{ 3 | LabName = 'SCCMLAB1' 4 | VMPath = 'D:\AutomatedLab-VMs' 5 | ServerOS = 'Windows Server 2016 SERVERDATACENTER' 6 | ReferenceDiskSize = 80 7 | } 8 | SwitchProps = @{ 9 | SwitchType = 'External' 10 | AdapterName = 'EXT-04' 11 | ManagementAdapter = $true 12 | vSwitchName = 'SCCMLab' 13 | vLANid = '50' 14 | } 15 | NetworkProps = @{ 16 | AddressSpace = '192.168.50.0' 17 | DefaultGW = '192.168.50.252' 18 | Netmask = '24' 19 | DNSServers = '192.168.50.10' 20 | DNSServerFowarder = '192.168.10.254' 21 | DHCPScope = @{ 22 | Name = 'Default Scope' 23 | StartRange = '192.168.50.100' 24 | EndRange = '192.168.50.150' 25 | SubnetMask = '255.255.255.0' 26 | Description = 'Default Scope for Clients' 27 | LeaseDuration = '0.08:00:00' 28 | } 29 | DHCPScopeOptions = @{ 30 | DnsServer = '192.168.50.10' 31 | Router = '192.168.50.252' 32 | ScopeId = '192.168.50.100' 33 | DNSDomain = 'labtest.local' 34 | } 35 | } 36 | ADProps = @{ 37 | DomainName = 'labtest.local' 38 | DomainFunctionalLevel = 'Win2012R2' 39 | ForestFunctionalLevel = 'Win2012R2' 40 | OUStructure = @( 41 | @{Name="_Admin";ProtectedFromAccidentalDeletion=$false} 42 | @{Parent="OU=_Admin";Name="Service Accounts";Description="Service Accounts";ProtectedFromAccidentalDeletion=$false} 43 | @{Parent="OU=_Admin";Name="Privileged Users";Description="Admin User Accounts";ProtectedFromAccidentalDeletion=$false} 44 | @{Parent="OU=_Admin";Name="Privileged Groups";Description="Admin User Accounts";ProtectedFromAccidentalDeletion=$false} 45 | @{Name="_Workstations";ProtectedFromAccidentalDeletion=$false} 46 | @{Parent="OU=_Workstations";Name="Desktops";Description="Default Desktops";ProtectedFromAccidentalDeletion=$false} 47 | @{Parent="OU=_Workstations";Name="Staging";Description="Staging Desktop OU Used During Builds";ProtectedFromAccidentalDeletion=$false} 48 | @{Name="_Standard";ProtectedFromAccidentalDeletion=$false} 49 | @{Parent="OU=_Standard";Name="User Accounts";Description="Standard Users";ProtectedFromAccidentalDeletion=$false} 50 | @{Parent="OU=_Standard";Name="Groups";Description="Standard Groups";ProtectedFromAccidentalDeletion=$false} 51 | @{Parent="OU=_Standard";Name="Distribution Lists";Description="Exchange Distribution Lists";ProtectedFromAccidentalDeletion=$false} 52 | ) 53 | } 54 | SCCMInstallProps = @{ 55 | SccmSiteCode = "S01" 56 | SccmSiteName = "Primary Site" 57 | SccmBinariesDirectory = "$labSources\SoftwarePackages\SCCM1802" 58 | SccmPreReqsDirectory = "$labSources\SoftwarePackages\SCCMPreReqs1802" 59 | SccmInstallDirectory = "D:\Program Files\Microsoft Configuration Manager" 60 | AdkDownloadPath = "$labSources\SoftwarePackages\ADK1809" 61 | AdkWinPEDownloadPath = "$labSources\SoftwarePackages\ADK1809WinPEAddons" 62 | SqlServerName = "$($LabName)-DB1" 63 | } 64 | SccmConfigProps = @{ 65 | ServiceAccounts = @( 66 | @{Role="DJ";Name="svcDJ";SamAccountName="svcDJ";UserPrincipalName="svcDJ";Password="Password123";Description="SCCM Domain Join Account";Enabled=$true;Path="OU=Service Accounts, OU=_Admin";ChangePasswordAtLogon=$False;PasswordNeverExpires=$True} 67 | @{Role="CP";Name="svcPush";SamAccountName="svcPush";UserPrincipalName="svcPush";Password="Password123";Description="SCCM Client Push Account";Enabled=$true;Path="OU=Service Accounts, OU=_Admin";ChangePasswordAtLogon=$False;PasswordNeverExpires=$True} 68 | @{Role="NA";Name="svcNAA";SamAccountName="svcNAA";UserPrincipalName="svcNAA";Password="Password123";Description="SCCM Network Access Account";Enabled=$true;Path="OU=Service Accounts, OU=_Admin";ChangePasswordAtLogon=$False;PasswordNeverExpires=$True} 69 | ) 70 | DomainJoinAccountOUs = @( 71 | @{OUName="OU=Desktops,OU=_Workstations"} 72 | @{OUName="OU=Staging,OU=_Workstations"} 73 | @{OUName="CN=Computers"} 74 | ) 75 | BoundaryGroups = @( 76 | @{Name="Default Boundary Group";SiteCode="S01"} 77 | ) 78 | SiteBoundaries = @( 79 | @{Name="192.168.50.0 Boundary";IPRange="192.168.50.1-192.168.50.254";MemberOfBoundaryGroupName="Default Boundary Group"} 80 | @{Name="192.168.51.0 Boundary";IPRange="192.168.51.1-192.168.51.254";MemberOfBoundaryGroupName="Default Boundary Group"} 81 | @{Name="192.168.52.0 Boundary";IPRange="192.168.52.1-192.168.52.254";MemberOfBoundaryGroupName="Default Boundary Group"} 82 | ) 83 | DiscoveryMethods = @{ 84 | ActiveDirectorySystemDiscovery = @{ 85 | Settings = @{SiteCode = "S01";Enabled=$true;EnableDeltaDiscovery=$true;DeltaDiscoveryMins=30;ActiveDirectoryContainer="LDAP://DC=LABTEST,DC=LOCAL";Recursive=$true} 86 | Schedule = @{RecurInterval="Days";RecurCount=1;Start="01/01/2001"} 87 | } 88 | ActiveDirectoryUserDiscovery = @{ 89 | Settings = @{SiteCode = "S01";Enabled=$true;EnableDeltaDiscovery=$true;DeltaDiscoveryMins=30;ActiveDirectoryContainer="LDAP://DC=LABTEST,DC=LOCAL";Recursive=$true} 90 | Schedule = @{RecurInterval="Days";RecurCount=1;Start="01/01/2001"} 91 | } 92 | ActiveDirectoryGroupDiscovery = @{ 93 | Settings = @{SiteCode = "S01";Enabled=$true;EnableDeltaDiscovery=$true;DeltaDiscoveryMins=30;DiscoverDistributionGroupMembership = $true} 94 | Scope = @{ Name = 'AD Group Discovery';SiteCode = "S01";RecursiveSearch = $true;LdapLocation="LDAP://DC=LABTEST,DC=LOCAL"} 95 | Schedule = @{RecurInterval="Days";RecurCount=1;Start="01/01/2001"} 96 | } 97 | HeartbeatDiscovery = @{ 98 | Settings = @{SiteCode = "S01";Enabled=$true} 99 | Schedule = @{RecurInterval="Days";RecurCount=7} 100 | } 101 | } 102 | Collections = @{ 103 | DeviceCollections = @( 104 | @{ 105 | BasicSettings = @{Name = "All Servers";Comment = "All Servers";LimitingCollectionName="All Systems";RefreshType=2} 106 | Location = "Master Collections" 107 | Schedule = @{RecurInterval="Days";RecurCount=7} 108 | QueryMembershipRules = @( 109 | @{RuleName="All Servers";QueryExpression = "select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System where OperatingSystemNameandVersion like '%Server%'"} 110 | ) 111 | } 112 | @{ 113 | BasicSettings = @{Name = "All Workstations";Comment = "All Workstations";LimitingCollectionName="All Systems";RefreshType=2} 114 | Location = "Master Collections" 115 | Schedule = @{RecurInterval="Days";RecurCount=7} 116 | QueryMembershipRules = @( 117 | @{RuleName="All Workstations";QueryExpression = "select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System where OperatingSystemNameandVersion like '%Workstation%'"} 118 | ) 119 | } 120 | @{ 121 | BasicSettings = @{Name = "All Workstations - Admin";Comment = "All workstations admin, to hide from technician";LimitingCollectionName="All Systems";RefreshType=2} 122 | Location = "Master Collections" 123 | Schedule = @{RecurInterval="Days";RecurCount=7} 124 | QueryMembershipRules = @( 125 | @{RuleName="All Workstations - Admin";QueryExpression = "select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System where OperatingSystemNameandVersion like '%Workstation%'"} 126 | ) 127 | } 128 | @{ 129 | BasicSettings = @{Name = "MC - CS - Workstation Prod";Comment = "Prod client settings for workstations";LimitingCollectionName="All Workstations - Admin";RefreshType=2} 130 | Location = "Master Collections\MC - Client Settings" 131 | Schedule = @{RecurInterval="Days";RecurCount=7} 132 | IncludeMembershipRules = @( 133 | @{IncludeCollectionName="All Workstations"} 134 | ) 135 | } 136 | @{ 137 | BasicSettings = @{Name = "MC - CS - Workstation Test";Comment = "Test client settings for workstations";LimitingCollectionName="All Workstations - Admin";RefreshType=2} 138 | Location = "Master Collections\MC - Client Settings" 139 | Schedule = @{RecurInterval="Days";RecurCount=7} 140 | } 141 | @{ 142 | BasicSettings = @{Name = "MC - CS - Server Prod";Comment = "Prod client settings for servers";LimitingCollectionName="All Servers";RefreshType=2} 143 | Location = "Master Collections\MC - Client Settings" 144 | Schedule = @{RecurInterval="Days";RecurCount=7} 145 | IncludeMembershipRules = @( 146 | @{IncludeCollectionName="All Servers"} 147 | ) 148 | } 149 | @{ 150 | BasicSettings = @{Name = "MC - CS - Server Test";Comment = "Test client settings for servers";LimitingCollectionName="All Servers";RefreshType=2} 151 | Location = "Master Collections\MC - Client Settings" 152 | Schedule = @{RecurInterval="Days";RecurCount=7} 153 | } 154 | @{ 155 | BasicSettings = @{Name = "MC - EP - Workstation Prod";Comment = "Endpoint Protection Policy for Prod Workstations";LimitingCollectionName="All Workstations - Admin";RefreshType=2} 156 | Location = "Master Collections\MC - Endpoint Protection" 157 | Schedule = @{RecurInterval="Days";RecurCount=7} 158 | IncludeMembershipRules = @( 159 | @{IncludeCollectionName="All Servers"} 160 | ) 161 | } 162 | @{ 163 | BasicSettings = @{Name = "MC - EP - Workstation Test";Comment = "Endpoint Protection Policy for Test Workstations";LimitingCollectionName="All Workstations - Admin";RefreshType=2} 164 | Location = "Master Collections\MC - Endpoint Protection" 165 | Schedule = @{RecurInterval="Days";RecurCount=7} 166 | } 167 | @{ 168 | BasicSettings = @{Name = "MC - EP - Server Prod";Comment = "Endpoint Protection Policy for PROD servers";LimitingCollectionName="All Servers";RefreshType=2} 169 | Location = "Master Collections\MC - Endpoint Protection" 170 | Schedule = @{RecurInterval="Days";RecurCount=7} 171 | IncludeMembershipRules = @( 172 | @{IncludeCollectionName="All Servers"} 173 | ) 174 | } 175 | @{ 176 | BasicSettings = @{Name = "MC - EP - Server Test";Comment = "Endpoint Protection Policy for Test Servers";LimitingCollectionName="All Servers";RefreshType=2} 177 | Location = "Master Collections\MC - Endpoint Protection" 178 | Schedule = @{RecurInterval="Days";RecurCount=7} 179 | } 180 | @{ 181 | BasicSettings = @{Name = "SRV - INV - Physical";Comment = "All physical servers";LimitingCollectionName="All Servers";RefreshType=2} 182 | Location = "Servers\SRV - Inventory\SRV - Hardware" 183 | Schedule = @{RecurInterval="Days";RecurCount=7} 184 | QueryMembershipRules = @( 185 | @{RuleName="SRV - INV - Physical";QueryExpression = "select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System where SMS_R_System.ResourceId not in (select SMS_R_SYSTEM.ResourceID from SMS_R_System inner join SMS_G_System_COMPUTER_SYSTEM on SMS_G_System_COMPUTER_SYSTEM.ResourceId = SMS_R_System.ResourceId where SMS_R_System.IsVirtualMachine = 'True') and SMS_R_System.OperatingSystemNameandVersion like 'Microsoft Windows NT%Server%'"} 186 | ) 187 | } 188 | @{ 189 | BasicSettings = @{Name = "SRV - INV - Virtual";Comment = "All virtual servers";LimitingCollectionName="All Servers";RefreshType=2} 190 | Location = "Servers\SRV - Inventory\SRV - Hardware" 191 | Schedule = @{RecurInterval="Days";RecurCount=7} 192 | QueryMembershipRules = @( 193 | @{RuleName="SRV - INV - Virtual";QueryExpression = "select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System where SMS_R_System.IsVirtualMachine = 'True' and SMS_R_System.OperatingSystemNameandVersion like 'Microsoft Windows NT%Server%'"} 194 | ) 195 | } 196 | @{ 197 | BasicSettings = @{Name = "SRV - INV - Windows 2008 and 2008 R2";Comment = "All servers with Windows 2008 or 2008 R2 operating system";LimitingCollectionName="All Servers";RefreshType=2} 198 | Location = "Servers\SRV - Inventory\SRV - Operating System" 199 | Schedule = @{RecurInterval="Days";RecurCount=7} 200 | QueryMembershipRules = @( 201 | @{RuleName="SRV - INV - Windows 2008 and 2008 R2";QueryExpression = "select SMS_R_System.ResourceID,SMS_R_System.ResourceType,SMS_R_System.Name,SMS_R_System.SMSUniqueIdentifier,SMS_R_System.ResourceDomainORWorkgroup,SMS_R_System.Client from SMS_R_System where OperatingSystemNameandVersion like '%Server 6.0%' or OperatingSystemNameandVersion like '%Server 6.1%'"} 202 | ) 203 | } 204 | @{ 205 | BasicSettings = @{Name = "SRV - INV - Windows 2012 and 2012 R2";Comment = "All servers with Windows 2012 or 2012 R2 operating system";LimitingCollectionName="All Servers";RefreshType=2} 206 | Location = "Servers\SRV - Inventory\SRV - Operating System" 207 | Schedule = @{RecurInterval="Days";RecurCount=7} 208 | QueryMembershipRules = @( 209 | @{RuleName = "SRV - INV - Windows 2012 and 2012 R2"; QueryExpression = "select SMS_R_System.ResourceID,SMS_R_System.ResourceType,SMS_R_System.Name,SMS_R_System.SMSUniqueIdentifier,SMS_R_System.ResourceDomainORWorkgroup,SMS_R_System.Client from SMS_R_System where OperatingSystemNameandVersion like '%Server 6.2%' or OperatingSystemNameandVersion like '%Server 6.3%'"} 210 | ) 211 | } 212 | @{ 213 | BasicSettings = @{Name = "SRV - INV - Windows 2003 and 2003 R2";Comment = "All servers with Windows 2003 or 2003 R2 operating system";LimitingCollectionName="All Servers";RefreshType=2} 214 | Location = "Servers\SRV - Inventory\SRV - Operating System" 215 | Schedule = @{RecurInterval="Days";RecurCount=7} 216 | QueryMembershipRules = @( 217 | @{RuleName = "SRV - INV - Windows 2003 and 2003 R2"; QueryExpression = "select SMS_R_System.ResourceID,SMS_R_System.ResourceType,SMS_R_System.Name,SMS_R_System.SMSUniqueIdentifier,SMS_R_System.ResourceDomainORWorkgroup,SMS_R_System.Client from SMS_R_System where OperatingSystemNameandVersion like '%Server 5.2%'"} 218 | ) 219 | } 220 | @{ 221 | BasicSettings = @{Name = "SRV - INV - Windows 2016";Comment = "All servers with Windows 2016";LimitingCollectionName="All Servers";RefreshType=2} 222 | Location = "Servers\SRV - Inventory\SRV - Operating System" 223 | Schedule = @{RecurInterval="Days";RecurCount=7} 224 | QueryMembershipRules = @( 225 | @{RuleName = "SRV - INV - Windows 2016"; QueryExpression = "select SMS_R_System.ResourceID,SMS_R_System.ResourceType,SMS_R_System.Name,SMS_R_System.SMSUniqueIdentifier,SMS_R_System.ResourceDomainORWorkgroup,SMS_R_System.Client from SMS_R_System where OperatingSystemNameandVersion like '%Server 10%'"} 226 | ) 227 | } 228 | @{ 229 | BasicSettings = @{Name = "WKS - INV - Windows 7";Comment = "All workstations with Windows 7 operating system";LimitingCollectionName="All Workstations";RefreshType=2} 230 | Location = "Workstations\WKS - Inventory\WKS - Operating System" 231 | Schedule = @{RecurInterval="Days";RecurCount=7} 232 | QueryMembershipRules = @( 233 | @{RuleName = "WKS - INV - Windows 7"; QueryExpression = "select SMS_R_System.ResourceID,SMS_R_System.ResourceType,SMS_R_System.Name,SMS_R_System.SMSUniqueIdentifier,SMS_R_System.ResourceDomainORWorkgroup,SMS_R_System.Client from SMS_R_System where OperatingSystemNameandVersion like '%Workstation 6.1%'"} 234 | ) 235 | } 236 | @{ 237 | BasicSettings = @{Name = "WKS - INV - Windows 8";Comment = "All workstations with Windows 8 operating system";LimitingCollectionName="All Workstations";RefreshType=2} 238 | Location = "Workstations\WKS - Inventory\WKS - Operating System" 239 | Schedule = @{RecurInterval="Days";RecurCount=7} 240 | QueryMembershipRules = @( 241 | @{RuleName = "WKS - INV - Windows 8"; QueryExpression = "select SMS_R_System.ResourceID,SMS_R_System.ResourceType,SMS_R_System.Name,SMS_R_System.SMSUniqueIdentifier,SMS_R_System.ResourceDomainORWorkgroup,SMS_R_System.Client from SMS_R_System where OperatingSystemNameandVersion like '%Workstation 6.2%'"} 242 | ) 243 | } 244 | @{ 245 | BasicSettings = @{Name = "WKS - INV - Windows 8.1";Comment = "All workstations with Windows 8.1 operating system";LimitingCollectionName="All Workstations";RefreshType=2} 246 | Location = "Workstations\WKS - Inventory\WKS - Operating System" 247 | Schedule = @{RecurInterval="Days";RecurCount=7} 248 | QueryMembershipRules = @( 249 | @{RuleName = "WKS - INV - Windows 8.1"; QueryExpression = "select SMS_R_System.ResourceID,SMS_R_System.ResourceType,SMS_R_System.Name,SMS_R_System.SMSUniqueIdentifier,SMS_R_System.ResourceDomainORWorkgroup,SMS_R_System.Client from SMS_R_System where OperatingSystemNameandVersion like '%Workstation 6.3%'"} 250 | ) 251 | } 252 | @{ 253 | BasicSettings = @{Name = "WKS - INV - Windows XP";Comment = "All workstations with Windows XP operating system";LimitingCollectionName="All Workstations";RefreshType=2} 254 | Location = "Workstations\WKS - Inventory\WKS - Operating System" 255 | Schedule = @{RecurInterval="Days";RecurCount=7} 256 | QueryMembershipRules = @( 257 | @{RuleName = "WKS - INV - Windows XP"; QueryExpression = "select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System where OperatingSystemNameandVersion like '%Workstation 5.1%' or OperatingSystemNameandVersion like '%Workstation 5.2%'"} 258 | ) 259 | } 260 | @{ 261 | BasicSettings = @{Name = "WKS - INV - SCCM Console";Comment = "All systems with SCCM console installed";LimitingCollectionName="All Workstations";RefreshType=2} 262 | Location = "Workstations\WKS - Inventory\WKS - Software" 263 | Schedule = @{RecurInterval="Days";RecurCount=7} 264 | QueryMembershipRules = @( 265 | @{RuleName = "WKS - INV - SCCM Console"; QueryExpression = "select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System inner join SMS_G_System_ADD_REMOVE_PROGRAMS on SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId where SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName like '%Configuration Manager Console%'"} 266 | ) 267 | } 268 | @{ 269 | BasicSettings = @{Name = "WKS - INV - Clients Version | 1710";Comment = "SCCM client version 1710";LimitingCollectionName="All Workstations";RefreshType=2} 270 | Location = "Workstations\WKS - Inventory\WKS - Software" 271 | Schedule = @{RecurInterval="Days";RecurCount=7} 272 | QueryMembershipRules = @( 273 | @{RuleName = "WKS - INV - Clients Version | 1710"; QueryExpression = "select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System where SMS_R_System.ClientVersion like '5.00.8577.100%'"} 274 | ) 275 | } 276 | @{ 277 | BasicSettings = @{Name = "WKS - INV - Laptops | Dell";Comment = "All Dell Laptops";LimitingCollectionName="All Workstations";RefreshType=2} 278 | Location = "Workstations\WKS - Inventory\WKS - Hardware" 279 | Schedule = @{RecurInterval="Days";RecurCount=7} 280 | QueryMembershipRules = @( 281 | @{RuleName = "WKS - INV - Laptops | Dell"; QueryExpression = "select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System inner join SMS_G_System_COMPUTER_SYSTEM on SMS_G_System_COMPUTER_SYSTEM.ResourceId = SMS_R_System.ResourceId where SMS_G_System_COMPUTER_SYSTEM.Manufacturer like '%Dell%'"} 282 | ) 283 | } 284 | @{ 285 | BasicSettings = @{Name = "WKS - INV - Laptops | Lenovo";Comment = "All Lenovo Laptops";LimitingCollectionName="All Workstations";RefreshType=2} 286 | Location = "Workstations\WKS - Inventory\WKS - Hardware" 287 | Schedule = @{RecurInterval="Days";RecurCount=7} 288 | QueryMembershipRules = @( 289 | @{RuleName = "WKS - INV - Laptops | Lenovo"; QueryExpression = "select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System inner join SMS_G_System_COMPUTER_SYSTEM on SMS_G_System_COMPUTER_SYSTEM.ResourceId = SMS_R_System.ResourceId where SMS_G_System_COMPUTER_SYSTEM.Manufacturer like '%Lenovo%'"} 290 | ) 291 | } 292 | @{ 293 | BasicSettings = @{Name = "WKS - INV - Laptops | HP";Comment = "All HP Laptops";LimitingCollectionName="All Workstations";RefreshType=2} 294 | Location = "Workstations\WKS - Inventory\WKS - Hardware" 295 | Schedule = @{RecurInterval="Days";RecurCount=7} 296 | QueryMembershipRules = @( 297 | @{RuleName = "WKS - INV - Laptops | HP"; QueryExpression = "select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System inner join SMS_G_System_COMPUTER_SYSTEM on SMS_G_System_COMPUTER_SYSTEM.ResourceId = SMS_R_System.ResourceId where SMS_G_System_COMPUTER_SYSTEM.Manufacturer like '%HP%' or SMS_G_System_COMPUTER_SYSTEM.Manufacturer like '%Hewlett-Packard%'"} 298 | ) 299 | } 300 | @{ 301 | BasicSettings = @{Name = "WKS - INV - Microsoft Surface 4";Comment = "All Microsoft Surface 4 Laptops";LimitingCollectionName="All Workstations";RefreshType=2} 302 | Location = "Workstations\WKS - Inventory\WKS - Hardware" 303 | Schedule = @{RecurInterval="Days";RecurCount=7} 304 | QueryMembershipRules = @( 305 | @{RuleName = "WKS - INV - Microsoft Surface 4"; QueryExpression = "select SMS_R_System.ResourceId, SMS_R_System.ResourceType, SMS_R_System.Name, SMS_R_System.SMSUniqueIdentifier, SMS_R_System.ResourceDomainORWorkgroup, SMS_R_System.Client from SMS_R_System inner join SMS_G_System_COMPUTER_SYSTEM on SMS_G_System_COMPUTER_SYSTEM.ResourceId = SMS_R_System.ResourceId where SMS_G_System_COMPUTER_SYSTEM.Model = 'Surface Pro 4'"} 306 | ) 307 | } 308 | @{ 309 | BasicSettings = @{Name = "WKS - INV - Windows 10";Comment = "All workstations with Windows 10 operating system";LimitingCollectionName="All Workstations";RefreshType=2} 310 | Location = "Workstations\WKS - Inventory\WKS - Operating System" 311 | Schedule = @{RecurInterval="Days";RecurCount=7} 312 | QueryMembershipRules = @( 313 | @{RuleName = "WKS - INV - Windows 10"; QueryExpression = "select SMS_R_System.ResourceID,SMS_R_System.ResourceType,SMS_R_System.Name,SMS_R_System.SMSUniqueIdentifier,SMS_R_System.ResourceDomainORWorkgroup,SMS_R_System.Client from SMS_R_System where OperatingSystemNameandVersion like '%Workstation 10.%'"} 314 | ) 315 | } 316 | @{ 317 | BasicSettings = @{Name = "WKS - OSD - Windows 10 - PROD";Comment = "OSD Collection for Windows 10 deployment in production";LimitingCollectionName="All Workstations";RefreshType=2} 318 | Location = "Workstations\WKS - OS Deployment" 319 | Schedule = @{RecurInterval="Days";RecurCount=7} 320 | } 321 | @{ 322 | BasicSettings = @{Name = "WKS - OSD - Windows 10 - TEST";Comment = "OSD collection to test deployment of Windows 10. Limited to admins only";LimitingCollectionName="All Workstations - Admin";RefreshType=2} 323 | Location = "Workstations\WKS - OS Deployment" 324 | Schedule = @{RecurInterval="Days";RecurCount=7} 325 | } 326 | @{ 327 | BasicSettings = @{Name = "WKS - SU - Exclusion";Comment = "Software Update collection to exclude computers from all Software Update collections. Manual Membership";LimitingCollectionName="All Workstations - Admin";RefreshType=2} 328 | Location = "Workstations\WKS - Software Update" 329 | Schedule = @{RecurInterval="Days";RecurCount=7} 330 | } 331 | @{ 332 | BasicSettings = @{Name = "WKS - SU - Pilot";Comment = "Software Update collection for Pilot group. Manual membership";LimitingCollectionName="All Workstations - Admin";RefreshType=2} 333 | Location = "Workstations\WKS - Software Update" 334 | Schedule = @{RecurInterval="Days";RecurCount=7} 335 | ExcludeMembershipRules = @( 336 | @{ExcludeCollectionName="WKS - SU - Exclusion"} 337 | ) 338 | } 339 | @{ 340 | BasicSettings = @{Name = "WKS - SU - TEST";Comment = "Software Update collection for test group. Manual membership";LimitingCollectionName="All Workstations - Admin";RefreshType=2} 341 | Location = "Workstations\WKS - Software Update" 342 | Schedule = @{RecurInterval="Days";RecurCount=7} 343 | ExcludeMembershipRules = @( 344 | @{ExcludeCollectionName="WKS - SU - Exclusion"} 345 | ) 346 | } 347 | @{ 348 | BasicSettings = @{Name = "WKS - SU - PROD";Comment = "Software Update collection for Production. All workstations";LimitingCollectionName="All Workstations - Admin";RefreshType=2} 349 | Location = "Workstations\WKS - Software Update" 350 | Schedule = @{RecurInterval="Days";RecurCount=7} 351 | ExcludeMembershipRules = @( 352 | @{ExcludeCollectionName="WKS - SU - Exclusion"} 353 | ) 354 | IncludeMembershipRules = @( 355 | @{IncludeCollectionName="All Workstations"} 356 | ) 357 | } 358 | @{ 359 | BasicSettings = @{Name = "WKS - SD - Office 365 - PROD";Comment = "Collection for deployment of Office 365 production";LimitingCollectionName="All Workstations";RefreshType=2} 360 | Location = "Workstations\WKS - Software Distribution" 361 | Schedule = @{RecurInterval="Days";RecurCount=7} 362 | } 363 | @{ 364 | BasicSettings = @{Name = "WKS - SD - Office 365 - TEST";Comment = "Test Collection for deployment of Office 365. Limited to admins only.";LimitingCollectionName="All Workstations - Admin";RefreshType=2} 365 | Location = "Workstations\WKS - Software Distribution" 366 | Schedule = @{RecurInterval="Days";RecurCount=7} 367 | } 368 | ) 369 | } 370 | WSUSProps = @{ 371 | ContentDirectory='F:\WSUS' 372 | UpdateLanguages= @( 373 | 'English' 374 | ) 375 | DisabledProducts = @( 376 | ) 377 | EnabledProducts = @( 378 | 'Windows Server 2016' 379 | 'Windows Server 2012 R2' 380 | 'Windows 10' 381 | 'Office 2010' 382 | 'Office 2016' 383 | ) 384 | EnabledProductFamilies = @( 385 | ) 386 | DisabledClassifications = @( 387 | 'Tools' 388 | ) 389 | EnabledClassifications = @( 390 | 'Critical Updates' 391 | 'Definition Updates' 392 | 'Feature Packs' 393 | 'Security Updates' 394 | 'Service Packs' 395 | 'Update Rollups' 396 | 'Updates' 397 | 'Upgrades' 398 | ) 399 | Schedule = @{RecurInterval="Days";RecurCount=3} 400 | } 401 | DistributionPointProps = @( 402 | @{ 403 | DistributionPointName = "SCCMLAB1-CM1.LABTEST.LOCAL" 404 | GeneralProps = @{ClientCommunicationType="HTTP"} 405 | PXEProps = @{EnablePxe=$True;PxeServerResponseDelaySeconds=0;AllowPxeResponse=$True;EnableUnknownComputerSupport=$True;UserDeviceAffinity="DoNotUse"} 406 | ValidationProps = @{EnableContentValidation=$True;Schedule = @{RecurInterval="Days";RecurCount=3}} 407 | } 408 | ) 409 | } 410 | } 411 | 412 | ConvertTo-Json $LabProperties -Depth 7 | Set-Content -Path $PSScriptRoot\SCCMProps.json 413 | -------------------------------------------------------------------------------- /SCCM Build 2/readme.md: -------------------------------------------------------------------------------- 1 | # Main 2 | 3 | This script is designed to deploy Microsoft System Centre Configuration Manager (Current Branch) using Automated-Lab as the base deployment toolkit 4 | 5 | This is a highly enhanced version of the CustomRoles toolkit in Automated Lab, and is designed to produce a fully-configured SCCM platform for build and deployment testing 6 | 7 | Prerequisites: 8 | 9 | - Installed version of Automated-Lab 10 | - Download of the Microsoft Assessment and Deployment Kit - available here: 11 | https://developer.microsoft.com/en-us/windows/hardware/windows-assessment-deployment-kit 12 | - Tested with 1809 Version 13 | - A Server operating system image for a three machine AL machine deployment (Domain Controller, SCCM Server, SQL Server): 14 | - Tested with Windows Server 2016 for all roles 15 | - SCCM Requires SQL Server installed, assumed that existing AL SQL Role deployment method is used. 16 | - Tested with SQL Server 2017 17 | - SCCM Prerequisites downloaded using SETUPDL.EXE, available in SCCM package in .\SMSSETUP\BIN\X64. 18 | - Tested with SCCM 1802 19 | 20 | Known Restrictions/Limitations: 21 | 22 | - Currently tested with a single AD Domain, Dedicated SCCM, and dedicated SQL Server 23 | - Lab is using the new VLAN configuration component of AL 24 | - SCCM Server has 3 additional drives attached for SCCM DP content, Sources, and WSUS Content, currently configured as 200gb each. Sizes can be changed based on requirements, but SCCM is a disk hog 25 | - A minimum of 12gb of memory + multiple vCPU's is recommended due to number of running processes across the three servers. DC can safely drop to 2gb if there are memory constraints 26 | - SCCM Requires a specific SQL collation setting, which needs to be specific during the Virtual Machine definition phase: 27 | 28 | ```ps 29 | $roles = (Get-LabMachineRoleDefinition -Role SQLServer2014 -Properties @{ Collation = 'SQL_Latin1_General_CP1_CI_AS' }) 30 | Add-LabDiskDefinition -Name SCCMData -DiskSizeInGb 100 31 | Add-LabMachineDefinition -Name $SCCMServerName -DiskName SCCMData -Memory 4GB -Processors 4 -Roles $roles -IpAddress '192.168.40.20' 32 | ``` 33 | 34 | - All SCCM Generated certificates are self-signed, solution does not currently integrate with Certificate Services 35 | - Note that the Breakdown of activities for SCCM configuration may not be ideal and does result in additional execution time to reload powershell modules / reconnect to SCCM site servers, however this is deliberate to allow specific functions to be disabled so manual configuration can be done as part of training / documentation development activities. 36 | 37 | This script is a work in progress, there are some assumptions made resulting in some lack of error checking. Additional enhancements are in the pipeline, and are managed as enhancement requests within GitHub 38 | 39 | Projected Functionality and Current Status 40 | - AD Domain Build - Complete 41 | - DHCP Server and Scopes - Complete 42 | - OU Structure - Complete (23/03) 43 | - DNS Forwarder Fix (AL currently configures an Azure Forwarder which must be replaced) 44 | - SQL Server Build - Complete (currently restricted to a single drive for all content) 45 | - SCCM Server build - Base Install Complete 46 | - Windows Deployment Server - Base Install Complete 47 | - DHCP / PXE listen configuration - Complete 48 | - Boot Image Generation - Missing 49 | - Domain Join account created in AD and SCCM with premission restrictions on OU's - Complete 50 | - WSUS Install - Base Install Complete 51 | - Update of base products and components - Complete 52 | - Customisation of content types to download - Complete (23/03) 53 | - SCCM SUP Role - Complete (23/03) 54 | - Network Access Account in AD and SCCM + CM Config for Software Distribution Component - Complete 55 | - Client Push Account in AD and SCCM + CM Config for Client Push Installation - Complete 56 | - Default SCCM Boundary + Boundary Group creation - Complete 57 | - AD System Discovery - Complete 58 | - AD User Discovery - Complete 59 | - AD Group Discovery - Complete 60 | - Distribution Point Role - Missing 61 | - SCCM MDT Integration - Missing 62 | - Device Collections - Complete (23/03) 63 | 64 | Update 11/03/19: 65 | Major changes to the build process, the majority (soon all) settings are gathered from a JSON file stored in the same directory as the script. This file has settings subheading for all components. 66 | 67 | This has resulted in a few changes: 68 | 69 | 1. All settings will be migrated to the config file. Currently there is some overlap for the main AL install process, however local variables have been created from settings in the config file. Eventually all settings will be pulled directly from the config file 70 | 2. The config file is based on my requirements for testing, so there are some configuration settings that may be less than ideal for a different setup (eg VLAN's). This mainly applies to the AL-Lab itself 71 | 3. Where possible, a non-specific approach for settings is being taken to aid in flexibility without requiring modifications to the main script. For example, AD OU Structure is completely arbitrary, and additional OU's can be added / removed. Current settings that are known to work: 72 | 1. OU's (Note: OU's currently need to be created in a sequential order due to parent OU's needing to exist before the child is created) 73 | 2. SCCM Service Accounts 74 | 3. SCCM Domain Join Account OU's 75 | 4. SCCM Boundary Groups 76 | 5. SCCM Site Boundaries 77 | 4. Splatting is now used for most functions directly from the config file content (for some fields in functions, ie passwords that need ConvertTo-SecureString, some surrounding code is still used) 78 | 5. A MAJOR advantage of this new approach is that additional parameter settings for most cmdlets (for example New-ADUser for SCCM service accounts) can be added directly to the config file without requiring code changes. For example, add an office, phone number, ManagedBy field to an object. **NOTE:** The splatting processes makes no assumptions regarding parameter sets / invalid parameter types and the like pulled in from the Config File, all provided values will be passed to the function regardless. 79 | 6. Due to the behaviour of ConvertFrom-JSON when reading in the config file resulting in a complex PSCustomObject variable (and not the expected array / hashtable), additional conversions are required to convert these structures to HashTables to be used for splatting. For functions using the Invoke-LabCommand, the ConvertTo-PSObjectToHash function needs to be placed inside the ScriptBlock to allow these conversions to occur. 80 | 81 | # Configuration File 82 | 83 | The config file is stored and created using the Props.ps1 file. Due to the way the object is constructed, comments are difficult to include, so are documented here 84 | 85 | ## LabProps 86 | 87 | ```powershell 88 | LabProps = @{ 89 | LabName = 'SCCMLAB1' 90 | VMPath = 'D:\AutomatedLab-VMs' 91 | ServerOS = 'Windows Server 2016 SERVERDATACENTER' 92 | ReferenceDiskSize = 80 93 | } 94 | ``` 95 | 96 | LabProps is a hashtable of the settings for the automatedLab itself 97 | 98 | ## SwitchProps 99 | 100 | ```powershell 101 | SwitchProps = @{ 102 | SwitchType = 'External' 103 | AdapterName = 'EXT-04' 104 | ManagementAdapter = $true 105 | vSwitchName = 'SCCMLab' 106 | vLANid = '50' 107 | } 108 | ``` 109 | 110 | SwitchProps is a hashtable for the main script, and defines the configuration of the switch that is created for the lab to connect to. Note that the current main script code is expecting some of these values (such as vLanID) 111 | 112 | ## NetworkProps 113 | 114 | ```powershell 115 | NetworkProps = @{ 116 | AddressSpace = '192.168.50.0' 117 | DefaultGW = '192.168.50.252' 118 | Netmask = '24' 119 | DNSServers = '192.168.50.10' 120 | DNSServerFowarder = '192.168.10.254' 121 | DHCPScope = @{ 122 | Name = 'Default Scope' 123 | StartRange = '192.168.50.100' 124 | EndRange = '192.168.50.150' 125 | SubnetMask = '255.255.255.0' 126 | Description = 'Default Scope for Clients' 127 | LeaseDuration = '0.08:00:00' 128 | } 129 | DHCPScopeOptions = @{ 130 | DnsServer = '192.168.50.10' 131 | Router = '192.168.50.252' 132 | ScopeId = '192.168.50.100' 133 | DNSDomain = 'labtest.local' 134 | } 135 | } 136 | ``` 137 | 138 | NetworkProps defines the overall networking configuration for the lab (AddressSpace, DefaultGW, NetMask, DNSServers). The remaining configuration items are used to configure the DHCP scope inside the lab on the Domain controller. DHCPScope and DHCPScopeOptions can have additional parameters includes where the called functions support it: 139 | 140 | * Add-DHCPServerv4Scope for DHCPScope 141 | * Set-DhcpServerV4OptionValue for DHCPScopeOptions 142 | 143 | ## ADProps 144 | 145 | ```powershell 146 | ADProps = @{ 147 | DomainName = 'labtest.local' 148 | DomainFunctionalLevel = 'Win2012R2' 149 | ForestFunctionalLevel = 'Win2012R2' 150 | OUStructure = @( 151 | @{Name="_Admin";ProtectedFromAccidentalDeletion=$false} 152 | @{Parent="OU=_Admin";Name="Service Accounts";Description="Service Accounts";ProtectedFromAccidentalDeletion=$false} 153 | @{Parent="OU=_Admin";Name="Privileged Users";Description="Admin User Accounts";ProtectedFromAccidentalDeletion=$false} 154 | @{Parent="OU=_Admin";Name="Privileged Groups";Description="Admin User Accounts";ProtectedFromAccidentalDeletion=$false} 155 | @{Name="_Workstations";ProtectedFromAccidentalDeletion=$false} 156 | @{Parent="OU=_Workstations";Name="Desktops";Description="Default Desktops";ProtectedFromAccidentalDeletion=$false} 157 | @{Parent="OU=_Workstations";Name="Staging";Description="Staging Desktop OU Used During Builds";ProtectedFromAccidentalDeletion=$false} 158 | @{Name="_Standard";ProtectedFromAccidentalDeletion=$false} 159 | @{Parent="OU=_Standard";Name="User Accounts";Description="Standard Users";ProtectedFromAccidentalDeletion=$false} 160 | @{Parent="OU=_Standard";Name="Groups";Description="Standard Groups";ProtectedFromAccidentalDeletion=$false} 161 | @{Parent="OU=_Standard";Name="Distribution Lists";Description="Exchange Distribution Lists";ProtectedFromAccidentalDeletion=$false} 162 | ) 163 | } 164 | ``` 165 | 166 | ADProps defines the Active Directory settings. DomainName, DomainFunctionalLevel, and ForestFunctionalLevel are used as part of the AutomatedLab process, with OUStructure being used to create OU's on the Domain Controller. OUStructure is defined as an array of hashtables, and additional parameters can be included provided the **New-ADOrganizationalUnit** cmdlet supports them and the key name must match the parameter name for the cmdlet. The minimum key/value that needs to be provided is "Name" as this will be the name of the new OU. Currently, the OU structure needs to be entered into the configuration file in a specific order, noting that parent OU's need to exist before the child OU is created. Note: by default in recent windows versions, OU's are automatically created with the protection flag enabled, so **ProtectedFromAccidentalDeletion=$false** will need to be included for each OU that you dont want this flag set for. The list of OU's is completely arbitrary, and can be as long as required. 167 | 168 | ## SCCMInstallProps 169 | 170 | ```powershell 171 | SCCMInstallProps = @{ 172 | SccmSiteCode = "S01" 173 | SccmSiteName = "Primary Site" 174 | SccmBinariesDirectory = "$labSources\SoftwarePackages\SCCM1802" 175 | SccmPreReqsDirectory = "$labSources\SoftwarePackages\SCCMPreReqs1802" 176 | SccmInstallDirectory = "D:\Program Files\Microsoft Configuration Manager" 177 | AdkDownloadPath = "$labSources\SoftwarePackages\ADK1809" 178 | AdkWinPEDownloadPath = "$labSources\SoftwarePackages\ADK1809WinPEAddons" 179 | SqlServerName = "$($LabName)-DB1" 180 | } 181 | ``` 182 | 183 | SCCMInstallProps defines the parameters required for the SCCM Custom role. Currently, this is not used, rather the parameters should be modified in the main script 184 | 185 | ## SCCMConfigProps 186 | 187 | The SCCMConfigProps section contains all SCCM configuration items, and due to its complexity, each sub-section is discussed individually 188 | 189 | ### ServiceAccounts 190 | 191 | ```powershell 192 | ServiceAccounts = @( 193 | @{Role="DJ";Name="svcDJ";SamAccountName="svcDJ";UserPrincipalName="svcDJ";Password="Password123";Description="SCCM Domain Join Account";Enabled=$true;Path="OU=Service Accounts, OU=_Admin";ChangePasswordAtLogon=$False;PasswordNeverExpires=$True} 194 | @{Role="CP";Name="svcPush";SamAccountName="svcPush";UserPrincipalName="svcPush";Password="Password123";Description="SCCM Client Push Account";Enabled=$true;Path="OU=Service Accounts, OU=_Admin";ChangePasswordAtLogon=$False;PasswordNeverExpires=$True} 195 | @{Role="NA";Name="svcNAA";SamAccountName="svcNAA";UserPrincipalName="svcNAA";Password="Password123";Description="SCCM Network Access Account";Enabled=$true;Path="OU=Service Accounts, OU=_Admin";ChangePasswordAtLogon=$False;PasswordNeverExpires=$True} 196 | ) 197 | ``` 198 | 199 | ServiceAccounts defines the service accounts that should be created specifically for SCCM. Additional parameters can be supplied, provided they are supported by the **New-ADUser** cmdlet. There are however a couple of parameters that need special consideration 200 | 201 | * Role - defines what SCCM role this account will be used for, as additional configuration is performed based on this role. Valid roles are: DJ = Domain Join Account, CP = Client Push Account, NA = Network Access Account. If an account role is not supplied, no additional configuration will be done, and the account will simply be a standard AD account 202 | * UserPrincipalName - This will automatically be post-pended with the domain name where the account is being created 203 | * Password - This should be supplied in plain text, and will automatically be converted using **ConvertTo-SecureString** 204 | * Path - this should be the OU relative to the domain root where the account should be created. The domain portion will automatically be added based on the **Get-ADRootDSE** return value 205 | 206 | ### DomainJoinAccountOUs 207 | 208 | ```powershell 209 | DomainJoinAccountOUs = @( 210 | @{OUName="OU=Desktops,OU=_Workstations"} 211 | @{OUName="OU=Staging,OU=_Workstations"} 212 | @{OUName="CN=Computers"} 213 | ) 214 | ``` 215 | 216 | DomainJoinAccountOUs defines those OUs that the Domain Join Account created in the ServiceAccounts section listed above should be granted rights to manage computer objects (add to domain etc). 217 | 218 | ### BoundaryGroups 219 | 220 | ```powershell 221 | BoundaryGroups = @( 222 | @{Name="Default Boundary Group";SiteCode="S01"} 223 | ) 224 | ``` 225 | 226 | BoundaryGroups defines the boundary groups that should be created. The number of boundary groups is arbitrary and can be as few or as many required. 227 | 228 | ### SiteBoundaries 229 | 230 | ```powershell 231 | SiteBoundaries = @( 232 | @{Name="192.168.50.0 Boundary";IPRange="192.168.50.1-192.168.50.254";MemberOfBoundaryGroupName="Default Boundary Group"} 233 | @{Name="192.168.51.0 Boundary";IPRange="192.168.51.1-192.168.51.254";MemberOfBoundaryGroupName="Default Boundary Group"} 234 | @{Name="192.168.52.0 Boundary";IPRange="192.168.52.1-192.168.52.254";MemberOfBoundaryGroupName="Default Boundary Group"} 235 | ) 236 | ``` 237 | 238 | SiteBoundries defines those site boundaries that should be created. Note that currently the only supported boundary type is **IPRange** 239 | 240 | ### DiscoveryMethods 241 | 242 | ```powershell 243 | DiscoveryMethods = @{ 244 | ActiveDirectorySystemDiscovery = @{ 245 | Settings = @{SiteCode = "S01";Enabled=$true;EnableDeltaDiscovery=$true;DeltaDiscoveryMins=30;ActiveDirectoryContainer="LDAP://DC=LABTEST,DC=LOCAL";Recursive=$true} 246 | Schedule = @{RecurInterval="Days";RecurCount=1;Start="01/01/2001"} 247 | } 248 | ActiveDirectoryUserDiscovery = @{ 249 | Settings = @{SiteCode = "S01";Enabled=$true;EnableDeltaDiscovery=$true;DeltaDiscoveryMins=30;ActiveDirectoryContainer="LDAP://DC=LABTEST,DC=LOCAL";Recursive=$true} 250 | Schedule = @{RecurInterval="Days";RecurCount=1;Start="01/01/2001"} 251 | } 252 | ActiveDirectoryGroupDiscovery = @{ 253 | Settings = @{SiteCode = "S01";Enabled=$true;EnableDeltaDiscovery=$true;DeltaDiscoveryMins=30;DiscoverDistributionGroupMembership = $true} 254 | Scope = @{ Name = 'AD Group Discovery';SiteCode = "S01";RecursiveSearch = $true;LdapLocation="LDAP://DC=LABTEST,DC=LOCAL"} 255 | Schedule = @{RecurInterval="Days";RecurCount=1;Start="01/01/2001"} 256 | } 257 | HeartbeatDiscovery = @{ 258 | Settings = @{SiteCode = "S01";Enabled=$true} 259 | Schedule = @{RecurInterval="Days";RecurCount=7} 260 | } 261 | } 262 | ``` 263 | 264 | DiscoveryMethods defines the settings for the various Discovery Methods in SCCM. Each of the **Settings** can have additional parameters based on the various allowed parameters for the **Set-CMDiscoveryMethod** cmdlet, and **Schedule** can be any valid settings supported by the **New-CMSchedule** cmdlet. for the ActiveDirectoryGroupDiscovery method, an additional **Scope** option is available, and any valid settings used by **New-CMADGroupDiscoveryScope** can be included. Currently, only a single Scope option is supported for the Group Discovery item. 265 | 266 | ### Collections 267 | 268 | ```powershell 269 | Collections = @{ 270 | DeviceCollections = @( 271 | @{ 272 | BasicSettings = @{Name = "All Servers";Comment = "All Servers";LimitingCollectionName="All Systems";RefreshType=2} 273 | Location = "Master Collections" 274 | Schedule = @{RecurInterval="Days";RecurCount=7} 275 | Variables = @(...) 276 | QueryMembershipRules = @(...) 277 | IncludeMembershipRules = @(...) 278 | ExcludeMembershipRules = @(...) 279 | DirectMembershipRules = @(...) 280 | } 281 | ) 282 | } 283 | ``` 284 | 285 | Collections defines those Device and User (Note User currently not implemented) collection to be created within SCCM. These are quite complex structure, so will be discussed in more detail. Note the collections within the Props.ps1 script have been taken from the excellent script at https://gallery.technet.microsoft.com/Set-of-Operational-SCCM-19fa8178#content and converted to be compatible with the format I required. 286 | 287 | **Basic Settings** 288 | Defines the overall basic settings of the collection. Additional parameters can be provided, as long as they are supported by the **New-CMDeviceCollection** cmdlet 289 | 290 | **Location** 291 | Defines the location within the Hierarchy under "Device Collections" in SCCM. The folder provided should be separated by \ characters to designate sub-folders. The folder hierarchy will be created if it does not exist 292 | 293 | **Schedule** 294 | Defines the refresh schedule for the collection, and can include any valid settings supported by the **New-CMSchedule** cmdlet (note that the refresh schedule may have limits on what type of schedule can be created). Currently if no schedule is supplied an error will be thrown 295 | 296 | **Variables** 297 | Defines any variables that should be assigned to collections. There can be zero or more variables defined. 298 | 299 | ```powershell 300 | @{VariableName="MyVariable";Value="123"} 301 | ``` 302 | 303 | **Membership Rules** 304 | There are 4 supported types of membership rules supported for each collection, noting that there can be multiple entries of each membership rule type, and collections can support zero or more membership rule types. Note that the script does not perform validation on the rule itself. 305 | 306 | *Query Membership Rule* 307 | 308 | Supports any parameters allowed by the **Add-CMDeviceCollectionQueryMembershipRule** cmdlet. Advice for properly formatted QueryExpression strings is to create the entry within SCCM, and then copy the query string out for use in the config file 309 | 310 | ```powershell 311 | @{RuleName="All Servers";QueryExpression = "select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System where OperatingSystemNameandVersion like '%Server%'"} 312 | ``` 313 | 314 | *Include Membership Rule* 315 | 316 | Supports any parameters allowed by the **Add-CMDeviceCollectionIncludeMembershipRule** cmdlet. 317 | 318 | ```powershell 319 | @{IncludeCollectionName="All Workstations"} 320 | ``` 321 | 322 | *Exclude Membership Rule* 323 | 324 | Supports any parameters allowed by the **Add-CMDeviceCollectionExcludeMembershipRule** cmdlet. 325 | 326 | ```powershell 327 | @{ExcludeCollectionName="WKS - SU - Exclusion"} 328 | ``` 329 | 330 | *Direct Membership Rule* 331 | 332 | Supports any parameters allowed by the **Add-CMDeviceCollectionDirectMembershipRule** cmdlet. Each item listed must be an existing device within SCCM otherwise an error will be thrown. 333 | 334 | ```powershell 335 | @('DeviceName' 336 | 'AnotherDevice' 337 | ) 338 | ``` 339 | 340 | ### WSUSProps 341 | 342 | Defines the properties for the WSUS/Software Update Point in SCCM 343 | 344 | ```powershell 345 | WSUSProps = @{ 346 | ContentDirectory='F:\WSUS' 347 | UpdateLanguages= @( 348 | 'English' 349 | ) 350 | 351 | EnabledProducts = @( 352 | 'Windows Server 2016' 353 | 'Windows Server 2012 R2' 354 | 'Windows 10' 355 | 'Office 2010' 356 | 'Office 2016' 357 | ) 358 | EnabledProductFamilies = @( 359 | ) 360 | DisabledProducts = @( 361 | ) 362 | DisabledClassifications = @( 363 | 'Tools' 364 | ) 365 | EnabledClassifications = @( 366 | 'Critical Updates' 367 | 'Definition Updates' 368 | 'Feature Packs' 369 | 'Security Updates' 370 | 'Service Packs' 371 | 'Update Rollups' 372 | 'Updates' 373 | 'Upgrades' 374 | ) 375 | Schedule = @{RecurInterval="Days";RecurCount=3} 376 | } 377 | ``` 378 | 379 | *ContentDirectory* defines the location on the SCCM server where WSUS content should be stored 380 | 381 | *UpdateLanguages* defines a list of those languages that should be enabled for content download. Note that the language names must be the same as they appear in the SCCM console 382 | 383 | *EnabledProducts* defines the list of product names that should be enabled for content download. Note the names must be the same as they appear in the SCCM console 384 | 385 | *EnabledProductFamilies* defines the list of product families that should be enabled for content download (eg 'Windows', 'Office'). Note the names must be the same as they appear in the SCCM console 386 | 387 | *Disabled Products* is a list of products that should be disabled. Note that by default, ALL products are disabled during initial configuration, and only those defined in the **EnabledProductFamilies** and **EnabledProducts** will then be re-enabled. This setting therefore is designed to disable specific product(s) within a Product Family without requiring every individual product to be listed in the **EnabledProducts** list. For example, if you wanted all Office and Windows versions, except Office 2007, Office 2003 and Windows Vista, the configuration would be the following: 388 | 389 | ```powershell 390 | EnabledProductFamilies = @( 391 | 'Office' 392 | 'Windows' 393 | ) 394 | DisabledProducts = @( 395 | 'Office 2003' 396 | 'Office 2007' 397 | 'Windows Vista' 398 | ) 399 | ``` 400 | 401 | *EnabledClassifications* defines those product classifications that should be enabled for content download. Note the names must be the same as they appear in the SCCM console 402 | 403 | -------------------------------------------------------------------------------- /SCCM Build/AL CustomRole/SCCM/DownloadAdk.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory)] 3 | [string]$AdkDownloadPath 4 | ) 5 | 6 | $windowsAdkUrl = 'http://download.microsoft.com/download/3/1/E/31EC1AAF-3501-4BB4-B61C-8BD8A07B4E8A/adk/adksetup.exe' 7 | $adkSetup = Get-LabInternetFile -Uri $windowsAdkUrl -Path $labSources\SoftwarePackages -PassThru 8 | 9 | if (-not (Test-Path -Path $AdkDownloadPath)) 10 | { 11 | $p = Start-Process -FilePath $adkSetup.FullName -ArgumentList "/quiet /layout $AdkDownloadPath" -PassThru 12 | Write-ScreenInfo "Waiting for ADK to download files" -NoNewLine 13 | while (-not $p.HasExited) { 14 | Write-ScreenInfo '.' -NoNewLine 15 | Start-Sleep -Seconds 10 16 | } 17 | Write-ScreenInfo 'finished' 18 | } 19 | else 20 | { 21 | Write-ScreenInfo "ADK folder does already exist, skipping the download. Delete the folder '$AdkDownloadPath' if you want to download again." 22 | } -------------------------------------------------------------------------------- /SCCM Build/AL CustomRole/SCCM/DownloadSccm.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory)] 3 | [string]$SccmBinariesDirectory, 4 | 5 | [Parameter(Mandatory)] 6 | [string]$SccmPreReqsDirectory 7 | ) 8 | 9 | $sccm1702Url = 'http://download.microsoft.com/download/C/A/0/CA0CAE64-358C-49EC-9F61-8FACFEDE7083/SC_Configmgr_SCEP_1702.exe' 10 | $sccmSetup = Get-LabInternetFile -Uri $sccm1702Url -Path $labSources\SoftwarePackages -PassThru 11 | 12 | if (-not (Test-Path -Path $SccmBinariesDirectory)) 13 | { 14 | $pArgs = '/AUTO "{0}"' -f $SccmBinariesDirectory 15 | $p = Start-Process -FilePath $sccmSetup.FullName -ArgumentList $pArgs -PassThru 16 | Write-ScreenInfo "Waiting for extracting the SCCM files to '$SccmBinariesDirectory'" -NoNewLine 17 | while (-not $p.HasExited) { 18 | Write-ScreenInfo '.' -NoNewLine 19 | Start-Sleep -Seconds 10 20 | } 21 | Write-ScreenInfo 'finished' 22 | } 23 | else 24 | { 25 | Write-ScreenInfo "SCCM folder does already exist, skipping the download. Delete the folder '$SccmBinariesDirectory' if you want to download again." 26 | } 27 | 28 | if (-not (Test-Path -Path $SccmPreReqsDirectory)) 29 | { 30 | $p = Start-Process -FilePath $labSources\SoftwarePackages\SCCM1702\SMSSETUP\BIN\X64\setupdl.exe -ArgumentList $SccmPreReqsDirectory -PassThru 31 | Write-ScreenInfo "Waiting for downloading the SCCM Prerequisites to '$SccmPreReqsDirectory'" -NoNewLine 32 | while (-not $p.HasExited) { 33 | Write-ScreenInfo '.' -NoNewLine 34 | Start-Sleep -Seconds 10 35 | } 36 | Write-ScreenInfo 'finished' 37 | 38 | } 39 | else 40 | { 41 | Write-ScreenInfo "SCCM Prerequisites folder does already exist, skipping the download. Delete the folder '$SccmPreReqsDirectory' if you want to download again." 42 | } -------------------------------------------------------------------------------- /SCCM Build/AL CustomRole/SCCM/HostStart.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | 3 | [Parameter(Mandatory)] 4 | [string]$ComputerName, 5 | 6 | [Parameter(Mandatory)] 7 | [string]$SccmSiteCode, 8 | 9 | [Parameter(Mandatory)] 10 | [string]$SccmBinariesDirectory, 11 | 12 | [Parameter(Mandatory)] 13 | [string]$SccmPreReqsDirectory, 14 | 15 | [Parameter(Mandatory)] 16 | [string]$AdkDownloadPath, 17 | 18 | [Parameter(Mandatory)] 19 | [string]$SqlServerName 20 | ) 21 | 22 | $sqlServer = Get-LabVM -Role SQLServer | Where-Object Name -eq $SqlServerName 23 | $sccmServer = Get-LabVM -ComputerName $SccmServerName 24 | if (-not $sqlServer) 25 | { 26 | Write-Error "The specified SQL Server '$SqlServerName' does not exist in the lab." 27 | return 28 | } 29 | 30 | if ($sccmServer.OperatingSystem.Version -lt 10.0 -or $SqlServer.OperatingSystem.Version -lt 10.0) 31 | { 32 | Write-Error "The SCCM role requires the SCCM server and the SQL Server to be Windows 2016 or higher." 33 | return 34 | } 35 | 36 | $script = Get-Command -Name $PSScriptRoot\DownloadAdk.ps1 37 | $param = Sync-Parameter -Command $script -Parameters $PSBoundParameters 38 | & $PSScriptRoot\DownloadAdk.ps1 @param 39 | 40 | $script = Get-Command -Name $PSScriptRoot\DownloadSccm.ps1 41 | $param = Sync-Parameter -Command $script -Parameters $PSBoundParameters 42 | & $PSScriptRoot\DownloadSccm.ps1 @param 43 | 44 | $script = Get-Command -Name $PSScriptRoot\InstallSCCM.ps1 45 | $param = Sync-Parameter -Command $script -Parameters $PSBoundParameters 46 | & $PSScriptRoot\InstallSCCM.ps1 @param -------------------------------------------------------------------------------- /SCCM Build/AL CustomRole/SCCM/InstallSCCM.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Install a functional SCCM Primary Site using the Automated-Lab tookit with SCCM being installed using the "CustomRoles" approach 4 | .DESCRIPTION 5 | Long description 6 | .EXAMPLE 7 | PS C:\> 8 | Explanation of what the example does 9 | .INPUTS 10 | Inputs (if any) 11 | .OUTPUTS 12 | Output (if any) 13 | .NOTES 14 | General notes 15 | #> 16 | 17 | param( 18 | 19 | [Parameter(Mandatory)] 20 | [string]$ComputerName, 21 | 22 | [Parameter(Mandatory)] 23 | [string]$SccmBinariesDirectory, 24 | 25 | [Parameter(Mandatory)] 26 | [string]$SccmPreReqsDirectory, 27 | 28 | [Parameter(Mandatory)] 29 | [string]$SccmSiteCode, 30 | 31 | [Parameter(Mandatory)] 32 | [string]$SqlServerName 33 | ) 34 | 35 | function Install-SCCM { 36 | param 37 | ( 38 | [Parameter(Mandatory)] 39 | [string]$SccmServerName, 40 | 41 | [Parameter(Mandatory)] 42 | [string]$SccmBinariesDirectory, 43 | 44 | [Parameter(Mandatory)] 45 | [string]$SccmPreReqsDirectory, 46 | 47 | [Parameter(Mandatory)] 48 | [string]$SccmSiteCode, 49 | 50 | [Parameter(Mandatory)] 51 | [string]$SqlServerName 52 | ) 53 | 54 | $sccmServer = Get-LabVM -ComputerName $SccmServerName 55 | $sccmServerFqdn = $sccmServer.FQDN 56 | $sqlServer = Get-LabVM -Role SQLServer | Where-Object Name -eq $SqlServerName 57 | $sqlServerFqdn = $sqlServer.FQDN 58 | $rootDC = Get-LabVM -Role RootDC | Where-Object { $_.DomainName -eq $sccmServer.DomainName } 59 | 60 | if (-not $sqlServer) 61 | { 62 | Write-Error "The specified SQL Server '$SqlServerName' does not exist in the lab." 63 | return 64 | } 65 | 66 | $mdtDownloadLocation = 'https://download.microsoft.com/download/3/3/9/339BE62D-B4B8-4956-B58D-73C4685FC492/MicrosoftDeploymentToolkit_x64.msi' 67 | $downloadTargetFolder = "$labSources\SoftwarePackages" 68 | 69 | #Do Some quick checks before we get going 70 | #Check for existance of ADK Installation Files 71 | if (-not (Test-Path -Path "$downloadTargetFolder\ADK")) { 72 | Write-LogFunctionExitWithError -Message "ADK Installation files not located at '$downloadTargetFolder\ADK'" 73 | return 74 | } 75 | 76 | if (-not (Test-Path -Path $SccmBinariesDirectory)) { 77 | Write-LogFunctionExitWithError -Message "SCCM Installation files not located at '$($SccmBinariesDirectory)'" 78 | return 79 | } 80 | 81 | if (-not (Test-Path -Path $SccmPreReqsDirectory)) { 82 | Write-LogFunctionExitWithError -Message "SCCM PreRequisite files not located at '$($SccmPreReqsDirectory)'" 83 | return 84 | } 85 | 86 | #Bring all available disks online (this is to cater for the secondary drive) 87 | #For some reason, cant make the disk online and RW in the one command, need to perform two seperate actions 88 | Invoke-LabCommand -ActivityName 'Bring Disks Online' -ComputerName $SccmServerName -ScriptBlock { 89 | $dataVolume = Get-Disk | Where-Object -Property OperationalStatus -eq Offline 90 | $dataVolume | Set-Disk -IsOffline $false 91 | $dataVolume | Set-Disk -IsReadOnly $false 92 | } 93 | 94 | #Copy the SCCM Binaries 95 | Copy-LabFileItem -Path $SccmBinariesDirectory -DestinationFolderPath C:\Install -ComputerName $SccmServerName -Recurse 96 | #Copy the SCCM Prereqs (must have been previously downloaded) 97 | Copy-LabFileItem -Path $SccmPreReqsDirectory -DestinationFolderPath C:\Install -ComputerName $SccmServerName -Recurse 98 | 99 | #Extend the AD Schema 100 | Invoke-LabCommand -ActivityName 'Extend AD Schema' -ComputerName $SccmServerName -ScriptBlock { 101 | C:\Install\SCCM1702\SMSSETUP\BIN\X64\extadsch.exe 102 | } 103 | 104 | #Need to execute this command on the Domain Controller, since it has the AD Powershell cmdlets available 105 | #Create the Necessary OU and permissions for the SCCM container in AD 106 | Invoke-LabCommand -ActivityName 'Configure SCCM Systems Management Container' -ComputerName $rootDC -ScriptBlock { 107 | param 108 | ( 109 | [Parameter(Mandatory)] 110 | [string]$SCCMServerName 111 | ) 112 | 113 | Import-Module ActiveDirectory 114 | # Figure out our domain 115 | $rootDomainNc = (Get-ADRootDSE).defaultNamingContext 116 | 117 | # Get or create the System Management container 118 | $ou = $null 119 | try 120 | { 121 | $ou = Get-ADObject "CN=System Management,CN=System,$rootDomainNc" 122 | } 123 | catch 124 | { 125 | Write-Verbose "System Management container does not currently exist." 126 | $ou = New-ADObject -Type Container -name "System Management" -Path "CN=System,$rootDomainNc" -Passthru 127 | } 128 | 129 | # Get the current ACL for the OU 130 | $acl = Get-ACL -Path "ad:CN=System Management,CN=System,$rootDomainNc" 131 | 132 | # Get the computer's SID (we need to get the computer object, which is in the form $) 133 | $sccmComputer = Get-ADComputer "$SCCMServerName$" 134 | $sccmServerSId = [System.Security.Principal.SecurityIdentifier] $sccmComputer.SID 135 | 136 | $ActiveDirectoryRights = "GenericAll" 137 | $AccessControlType = "Allow" 138 | $Inherit = "SelfAndChildren" 139 | $nullGUID = [guid]'00000000-0000-0000-0000-000000000000' 140 | 141 | # Create a new access control entry to allow access to the OU 142 | $ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $sccmServerSId, $ActiveDirectoryRights, $AccessControlType, $Inherit, $nullGUID 143 | 144 | # Add the ACE to the ACL, then set the ACL to save the changes 145 | $acl.AddAccessRule($ace) 146 | Set-ACL -AclObject $acl "ad:CN=System Management,CN=System,$rootDomainNc" 147 | 148 | } -ArgumentList $SccmServerName 149 | 150 | Write-ScreenInfo -Message "Downloading MDT Installation Files from '$mdtDownloadLocation'" 151 | $mdtInstallFile = Get-LabInternetFile -Uri $mdtDownloadLocation -Path $downloadTargetFolder -ErrorAction Stop -PassThru 152 | 153 | Write-ScreenInfo "Copying MDT Install Files to server '$SccmServerName'..." 154 | Copy-LabFileItem -Path $mdtInstallFile.FullName -DestinationFolderPath C:\Install -ComputerName $SccmServerName 155 | 156 | Write-ScreenInfo "Copying ADK Install Files to server '$SccmServerName'..." 157 | Copy-LabFileItem -Path "$downloadTargetFolder\ADK" -DestinationFolderPath C:\Install -ComputerName $SccmServerName -Recurse 158 | 159 | Write-ScreenInfo "Installing ADK on server '$SccmServerName'..." -NoNewLine 160 | $job = Install-LabSoftwarePackage -LocalPath C:\Install\ADK\adksetup.exe -CommandLine "/norestart /q /ceip off /features OptionId.WindowsPreinstallationEnvironment OptionId.DeploymentTools OptionId.UserStateMigrationTool OptionId.ImagingAndConfigurationDesigner" ` 161 | -ComputerName $SccmServerName -NoDisplay -AsJob -PassThru 162 | Wait-LWLabJob -Job $job -NoDisplay 163 | 164 | Write-ScreenInfo "Installing .net 3.5 on '$SccmServerName'..." -NoNewLine 165 | $job = Install-LabWindowsFeature -ComputerName $SccmServerName -FeatureName NET-Framework-Core -NoDisplay -AsJob -PassThru 166 | Wait-LWLabJob -Job $job -NoDisplay 167 | 168 | Write-ScreenInfo "Installing WDS on '$SccmServerName'..." -NoNewLine 169 | $job = Install-LabWindowsFeature -ComputerName $SccmServerName -FeatureName WDS -NoDisplay -AsJob -PassThru 170 | Wait-LWLabJob -Job $job -NoDisplay 171 | 172 | Write-ScreenInfo "Installing 'MDT' on server '$SccmServerName'..." -NoNewLine 173 | Install-LabSoftwarePackage -ComputerName $SccmServerName -LocalPath "C:\Install\$($mdtInstallFile.FileName)" -CommandLine '/qb' -NoDisplay -AsJob -PassThru 174 | Wait-LWLabJob -Job $job -NoDisplay 175 | 176 | Invoke-LabCommand -ActivityName 'Configure WDS' -ComputerName $SccmServerName -ScriptBlock { 177 | Start-Process -FilePath "C:\Windows\System32\WDSUTIL.EXE" -ArgumentList "/Initialize-Server /RemInst:C:\RemoteInstall" -Wait 178 | Start-Sleep -Seconds 10 179 | Start-Process -FilePath "C:\Windows\System32\WDSUTIL.EXE" -ArgumentList "/Set-Server /AnswerClients:All" -Wait 180 | } 181 | 182 | #SCCM Needs a ton of additional features installed... 183 | Write-ScreenInfo "Installing a ton of additional features on server '$SccmServerName'..." -NoNewLine 184 | $job = Install-LabWindowsFeature -ComputerName $SccmServerName -FeatureName 'FS-FileServer,Web-Mgmt-Tools,Web-Mgmt-Console,Web-Mgmt-Compat,Web-Metabase,Web-WMI,Web-WebServer,Web-Common-Http,Web-Default-Doc,Web-Dir-Browsing,Web-Http-Errors,Web-Static-Content,Web-Http-Redirect,Web-Health,Web-Http-Logging,Web-Log-Libraries,Web-Request-Monitor,Web-Http-Tracing,Web-Performance,Web-Stat-Compression,Web-Dyn-Compression,Web-Security,Web-Filtering,Web-Windows-Auth,Web-App-Dev,Web-Net-Ext,Web-Net-Ext45,Web-Asp-Net,Web-Asp-Net45,Web-ISAPI-Ext,Web-ISAPI-Filter' -NoDisplay -AsJob -PassThru 185 | Wait-LWLabJob -Job $job -NoDisplay 186 | Write-ScreenInfo done 187 | 188 | $job = Install-LabWindowsFeature -ComputerName $SccmServerName -FeatureName 'NET-HTTP-Activation,NET-Non-HTTP-Activ,NET-Framework-45-ASPNET,NET-WCF-HTTP-Activation45,BITS,RDC' -NoDisplay -AsJob -PassThru 189 | Wait-LWLabJob -Job $job -NoDisplay 190 | Write-ScreenInfo done 191 | 192 | #Before we start the SCCM Install, restart the computer 193 | Write-ScreenInfo "Restarting server '$SccmServerName'..." -NoNewLine 194 | Restart-LabVM -ComputerName $SccmServerName -Wait -NoDisplay 195 | 196 | #Build the Installation unattended .INI file 197 | $setupConfigFileContent = @" 198 | [Identification] 199 | Action=InstallPrimarySite 200 | 201 | [Options] 202 | ProductID=EVAL 203 | SiteCode=$SccmSiteCode 204 | SiteName=Primary Site 1 205 | SMSInstallDir=C:\Program Files\Microsoft Configuration Manager 206 | SDKServer=$sccmServerFqdn 207 | RoleCommunicationProtocol=HTTPorHTTPS 208 | ClientsUsePKICertificate=0 209 | PrerequisiteComp=1 210 | PrerequisitePath=C:\Install\SCCMPreReqs 211 | MobileDeviceLanguage=0 212 | ManagementPoint=$sccmServerFqdn 213 | ManagementPointProtocol=HTTP 214 | DistributionPoint=$sccmServerFqdn 215 | DistributionPointProtocol=HTTP 216 | DistributionPointInstallIIS=0 217 | AdminConsole=1 218 | JoinCEIP=0 219 | 220 | [SQLConfigOptions] 221 | SQLServerName=$SqlServerFqdn 222 | DatabaseName=CM_$SccmSiteCode 223 | SQLSSBPort=4022 224 | SQLDataFilePath=C:\CMSQL\SQLDATA\ 225 | SQLLogFilePath=C:\CMSQL\SQLLOGS\ 226 | 227 | [CloudConnectorOptions] 228 | CloudConnector=0 229 | CloudConnectorServer=$sccmServerFqdn 230 | UseProxy=0 231 | 232 | [SystemCenterOptions] 233 | 234 | [HierarchyExpansionOption] 235 | "@ 236 | 237 | #Save the config file to disk, and copy it to the SCCM Server 238 | $setupConfigFileContent | Out-File -FilePath "$($lab.LabPath)\ConfigMgrUnattend.ini" -Encoding ascii 239 | 240 | Copy-LabFileItem -Path "$($lab.LabPath)\ConfigMgrUnattend.ini" -DestinationFolderPath C:\Install -ComputerName $SccmServerName 241 | 242 | $sccmComputerAccount = '{0}\{1}$' -f 243 | $sccmServer.DomainName.Substring(0, $sccmServer.DomainName.IndexOf('.')), 244 | $SccmServerName 245 | 246 | Invoke-LabCommand -ActivityName 'Create Folders for SQL DB' -ComputerName $sqlServer -ScriptBlock { 247 | #SQL Server does not like creating databases without the directories already existing, so make sure to create them first 248 | New-Item -Path 'C:\CMSQL\SQLDATA' -ItemType Directory -Force | Out-Null 249 | New-Item -Path 'C:\CMSQL\SQLLOGS' -ItemType Directory -Force | Out-Null 250 | 251 | if (-not (Get-LocalGroupMember -Group Administrators -Member $sccmComputerAccount -ErrorAction SilentlyContinue)) 252 | { 253 | Add-LocalGroupMember -Group Administrators -Member $sccmComputerAccount 254 | } 255 | } -Variable (Get-Variable -Name sccmComputerAccount) -NoDisplay 256 | 257 | Write-ScreenInfo 'Install SCCM. This step will take quite some time...' -NoNewLine 258 | $job = Install-LabSoftwarePackage -ComputerName $SccmServerName -LocalPath C:\Install\SCCM1702\SMSSETUP\BIN\X64\setup.exe -CommandLine '/Script "C:\Install\ConfigMgrUnattend.ini" /NoUserInput' -AsJob -PassThru 259 | Wait-LWLabJob -Job $job -NoDisplay 260 | } 261 | 262 | Write-ScreenInfo '' 263 | $lab = Import-Lab -Name $data.Name -NoValidation -NoDisplay -PassThru 264 | 265 | Install-SCCM -SccmServerName $ComputerName -SccmBinariesDirectory $SCCMBinariesDirectory -SccmPreReqsDirectory $SCCMPreReqsDirectory -SccmSiteCode $SCCMSiteCode -SqlServerName $SqlServerName -------------------------------------------------------------------------------- /SCCM Build/AL CustomRole/SCCM/README.md: -------------------------------------------------------------------------------- 1 | # SCCM 2 | 3 | ## Defining the role 4 | 5 | ``` PowerShell 6 | $sccmRole = Get-LabPostInstallationActivity -CustomRole SCCM -Properties @{ 7 | SccmSiteCode = "CM1" 8 | SccmBinariesDirectory = "$labSources\SoftwarePackages\SCCM1702" 9 | SccmPreReqsDirectory = "$labSources\SoftwarePackages\SCCMPreReqs" 10 | AdkDownloadPath = "$labSources\SoftwarePackages\ADK" 11 | SqlServerName = 'SQL1' 12 | } 13 | 14 | Add-LabMachineDefinition -Name SCCM1 -Memory 4GB -OperatingSystem 'Windows Server 2016 Datacenter (Desktop Experience)' -DomainName contoso.com -PostInstallationActivity $sccmRole 15 | ``` 16 | 17 | Requires a SQL Server with collation 'SQL_Latin1_General_CP1_CI_AS' 18 | 19 | ``` PowerShell 20 | $sqlRole = Get-LabMachineRoleDefinition -Role SQLServer2017 -Properties @{ Collation = 'SQL_Latin1_General_CP1_CI_AS' } 21 | Add-LabMachineDefinition -Name SQL1 -Memory 2GB -OperatingSystem 'Windows Server 2016 Datacenter (Desktop Experience)' -DomainName contoso.com -Roles $sqlRole 22 | ``` -------------------------------------------------------------------------------- /SCCM Build/SCCM Server Build.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Install a functional SCCM Primary Site using the Automated-Lab tookit 4 | .DESCRIPTION 5 | Long description 6 | .EXAMPLE 7 | PS C:\> 8 | Explanation of what the example does 9 | .INPUTS 10 | Inputs (if any) 11 | .OUTPUTS 12 | Output (if any) 13 | .NOTES 14 | General notes 15 | #> 16 | 17 | function Install-SCCM { 18 | param 19 | ( 20 | [Parameter(Mandatory)] 21 | $SCCMServerName, 22 | 23 | [Parameter(Mandatory)] 24 | $SCCMBinariesDirectory, 25 | 26 | [Parameter(Mandatory)] 27 | $SCCMPreReqsDirectory, 28 | 29 | [Parameter(Mandatory)] 30 | $SCCMSiteCode = 'CM1' 31 | ) 32 | 33 | $MDTDownloadLocation = 'https://download.microsoft.com/download/3/3/9/339BE62D-B4B8-4956-B58D-73C4685FC492/MicrosoftDeploymentToolkit_x64.msi' 34 | 35 | #Do Some quick checks before we get going 36 | $downloadTargetFolder = Join-Path -Path $labSources -ChildPath SoftwarePackages 37 | #Check for existance of ADK Installation Files 38 | if (!(Test-Path -Path (Join-Path -Path $downloadTargetFolder -ChildPath 'ADK'))) { 39 | Write-LogFunctionExitWithError -Message "ADK Installation files not located at '$(Join-Path -Path $downloadTargetFolder -ChildPath 'ADK')'" 40 | return 41 | } 42 | 43 | if (!(Test-Path -Path (Join-Path -Path $downloadTargetFolder -ChildPath $SCCMBinariesDirectory))) { 44 | Write-LogFunctionExitWithError -Message "SCCM Installation files not located at '$(Join-Path -Path $downloadTargetFolder -ChildPath $SCCMBinariesDirectory)'" 45 | return 46 | } 47 | 48 | if (!(Test-Path -Path (Join-Path -Path $downloadTargetFolder -ChildPath $SCCMPreReqsDirectory))) { 49 | Write-LogFunctionExitWithError -Message "SCCM PreRequisite files not located at '$(Join-Path -Path $downloadTargetFolder -ChildPath $SCCMPreReqsDirectory)'" 50 | return 51 | } 52 | 53 | #Bring all available disks online (this is to cater for the secondary drive) 54 | #For some reason, cant make the disk online and RW in the one command, need to perform two seperate actions 55 | Invoke-LabCommand -ActivityName 'Bring Disks Online' -ComputerName $SCCMServerName -ScriptBlock { 56 | $DataVolume = Get-Disk | Where-Object -Property OperationalStatus -eq Offline 57 | $DataVolume | Set-Disk -IsOffline $false 58 | $DataVolume | Set-Disk -IsReadOnly $false 59 | } 60 | 61 | #Copy the SCCM Binaries 62 | $downloadTargetFolder = Join-Path -Path $labSources -ChildPath SoftwarePackages 63 | Copy-LabFileItem -Path (Join-Path -Path $downloadTargetFolder -ChildPath $SCCMBinariesDirectory) -DestinationFolderPath C:\Install -ComputerName $SCCMServerName -Recurse 64 | #Copy the SCCM Prereqs (must have been previously downloaded) 65 | Copy-LabFileItem -Path (Join-Path -Path $downloadTargetFolder -ChildPath $SCCMPreReqsDirectory) -DestinationFolderPath C:\Install -ComputerName $SCCMServerName -Recurse 66 | 67 | #Extend the AD Schema 68 | Invoke-LabCommand -ActivityName 'Extend AD Schema' -ComputerName $SCCMServerName -ScriptBlock { 69 | Start-Process -FilePath "C:\Install\SCCM1702\SMSSETUP\BIN\X64\extadsch.exe" -Wait 70 | } 71 | 72 | #Need to execute this command on the Domain Controller, since it has the AD Powershell cmdlets available 73 | $RootDC = Get-LabMachine | Where-Object {$_.Roles -like "RootDC"} 74 | #Create the Necessary OU and permissions for the SCCM container in AD 75 | 76 | Invoke-LabCommand -ActivityName 'Configure SCCM Systems Management Container' -ComputerName $RootDC -ScriptBlock { 77 | param 78 | ( 79 | [Parameter(Mandatory)] 80 | $SCCMServerName 81 | ) 82 | 83 | Import-Module ActiveDirectory 84 | # Figure out our domain 85 | $DomainRoot = (Get-ADRootDSE).defaultNamingContext 86 | 87 | # Get or create the System Management container 88 | $ou = $null 89 | try 90 | { 91 | $ou = Get-ADObject "CN=System Management,CN=System,$DomainRoot" 92 | } 93 | catch 94 | { 95 | Write-Verbose "System Management container does not currently exist." 96 | } 97 | 98 | #If the OU Doesnt already exist, create it 99 | if ($ou -eq $null) 100 | { 101 | $ou = New-ADObject -Type Container -name "System Management" -Path "CN=System,$DomainRoot" -Passthru 102 | } 103 | 104 | # Get the current ACL for the OU 105 | $acl = Get-ACL "ad:CN=System Management,CN=System,$DomainRoot" 106 | 107 | # Get the computer's SID (we need to get the computer object, which is in the form $) 108 | $SCCMComputer = Get-ADComputer "$SCCMServerName$" 109 | $SCCMServerSID = [System.Security.Principal.SecurityIdentifier] $SCCMComputer.SID 110 | 111 | $ActiveDirectoryRights = "GenericAll" 112 | $AccessControlType = "Allow" 113 | $Inherit = "SelfAndChildren" 114 | $nullGUID = [guid]'00000000-0000-0000-0000-000000000000' 115 | 116 | # Create a new access control entry to allow access to the OU 117 | $ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $SCCMServerSID, $ActiveDirectoryRights, $AccessControlType, $Inherit, $nullGUID 118 | 119 | # Add the ACE to the ACL, then set the ACL to save the changes 120 | $acl.AddAccessRule($ACE) 121 | Set-ACL -aclobject $acl "ad:CN=System Management,CN=System,$DomainRoot" 122 | 123 | } -ArgumentList $SCCMServerName 124 | 125 | Write-ScreenInfo -Message "Downloading MDT Installation Files from '$MDTDownloadLocation'" 126 | Get-LabInternetFile -Uri $MDTDownloadLocation -Path $downloadTargetFolder -ErrorAction Stop 127 | 128 | $MDTDownloadURL = New-Object System.Uri($MDTDownloadLocation) 129 | $MDTInstallFileName = $MDTDownloadURL.Segments[$MDTDownloadURL.Segments.Count-1] 130 | 131 | Write-ScreenInfo "Copying MDT Install Files to server '$SCCMServerName'..." 132 | Copy-LabFileItem -Path (Join-Path -Path $downloadTargetFolder -ChildPath $MDTInstallFileName) -DestinationFolderPath C:\Install -ComputerName $SCCMServerName 133 | 134 | Write-ScreenInfo "Copying ADK Install Files to server '$SCCMServerName'..." 135 | Copy-LabFileItem -Path (Join-Path -Path $downloadTargetFolder -ChildPath 'ADK') -DestinationFolderPath C:\Install -ComputerName $SCCMServerName -Recurse 136 | 137 | Write-ScreenInfo "Installing ADK on server '$SCCMServerName'..." 138 | Invoke-LabCommand -ActivityName 'Install ADK' -ComputerName $SCCMServerName -ScriptBlock { 139 | Start-Process -FilePath "C:\Install\ADK\adksetup.exe" -ArgumentList "/norestart /q /ceip off /features OptionId.WindowsPreinstallationEnvironment OptionId.DeploymentTools OptionId.UserStateMigrationTool OptionId.ImagingAndConfigurationDesigner" -Wait 140 | } 141 | 142 | Install-LabWindowsFeature -ComputerName $SCCMServerName -FeatureName 'NET-Framework-Core' 143 | 144 | Invoke-LabCommand -ActivityName 'Install WDS Tools' -ComputerName $SCCMServerName -ScriptBlock { 145 | Add-WindowsFeature WDS -IncludeManagementTools | Out-Null 146 | } 147 | 148 | Write-ScreenInfo "Installing 'MDT' on server '$SCCMServerName'..." 149 | Install-LabSoftwarePackage -ComputerName $SCCMServerName -LocalPath "C:\Install\$MDTInstallFileName" -CommandLine '/qb' 150 | 151 | Invoke-LabCommand -ActivityName 'Configure WDS' -ComputerName $SCCMServerName -ScriptBlock { 152 | Start-Process -FilePath "C:\Windows\System32\WDSUTIL.EXE" -ArgumentList "/Initialize-Server /RemInst:C:\RemoteInstall" -Wait 153 | Start-Sleep -Seconds 10 154 | Start-Process -FilePath "C:\Windows\System32\WDSUTIL.EXE" -ArgumentList "/Set-Server /AnswerClients:All" -Wait 155 | } 156 | 157 | #SCCM Needs a ton of additional features installed... 158 | Install-LabWindowsFeature -ComputerName $SCCMServerName -FeatureName 'FS-FileServer,Web-Mgmt-Tools,Web-Mgmt-Console,Web-Mgmt-Compat,Web-Metabase,Web-WMI,Web-WebServer,Web-Common-Http,Web-Default-Doc,Web-Dir-Browsing,Web-Http-Errors,Web-Static-Content,Web-Http-Redirect,Web-Health,Web-Http-Logging,Web-Log-Libraries,Web-Request-Monitor,Web-Http-Tracing,Web-Performance,Web-Stat-Compression,Web-Dyn-Compression,Web-Security,Web-Filtering,Web-Windows-Auth,Web-App-Dev,Web-Net-Ext,Web-Net-Ext45,Web-Asp-Net,Web-Asp-Net45,Web-ISAPI-Ext,Web-ISAPI-Filter' 159 | Install-LabWindowsFeature -ComputerName $SCCMServerName -FeatureName 'NET-HTTP-Activation,NET-Non-HTTP-Activ,NET-Framework-45-ASPNET,NET-WCF-HTTP-Activation45,BITS,RDC' 160 | 161 | #Before we start the SCCM Install, restart the computer 162 | Restart-LabVM -ComputerName $SCCMServerName -Wait 163 | 164 | #Build the Installation unattended .INI file 165 | $setupConfigFileContent = " 166 | [Identification] 167 | Action=InstallPrimarySite 168 | 169 | [Options] 170 | ProductID=EVAL 171 | SiteCode=$SCCMSiteCode 172 | SiteName=Primary Site 1 173 | SMSInstallDir=D:\Program Files\Microsoft Configuration Manager 174 | SDKServer=$((Get-LabMachineDefinition -ComputerName $SCCMServerName).FQDN) 175 | RoleCommunicationProtocol=HTTPorHTTPS 176 | ClientsUsePKICertificate=0 177 | PrerequisiteComp=1 178 | PrerequisitePath=C:\Install\SCCMPreReqs 179 | MobileDeviceLanguage=0 180 | ManagementPoint=$((Get-LabMachineDefinition -ComputerName $SCCMServerName).FQDN) 181 | ManagementPointProtocol=HTTP 182 | DistributionPoint=$((Get-LabMachineDefinition -ComputerName $SCCMServerName).FQDN) 183 | DistributionPointProtocol=HTTP 184 | DistributionPointInstallIIS=0 185 | AdminConsole=1 186 | JoinCEIP=0 187 | 188 | [SQLConfigOptions] 189 | SQLServerName=$((Get-LabMachineDefinition -ComputerName $SCCMServerName).FQDN) 190 | DatabaseName=CM_$SCCMSiteCode 191 | SQLSSBPort=4022 192 | SQLDataFilePath=D:\CMSQL\SQLDATA\ 193 | SQLLogFilePath=D:\CMSQL\SQLLOGS\ 194 | 195 | [CloudConnectorOptions] 196 | CloudConnector=0 197 | CloudConnectorServer=$((Get-LabMachineDefinition -ComputerName $SCCMServerName).FQDN) 198 | UseProxy=0 199 | 200 | [SystemCenterOptions] 201 | 202 | [HierarchyExpansionOption]" 203 | 204 | #Save the config file to disk, and copy it to the SCCM Server 205 | $SCCMInIFileLocation = Join-Path -Path $labSources -ChildPath PostInstallationActivities 206 | $setupConfigFileContent | Out-File -Encoding ascii -FilePath "$SCCMIniFileLocation\ConfigMgrUnattend.ini" 207 | 208 | Copy-LabFileItem -Path "$SCCMIniFileLocation\ConfigMgrUnattend.ini" -DestinationFolderPath C:\Install -ComputerName $SCCMServerName 209 | 210 | Invoke-LabCommand -ActivityName 'Install SCCM' -ComputerName $SCCMServerName -ScriptBlock { 211 | #SQL Server does not like creating databases without the directories already existing, so make sure to create them first 212 | New-Item -Path 'D:\CMSQL\SQLDATA' -ItemType Directory -Force | Out-Null 213 | New-Item -Path 'D:\CMSQL\SQLLOGS' -ItemType Directory -Force | Out-Null 214 | #Install SCCM. This step will take quite some time. 215 | Start-Process -FilePath "C:\Install\SCCM1702\SMSSETUP\BIN\X64\setup.exe" -ArgumentList "/Script ""C:\Install\ConfigMgrUnattend.ini"" /NoUserInput" -Wait 216 | } 217 | 218 | } 219 | #Cleanup from last run 220 | Remove-Item -Path 'C:\Temp\SCCMLab.log' -Force -ErrorAction SilentlyContinue 221 | Start-Transcript -Path 'C:\Temp\SCCMLab.log' 222 | 223 | $labName = 'SCCMLab' 224 | $labSources = Get-LabSourcesLocation 225 | $SCCMServerName = 'SCCMServer' 226 | 227 | New-LabDefinition -Name $LabName -DefaultVirtualizationEngine HyperV -VmPath "C:\Hyper-V\Automation-Lab" 228 | 229 | $PSDefaultParameterValues = @{ 230 | 'Add-LabMachineDefinition:Network' = $labName 231 | 'Add-LabMachineDefinition:ToolsPath'= "$labSources\Tools" 232 | 'Add-LabMachineDefinition:DomainName' = 'sccmlab.local' 233 | 'Add-LabMachineDefinition:DnsServer1' = '192.168.40.10' 234 | 'Add-LabMachineDefinition:OperatingSystem' = 'Windows Server 2016 SERVERSTANDARD' 235 | } 236 | 237 | Add-LabVirtualNetworkDefinition -Name $LabName -AddressSpace 192.168.40.0/24 238 | Add-LabIsoImageDefinition -Name SQLServer2014 -Path $labSources\ISOs\en_sql_server_2014_standard_edition_x64_dvd_3932034.iso 239 | 240 | Add-LabMachineDefinition -Name DC1 -Memory 2GB -Roles RootDC -IPAddress '192.168.40.10' 241 | 242 | #Add the SQL ROle definition. SCCM requires a specific Collation setting, so pass that in 243 | $roles = (Get-LabMachineRoleDefinition -Role SQLServer2014 -Properties @{ Collation = 'SQL_Latin1_General_CP1_CI_AS' }) 244 | Add-LabDiskDefinition -Name SCCMData -DiskSizeInGb 100 245 | Add-LabMachineDefinition -Name $SCCMServerName -DiskName SCCMData -Memory 4GB -Processors 4 -Roles $roles -IpAddress '192.168.40.20' 246 | 247 | #Do the installation 248 | Install-Lab 249 | 250 | #Save a snapshot of the machines during development, remove for production deployments 251 | Checkpoint-LABVM -All -SnapshotName 'After Build' 252 | 253 | Install-SCCM -SCCMServerName $SCCMServerName -SCCMBinariesDirectory 'SCCM1702' -SCCMPreReqsDirectory 'SCCMPreReqs' 254 | 255 | Show-LabDeploymentSummary -Detailed 256 | -------------------------------------------------------------------------------- /SCCM Build/readme.md: -------------------------------------------------------------------------------- 1 | This script is designed to deploy Microsoft System Centre Configuration Manager (Current Branch) using Automated-Lab as the base deployment toolkit 2 | 3 | Prerequisites: 4 | 5 | - Installed version of Automated-Lab (Tested on v4.5.0) 6 | - Download of the Microsoft Assessment and Deployment Kit - available here: 7 | https://developer.microsoft.com/en-us/windows/hardware/windows-assessment-deployment-kit 8 | Tested with 1709 Version 9 | - A Server operating system image for an two machine AL machine deployment (Domain Controller and SCCM Server: 10 | Tested with Windows Server 2016 for both roles 11 | - SCCM Requires SQL Server installed, assumed that existing AL SQL Role deployment method is used. 12 | Tested with SQL Server 2014 13 | - SCCM Prerequisites downloaded using SETUPDL.EXE, available in SCCM package in .\SMSSETUP\BIN\X64. It is assumed that the guest machine does not have internet access, so this set of packages (approx 600mb) must be downloaded and placed into the $LabSources\SoftwarePackages\SCCMPreReqs folder 14 | 15 | Known Restrictions/Limitations: 16 | 17 | - Currently tested with a single AD Domain and Dedicated SCCM+SQL Server 18 | - SCCM Server must have a second disk attached to hold the SCCM Binaries, SQL Databases, and SCCM Content Shares (assumed to be D:) - A default install of SQL + SCCM + ADK uses approx 20GB of disk space, 60GB or more is recommended if Operating Systems, Applications, and Drivers will be installed 19 | - A minimum of 4gb of memory + multiple vCPU's is recommended due to number of running processes + SQL Server 20 | - SCCM Requires a specific SQL collation setting, which needs to be specific during the Virtual Machine definition phase: 21 | 22 | ```ps 23 | $roles = (Get-LabMachineRoleDefinition -Role SQLServer2014 -Properties @{ Collation = 'SQL_Latin1_General_CP1_CI_AS' }) 24 | Add-LabDiskDefinition -Name SCCMData -DiskSizeInGb 100 25 | Add-LabMachineDefinition -Name $SCCMServerName -DiskName SCCMData -Memory 4GB -Processors 4 -Roles $roles -IpAddress '192.168.40.20' 26 | ``` 27 | 28 | - All SCCM Generated certificates are self-signed, solution does not currently integrate with Certificate Services 29 | - Currently SCCM binaries are assumed to be in the $LabSources\SoftwarePackages folder. Evaluation version of SCCM available from Microsoft Evaluation Center is a self-extracting EXE, rather than an ISO, so an ISO image deployment has not been tested. 30 | 31 | This script is a work in progress, there are some assumptions made resulting in some lack of error checking. Additional enhancements are in the pipeline, and are managed as enhancement requests within GitHub 32 | 33 | Update 31/03/18 34 | 35 | A version of this script is being developed to support the AutomatedLab 'CustomRoles' feature that will released as part of Version 5.0 36 | 37 | Scripts are located in the 'AL Custom Role' folder, and all items should be copied to the 'LabSources\CustomRoles' folder with the 'SCCM' folder name, eg: 38 | 39 | ```yaml 40 | C:\LabSources\CustomRoles 41 | \SCCM 42 | \DownloadADK.ps1 43 | \HostInit.ps1 44 | \InstallSCCM.ps1 45 | ``` 46 | 47 | To use from AL: 48 | 49 | ```ps 50 | $SCCMRole = Get-LabPostInstallationActivity -CustomRole SCCM -Properties @{ 51 | SCCMSiteCode = "CM1" 52 | SCCMBinariesDirectory = "$labSources\SoftwarePackages\SCCM1702" 53 | SCCMPreReqsDirectory = "$labSources\SoftwarePackages\SCCMPreReqs" 54 | AdkDownloadPath = "$labSources\SoftwarePackages\ADK" 55 | } 56 | 57 | $roles = (Get-LabMachineRoleDefinition -Role SQLServer2014 -Properties @{ Collation = 'SQL_Latin1_General_CP1_CI_AS' }) 58 | Add-LabDiskDefinition -Name SCCMData -DiskSizeInGb 100 59 | Add-LabMachineDefinition -Name SCCMDC -Roles RootDC -DomainName contoso.com 60 | Add-LabMachineDefinition -Name SCCMServer -DiskName SCCMData -Memory 4GB -Processors 4 -Roles $roles -PostInstallationActivity $SCCMRole -DomainName contoso.com 61 | 62 | ``` 63 | --------------------------------------------------------------------------------