Creating Configuration Manager Collections and Deployments

I do a lot of application packaging and deployment at work, so recently I’ve been experimenting with using PowerShell to speed up some of my testing procedures. To that end, I have some scripts that do the following:

  1. Create a collection in Configuration Manager
  2. Add a computer to that collection
  3. Create an application deployment targeted at the collection I created
I have three separate PowerShell scripts to do this work. They all work correctly.

I’ve tried to combine the three scripts into one. But in doing so, I now get an error that I can’t explain and can’t figure out how to fix. Code for the one script combining the three smaller scripts is below. The error occurs at the following line:

[pre]Add-CMDeviceCollectionDirectMembershipRule -CollectionName $CollectionName -ResourceID $(get-cmdevice -name $DeviceName).ResourceID[/pre]

The error message is:

Add-CMDeviceCollectionDirectMembershipRule : One or more errors occurred.
Add-CMDeviceCollectionDirectMembershipRule -CollectionName "$Collecti …
CategoryInfo : NotSpecified: (:slight_smile: [Add-CMDeviceCol…tMembershipRule], AggregateException
FullyQualifiedErrorId : System.AggregateException,Microsoft.ConfigurationManagement.Cmdlets.Collections.Commands.AddDeviceCollectionDirectM
embershipRuleCommand

Here’s the full script:

[pre]

change the drive to our Config Mgr site

$SiteCode = Get-PSDrive -PSProvider CMSITE

Set-Location $($SiteCode.Name):”

 

user prompts

$DeviceName = Read-host(“Enter the device name”)

$CollectionName = Read-host(“Enter the collection name”)

$ApplicationName = Read-host(“Enter the application name”)

 

Create the collection

Write-Host “Creating collection…”

New-CMDeviceCollection -Name $CollectionName -LimitingCollectionName ‘All Workstations’

 

Add device to collection

Write-Host “Adding device to collection…”

Add-CMDeviceCollectionDirectMembershipRule -CollectionName $CollectionName -ResourceID $(get-cmdevice -name $DeviceName).ResourceID

 

Move the collection to the Development folder

Write-Host “Moving collection…”

$Collection1 = Get-CMDeviceCollection -Name $CollectionName

Move-CMObject -InputObject $Collection1 -FolderPath ‘SMS:\DeviceCollection\Engineering\Development’

 

Create the deployment.

Write-Host “Creating deployment…”

New-CMApplicationDeployment -CollectionName $CollectionName -name $ApplicationName

-DeployAction Install -DeployPurpose Required -UserNotification DisplayAll -AvailableDateTime (get-date) `

-DeadlineDateTime (get-date) -TimeBaseOn LocalTime -SendWakeupPacket $true -Verbose

[/pre]

 

I do not have SCCM to look at or validate this, but there are things that need to be taken under consideration.

<li>You never need Write-Host for sending text to the screen unless you are using color or special formatting.</li>

<li>You never need double quotes unless you need to expand variables, or other custom formatting.</li>

<li>Use splatting for commands with parameters or switches that are very long. </li>

The Graveyard Accent is fine and I too still use it, but I bring this up because many just complain about it. The complaint is it’s hard to see, if fails if you don’t remember spacing, yadda, yadda, yards. Personally I don’t have / never had an issue with it.

So, your script would end up like this. This method allows you to pass parameters and arguments vs prompting, but if on is skipped, you’ll get prompted for it. It does not have to be a function. I just did it this way to quick test. TO use as a regular script, just remove the opening and closing function stuff.

As for the error, that error seems to indicated that require info needed to process the next step is not available. So, you will need to either add a delay or use error / validation checking for the active action before moving to the next. Think Do/While or Try catch. I only say this, because if you run them individually, of course there is a natural delay by your manual effort for each.

function New-SCCMDeployment 
{
    param 
    (
        # user prompts
        $DeviceName = (Read-host('Enter the device name')),
        $CollectionName = (Read-host('Enter the collection name')),
        $ApplicationName = (Read-host('Enter the application name'))
    )

    # change the drive to our Config Mgr site
    $SiteCode = Get-PSDrive -PSProvider CMSITE
    Set-Location "$($SiteCode.Name):\"
     

    # Create the collection
    'Creating collection...'
    New-CMDeviceCollection -Name $CollectionName -LimitingCollectionName 'All Workstations'


    # Add device to collection
    'Adding device to collection...'
    Add-CMDeviceCollectionDirectMembershipRule -CollectionName $CollectionName `
    -ResourceID $(get-cmdevice -name $DeviceName).ResourceID


    # Move the collection to the Development folder
    'Moving collection...'
    $Collection1 = Get-CMDeviceCollection -Name $CollectionName
    Move-CMObject -InputObject $Collection1 -FolderPath 'SMS:\DeviceCollection\Engineering\Development'


    # Create the deployment.
    'Creating deployment...'

    $Params = @{
        CollectionName = $CollectionName
        Name = $ApplicationName
        DeployAction = 'Install'
        DeployPurpose = 'Required'
        UserNotification = 'DisplayAll' 
        AvailableDateTime = (get-date)
        DeadlineDateTime = (get-date)
        TimeBaseOn = 'LocalTime'
        SendWakeupPacket = $true
        Verbose = $true
    }
    New-CMApplicationDeployment @Params
}

# Example use
New-SCCMDeployment -DeviceName -CollectionName -ApplicationName

Thanks for the reply, postanote. All valid points you make, and I will update the script accordingly.

Did a bit more testing yesterday and was also starting to lean toward the error maybe being caused because of a timing issue, so I’m going to add in some error handling and see what happens.

Thanks again, much appreciated!

Had hoped to post a final version of the code by now, but I’m still getting the ambiguous error message.

As mentioned in my original post, I have three separate scripts that I wanted to combine into one. But when I combined them, I began to get an error message at the point where the script attempts to add a computer to a collection. First script creates the collection, second script adds a computer to that collection.

I can run those two scripts separately one right after the other and it always works.

If I run the combined script, it errors.

Started sounding like it was a timing issue, that enough time was passing between the time I ran the two individual scripts to account for the success, but I began to run them as quickly as I could so that only a couple seconds passed between them. And still, always successful.

I changed the order of the user prompts in the combined script so that I could control the amount of time that passes between the action of the first script (create the collection) and that of the second script (add a computer to that collection). In testing yesterday, I waited up to an hour before typing in the name of a computer and letting the script continue on. And still it failed.

So for now I’m stumped. It doesn’t seem like a timing issue, but I have no idea why it’s throwing the error, and haven’t found any more info online to give me any additional clues as to a potential fix.

Believe I’ve solved this, although I can’t explain WHY.

Only change I made to the script was to change this line:

[pre]Add-CMDeviceCollectionDirectMembershipRule -CollectionName $CollectionName -ResourceID $(get-cmdevice -name $DeviceName).ResourceID[/pre]

to this:

[pre]Add-CMDeviceCollectionDirectMembershipRule -CollectionName $CollectionName -ResourceID $ResourceID [/pre]

I’ve tested at least a couple dozen times and have not experienced the error message I was getting.

Try putting a sleep between them

IF that fails, use a if/then between them. Meaning run one, use the if to check for success then move to the next, and so on.