Enclosed a script to join the Azure machine into AD and install the SCCM client. This is useful if you want to populate a native Azure VM that was not installed with SCCM. To make the AD-join a service user was assigned in the script, certainly not the most beautiful variant but this can be encrypted by a compiled EXE. This can be done with the following tool: https://gallery.technet.microsoft.com/scriptcenter/PS2EXE-GUI-Convert-e7cb69d5
Of course, network access to the AD and SCCM server must be available.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
#by Jeremias Kühnis #02.10.2019 ### Vars Section ### $SCCM_Server = "SCCMPrimary.f.q.d.n" $site_code = "Your Site Code -like S01" $SCCM_MPServer = "ManagementPoint.f.q.d.n" $LocalSource_Path = "$env:SystemDrive\temp\" $SCCM_ClientInstaller = "$LocalSource_Path" + "Client\ccmsetup.exe" $SCCM_Repo = "\\$SCCM_Server\SMS_***YOURSITECODE***\Client" $time = ([datetime]::now).tostring("dd_MM_yyyy_HH-mm-ss") $ScriptFilename = Split-Path $MyInvocation.MyCommand.Definition -leaf $LogfileName = $LocalSource_Path + 'Azure-SCCMInstaller' + '__' + $time + '.log' $fqdn = 'someFQDN' $JoinADUser = $fqdn + '\ServiceAccountjoinAD' $JoinADUserPw = 'ServiceAccountPW' $ADOU_NewAzuewDevice = "OU=Germany,DC=contoso,DC=com" ### External Functions ### #by https://gallery.technet.microsoft.com/scriptcenter/Write-Log-PowerShell-999c32d0 function Write-Log { [CmdletBinding()] Param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [Alias("LogContent")] [string]$Message, [Parameter(Mandatory = $false)] [Alias('LogPath')] [string]$Path = 'C:\Logs\PowerShellLog.log', [Parameter(Mandatory = $false)] [ValidateSet("Error", "Warn", "Info")] [string]$Level = "Info", [Parameter(Mandatory = $false)] [switch]$NoClobber ) Begin { # Set VerbosePreference to Continue so that verbose messages are displayed. $VerbosePreference = 'Continue' } Process { # If the file already exists and NoClobber was specified, do not write to the log. if ((Test-Path $Path) -AND $NoClobber) { Write-Error "Log file $Path already exists, and you specified NoClobber. Either delete the file or specify a different name." Return } # If attempting to write to a log file in a folder/path that doesn't exist create the file including the path. elseif (!(Test-Path $Path)) { Write-Verbose "Creating $Path." $NewLogFile = New-Item $Path -Force -ItemType File } else { # Nothing to see here yet. } # Format Date for our Log File $FormattedDate = Get-Date -Format "yyyy-MM-dd HH:mm:ss" # Write message to error, warning, or verbose pipeline and specify $LevelText switch ($Level) { 'Error' { Write-Error $Message $LevelText = 'ERROR:' } 'Warn' { Write-Warning $Message $LevelText = 'WARNING:' } 'Info' { Write-Verbose $Message $LevelText = 'INFO:' } } # Write log entry to $Path "$FormattedDate $LevelText $Message" | Out-File -FilePath $Path -Append } End { } } ### own Functions ### function Mount-SCCMShare { $DriveName = 'SCCMRepo' If (!(Get-PSDrive -name $DriveName -ErrorAction SilentlyContinue)) { try { New-PSDrive -name $DriveName -PSProvider "FileSystem" -Root $SCCM_Repo -Credential $credential -Scope Script } catch { Write-Log -Path $LogfileName -Level Error -Message "Can not Mount SCCM Share $SCCM_Repo" Exit } } } Function SCCMClientInstaller { ########################################################################### ## SCCM Client Health check and Troubleshooting Script ## Author: Lokesh Agarwal ## Date: 23-08-2017 ## Input:- SCCM Client path, MP Address, Site Code ## Edited: Jeremias Kühnis 27.09.2019 -> Added/Modifying some Code and add some Log Warning ########################################################################### ############################### Main Code #################################### $machinename = hostname ############################### Check if WMI is working ####################### if ((Get-WmiObject -Namespace root\ccm -Class SMS_Client -ErrorAction SilentlyContinue) -and (Get-WmiObject -Namespace root\ccm -Class SMS_Client -ErrorAction SilentlyContinue)) { Write-Log -Path $LogfileName -Level Info -Message "WMI is OK" $WMI_Status = "Working" } else { Write-Log -Path $LogfileName -Level Warn -Message "Try to Repair WMI" Stop-Service -Force winmgmt -ErrorAction SilentlyContinue cd C:\Windows\System32\Wbem\ Remove-item C:\Windows\System32\Wbem\Repository.old -Recurse -Force -ErrorAction SilentlyContinue -Confirm:$false rename-Item Repository Repository.old -ErrorAction SilentlyContinue -Confirm:$false Start-Service winmgmt } ############################# Check if SCCM Client is installed ################## If (Get-Service -Name CcmExec -ErrorAction SilentlyContinue) { $Client_Status = "Yes" Write-Log -Path $LogfileName -Level Info -Message "SCCM Status OK, Client is installed" ########### Check if services are running ################################ $CcmExec_Status = Get-Service -Name CcmExec | % { $_.status } $BITS_Status = Get-Service -Name BITS | % { $_.status } $wuauserv_Status = Get-Service -Name wuauserv | % { $_.status } $Winmgmt_Status = Get-Service -Name Winmgmt | % { $_.status } $RRegistry_Status = Get-Service -Name RemoteRegistry | % { $_.status } if ($CcmExec_Status -eq "Stopped") { Write-Log -Path $LogfileName -Level Warn -message "Try to start Service $CcmExec_Status" Get-Service -Name CcmExec | Start-Service } if ($BITS_Status -eq "Stopped") { Write-Log -Path $LogfileName -Level Warn -message "Try to start Service $BITS_Status" Get-Service -Name BITS | Start-Service } if ($wuauserv_Status -eq "Stopped") { Write-Log -Path $LogfileName -Level Warn -message "Try to start Service $wuauserv_Status" Get-Service -Name wuauserv | Start-Service } if ($Winmgmt_Status -eq "Stopped") { Write-Log -Path $LogfileName -Level Warn -message "Try to start Service $Winmgmt_Status" Get-Service -Name Winmgmt | Start-Service } $MachinePolicyRetrievalEvaluation = "{00000000-0000-0000-0000-000000000021}" $SoftwareUpdatesScan = "{00000000-0000-0000-0000-000000000113}" $SoftwareUpdatesDeployment = "{00000000-0000-0000-0000-000000000108}" #################### check if Scan cycles are working ################### $machine_status = Invoke-WmiMethod -Namespace root\ccm -Class sms_client -Name TriggerSchedule $MachinePolicyRetrievalEvaluation $software_status = Invoke-WmiMethod -Namespace root\ccm -Class sms_client -Name TriggerSchedule $SoftwareUpdatesScan $softwaredeploy_Status = Invoke-WmiMethod -Namespace root\ccm -Class sms_client -Name TriggerSchedule $SoftwareUpdatesDeployment if ($machine_status -and $software_status -and $softwaredeploy_Status) { $machine_Rstatus = "Successful" Write-Log -Path $LogfileName -Level Info -message "Scan cycles are working $machine_Rstatus" } else { $SMSCli = [wmiclass] "root\ccm:sms_client" Write-Log -Path $LogfileName -Level Warn -message "Scan cycles are not working, try to repair SMSCLI-Client" $repair = $SMSCli.RepairClient() } } else { ############## Install SCCM Client ############################### Write-Log -Path $LogfileName -Level Info -message "Missing SCCM Client, try to start installation" &$SCCM_ClientInstaller /mp:$SCCM_MPServer /logon SMSSITECODE=$site_code Start-Sleep 5 DO { $ProcessesFound = (Get-Process -name ccmsetup -ErrorAction SilentlyContinue) If (($ProcessesFound) -and ($counter -le "90")) { Start-Sleep 10 $counter++ Write-Host "Still running: $($ProcessesFound) $counter" } Else { IF ($counter -gt "90") { Write-Log -Path $LogfileName -Level Error -message "Not OK: Try to kill running Process while InstallationProcess is taking more than 15 Minutes" Get-Process ccmsetup | Stop-Process -Force Exit } Else { Write-Log -Path $LogfileName -Level Info -message "OK:Process ended by SCCM installer." } } } Until (!$ProcessesFound) } #################################################################################################### } function New-folder { [CmdletBinding()] Param( [Parameter(Mandatory = $true)][string]$folderpath ) If (!(Test-path $folderpath)) { New-Item $folderpath -ItemType Directory } } function VerifyPrerequisits { #Check Powershell Version $psversion = $PSVersionTable.PSVersion.Major IF ($psversion -ge "5") { Write-Log -Path $LogfileName -Level Info -Message "Powershell Version is OK – $psversion" } Else { Write-Log -Path $LogfileName -Level Error -Message "Missing PowerShell or installed Version is to low – $psversion " $Errorcouonter = "1" } #Check .Net FrameWork Version $DotNetVersion = (Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\' | Get-ItemPropertyValue -Name Version) IF (Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\' | Get-ItemPropertyValue -Name Release | Foreach-Object { $_ -ge 461814 }) { Write-Log -Path $LogfileName -Level Info -Message ".NetVersion ist OK – $DotNetVersion" } else { Write-Log -Path $LogfileName -Level Error -Message "Missing .NetFramework or installed Version is to low – $DotNetVersion " $Errorcouonter = "1" } #Verify SourcePath IF (!(Test-Path $SCCM_Repo) ) { Write-Log -Path $LogfileName -Level Error -Message "Can not find SCCM installer Path: $SCCM_Repo" $Errorcouonter = "1" } ##Last Part If ($Errorcouonter -eq "1") { Write-Log -Path $LogfileName -Level Warn -Message "Installation is not performed because the checked prerequisites are Wrong/Missing. See further up in the log." exit } Else { Write-Log -Path $LogfileName -Level Info -Message "Prerequisits are Okay, try to lead trough installation" } } Function Remove-InstallerLocation { $removepaths = @( "$LocalSource_Path\Client" ) foreach ($ToDelPath in $removepaths) { Remove-Item $ToDelPath -Recurse -Force -ErrorAction SilentlyContinue } } ################### ### Main Script ### ################### $password = $JoinADUserPw | ConvertTo-SecureString -asPlainText -Force $credential = New-Object System.Management.Automation.PSCredential($JoinADUser, $password) ### Create C:\Temp Folder, if not Exists for logs ### New-folder -folderpath $LocalSource_Path ### Join AD-Section ### #Need to Add credentials and start Job for OU path $Error.Clear() Try { Add-Computer -DomainName $fqdn -Credential $credential -OUPath $ADOU_NewAzuewDevice -Force -ErrorAction Stop } catch [System.Net.WebException], [System.Exception] { Write-Log -Path $LogfileName -Level Error -Message "Failed @ Ad-join Part...maybe ADAccount already exists." Write-Log -Path $LogfileName -Level Error -Message $Error Exit } Mount-SCCMShare VerifyPrerequisits ### Install SCCM-Client Section ### Write-Log -Path $LogfileName -Level Info -message "Start-SCCM Repair/ Install Process..." Copy-Item $SCCM_Repo -Recurse -Destination $LocalSource_Path -Force SCCMClientInstaller Write-Log -Path $LogfileName -Level Info -message "End Section: 'Start-SCCM Repair/ Install Process...'" Write-Log -Path $LogfileName -Level Info -message "Finished all Jobs, if there are any Problems Check if Computer is joined in AD and Check the Execution Policy. Also Check de Install status of SCCM Client." Write-Log -Path $LogfileName -Level Info -message "Try to clean Up local install Files" Start-Sleep 3 Remove-InstallerLocation Write-Log -Path $LogfileName -Level Info -message "Successfully finish..." #reboot while AD-Join shutdown -r -f -t 60 |
0