Add Computer to Collection during OSD via the ConfigMgr AdminService

In this post you learn how to configure your ConfigMgr task sequence to add a machine to a collection during deployment via the ConfigMgr AdminService. You will setup a service account, grant the minimal permissions for a service account in ConfigMgr, and then use a PowerShell script in the task sequence to trigger the ConfigMgr AdminService (administration service) to add the machine to the collection.

Update November 5, 2023: Worked with Adam Gross (last weekend) to fix an issue when running in environments using username and password. Adam created a Johan edition of the PowerShell module that works in full OS deployment task sequences. Thanks Adam!

Credits: Big thanks to the following Community Champions: To Adam Gross (again) for his amazing ConfigMgr.AdminService PowerShell module, and to Nickolaj Andersen and Maurice Daly for a solution to the below error message that you may encounter when trying to use the ConfigMgr Admin Service:

System.Net.WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. —> System.Security.Authentication.Authenticati
onException: The remote certificate is invalid according to the validation procedure.
at System.Net.TlsStream.EndWrite(IAsyncResult asyncResult)

Creating the Device Collection

First, you need to have a device collection to which you want to add the computer account. In my lab the device collection was named Co-Management Clients. I use this collection to only have a subset of my machines being enrolled into Intune by ConfigMgr. Meaning that the Automatic enrollment in Intune feature is set to Pilot in the Co-Management Properties.

Real World Note: When configuring these settings in ConfigMgr, you will find that ConfigMgr deploys a set of internal configuration policies to that collection. These are used for the enrollment process.

Setting Automatic enrollment to Pilot in ConfigMgr.

Creating the Service Account

In Active Directory, create a domain user account, and configure its password to never expire. I named my service account CM_OSD, and gave it the following description: CM Service Account – Add Computer to Collection.

My CM_OSD Service Account.

Creating the Security Role in ConfigMgr

To ensure the service account cannot do more in ConfigMgr than it should, I created a custom security role named Add to Collection that only had access to modify resources for a given collection. For simplicity I made a copy of the built-in Read-only Analyst security role, and allowed modification of collections by changing the following permissions to Yes under Collection:

  • Modify
  • Modify Resource

Note: You probably don't want the service account to manage all collections, so you will select the specific collection when adding the service account as an administrative user in ConfigMgr.

Adding the Service Account as an Administrative User in ConfigMgr

Using the ConfigMgr console, in Administrative Users, add the CM_OSD service account, and assign it the Add to Collection security role.

Note: Don't remove the default All Systems collection. Machines that you deploy will be created in this collection, and you need permissions to read those devices in order for adding them to another collection.

Adding the Service Account as an Administrative User.

Creating a Package with the ConfigMgr.AdminService PowerShell module

Download the ConfigMgr.AdminService PowerShell module from this URL: https://github.com/AdamGrossTX/ConfigMgr.AdminService/tree/JohanEdition

Then run the build.ps1 script to create a folder with the PowerShell module.

Make a note of the output path from the build.ps1 script, and copy the content of that folder to a folder where you keep your data sources for ConfigMgr. In my example, I copied the module to a folder on a DFS Share: \\corp.viamonstra.com\fs1\Sources\OSD\Modules\ConfigMgr.AdminService.

The PowerShell module copied to a DFS Share.

Add the below script to the root of the package, name the script Add-ComputerToCollection.ps1.

<#
.SYNOPSIS
	Script to add the local computer to a specified collection´╗┐.
	
.DESCRIPTION
    This script will use the ConfigMgr.AdminService from Adam Gross to add the local compouter to a collection via the ConfigMgr Admin Service.

.PARAMETER CollectionName
	The ConfigMgr collection to add the computer to

.PARAMETER SMSProvider
	The SMS Provider on which the ConfigMgr AdminService is installed. Typically the site server.

.EXAMPLE
	.\Add-ComputerToCollection.ps1 -CollectionName "Co-Management Clients" -SMSProvider "cm01.corp.viamonstra.com"

.NOTES
    FileName:    Add-ComputerToCollection.ps1
	Author:      Johan Arwidmark
    Contact:     @jarwidmark
    Created:     09/25/2023
    Updated:     09/25/2023
	
    Version history:
    1.0.0 - 09/25/2023 - Script created
#>

param(
    [Parameter(Mandatory)]
    [string]$CollectionName,

    [Parameter(Mandatory)]
    [string]$SMSProvider
)

$Logfile = "C:\Windows\Temp\AddComputerToCollection.log"

# Delete any existing logfile if it exists
If (Test-Path $Logfile){Remove-Item $Logfile -Force -ErrorAction SilentlyContinue -Confirm:$false}

Function Write-Log{
	param (
    [Parameter(Mandatory = $true)]
    [string]$Message
   )

   $TimeGenerated = $(Get-Date -UFormat "%D %T")
   $Line = "$TimeGenerated : $Message"
   Add-Content -Value $Line -Path $LogFile -Encoding Ascii 

}

Write-Log "Starting Add-ComputerToCollection.ps1"

$ComputerName = "$env:COMPUTERNAME"
Write-Log "Computer name is: $ComputerName" 
Write-Log "Collection name is: $CollectionName" 
Write-Log "SMS Provider is: $SMSProvider" 

Write-Log "Importing ConfigMgr.AdminService PowerShell module" 
Import-Module "$PSScriptRoot\ConfigMgr.AdminService.psd1" 

# For testing
# $CollectionName = 'Co-Management Clients' 
# $SMSProvider = 'cm01.corp.viamonstra.com'
# Import-Module "C:\Temp\ConfigMgr.AdminService\ConfigMgr.AdminService.psd1" 

# Get Credentials from task sequence variables
$TSEnv = New-Object -ComObject Microsoft.SMS.TSEnvironment

$username = $TSEnv.Value("OSDAddToCollectionUserName")
$password = ConvertTo-SecureString $TSEnv.Value("OSDAddToCollectionPassword") -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($username, $password)

Write-Log "Username set to $username"
Write-Log "Password set to ***Secret***"

# Initialize CMAdminService
Write-Log "about to run the Initialize-CMAdminService function"
Try {
    Initialize-CMAdminService -AdminServiceProviderURL "https://$SMSProvider/AdminService" -UseLocalAuth -LocalAuthCreds $credential -ErrorAction Stop 
}
Catch {
    $errorMessage = $_.Exception.Message
    write-Log "Initialize-CMAdminService Failed, error message: $errorMessage"        
}

# Add Computer to Collection, try for up to 10 minutes
$MaxRetries = 10
$i = 1
do { 
    Write-Log "Searching for the $ComputerName device in ConfigMgr, Attempt $i of $MaxRetries"
    Try {
        $Device = Get-CMDevice -Name $ComputerName
    }
    Catch {
        $errorMessage = $_.Exception.Message
        write-Log "Get-CMDevice failed, error message: $errorMessage"        
    }
    If ($Device){
        $DeviceCount = ($Device | Measure-Object).Count
        If ($DeviceCount -eq 1){
            $SelectedDevice = $Device
            Write-Log "One Device found matching the $ComputerName computer name having Resource ID: $($SelectedDevice.MachineId)"
            
        }
        Else {
            Write-Log "$DeviceCount Device(s) found matching the $ComputerName computer name, selecting the first match"
            $SelectedDevice = $Device | Select -First 1
            Write-Log "Selected Device matching the $ComputerName computer name having Resource ID: $($SelectedDevice.MachineId)"
        }
        
        
        # Check wether its a real Resource ID and not a discovery record
        If (([string]$SelectedDevice.MachineId).substring(0,1) -eq 1){
            Write-Log "Adding $ComputerName to the $CollectionName collection"
            Try {
                $CMDirectRule = New-CMDirectRule -InputObject $SelectedDevice -RuleName $ComputerName -ErrorAction Stop
                $Collection = Get-CMCollection -Name $CollectionName
                Add-CMCollectionRule -Collection $Collection -CollectionRule $CMDirectRule  -ErrorAction Stop
            }
            Catch {
                $errorMessage = $_.Exception.Message
                write-Log "Adding Computer to Collection Failed (New-CMDirectRule,Get-CMCollection and Add-CMCollectionRule commands), error message: $errorMessage"        
            }
            # Exit the loop
            Break
        }
    }
    Else{
        Write-Log "Device not found in ConfigMgr, retrying to find $ComputerName. Attempt $i of $MaxRetries"
        Start-sleep -Seconds 60
    }
    $i++
}
while ($i -le $MaxRetries)

You should now have a folder structure looking like this:

Completed package content after also adding the Add-ComputerToCollection.ps1 script.

Create a ConfigMgr Legacy Package using the preceding content as its data source. No program needed. I named my package Add Computer To Collection via AdminService.

Configuring your Task Sequence(s)

1. In the Windows phase of your task sequence, typically near the end, add a new group named Add Computer To Collection via AdminService. In that group, add the following actions:

2. Add a Set Dynamic Variables action named Set Add To Collection Variables. Add the OSDAddToCollectionUserName and OSDAddToCollectionPassword variables to match your environment.

3. Add a a Run PowerShell Script action. Configure it with the following settings:

  • Name: Disable Provisioning Mode
  • Enter a PowerShell script: (use below script
Invoke-WmiMethod -Namespace root\CCM -Class SMS_Client -Name SetClientProvisioningMode -ArgumentList $false
  • PowerShell execution policy: Bypass

4. Add a Run Command Line action. Configure it with the following settings:

  • Name: Pause for 5 Minutes
  • Command line: powershell.exe -Command Start-Sleep -Seconds 300

4. Add a Run PowerShell Script action. Configure it with the following settings:

  • Name: Add Computer To Collection
  • Package: Select the Add Computer To Collection via AdminService.
  • Script name: Add-ComputerToCollection.ps1
  • Parameters: -CollectionName "Co-Management Clients" -SMSProvider "cm01.corp.viamonstra.com"
  • PowerShell execution policy: Bypass
Task Sequence with the Add Computer To Collection step added.
About the author

Johan Arwidmark

5 1 vote
Article Rating
Subscribe
Notify of
guest
25 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
Uli
Uli
3 months ago

Hi Johan,
Thanks a lot for this helpful guidance!
Is there also a way to remove machines out of a collection via the ConfigMgr AdminService?

Regards
Uli

Uli
Uli
3 months ago

Do you have a example of the WMI method, or where can I research it?

Jonathan Caserta
Jonathan Caserta
4 months ago

Hrmm… I can't seem to get this to work. when running the import command manually on a machine, it looks like it import it. I don't see it in a "get-installedmodule" list, and none of the commands are recognized.

Jonathan Caserta
Jonathan Caserta
4 months ago

verbose shows the modules being exported but commands still not recognized. I went back and checked to make sure i had the current version (it looks like there was an update at some point after MMS) and everything looked correct. Im using the Johan version.

Jonathan Caserta
Jonathan Caserta
3 months ago

Does the module only work on a system that ran the build.ps1? I built the module and then copied the files to the network share.

Jonathan Caserta
Jonathan Caserta
3 months ago

Does this work with Windows 11? I really want this to work. Ill have to rebuild and see if something is missing.

David
David
4 months ago

This is really helpful, thanks a lot!
Is it possible to have a workaround having the User Password in plain text in the Task Sequence (even if only Admins have access to the Task Sequence)?
Maybe with a "Run PowerShell Script" step with option "Run this step as the following account"

Last edited 4 months ago by David
Tim
Tim
6 months ago

Thanks for all the work on this. No matter how I configure the task sequence, the AddcomputertoCollection.log always returns "Initialize-CMAdminService failed: The term 'Initialize-CMAdminService' is not recognized" and "Get-CMDevice failed, error message: The term 'get-CMDevice' is not recognized…"
I don't see an error about importing Configmgr.AdminService powershell module.

Thanks for any advice.

SomeZyla
SomeZyla
5 months ago
Reply to  Tim

Re-download the files from https://github.com/AdamGrossTX/ConfigMgr.AdminService/tree/JohanEdition

You most likely snagged the files from the main tree (https://github.com/AdamGrossTX/ConfigMgr.AdminService/tree/main) which the Initialize-CMAdminService function on that tree does NOT have a parameter for LocalAuthCreds.

Ask me how I know ­čÖé

Tyler
Tyler
7 months ago

Hello Adam,

Thanks for your work on this. I followed the steps provided for use in one of our SCCM OSD task sequences. However, it's failing because none of the commands are recognized (when checking the log).

Is there some sort of pre-req required that I'm missing?

Justin
Justin
7 months ago

Thanks for this! Is there any reason why steps 2 and 3 were separated out instead of included in the main powershell script? Seems it would be cleaner and use fewer steps

Justin
Justin
7 months ago

Apologies, I meant steps 3 and 4 – disabling provisioning and the sleep command. Seems to me both of those can be rolled into the beginning of the script in step 5.

I fully agree with using the variables to keep the username/password hidden.

Lindsay
Lindsay
8 months ago

Hi Johan,

Great article / solution to adding a PC to a collection during the TS. Thanks!
During your testing, did you ever have the error of "error creating the web proxy specified in the 'system.net/defaultproxy' configuration section" when trying to run the script?
I haven't been able to get it working due to that error

I also had to give the domain service account local admin permissions temporarily to get that far.


>