SCCM 2012 SP1 – Remove Client from Collection after OSD

Times are changing, so are our scripts. I can’t tell you how often I used this VB-Script http://ccmexec.com/2012/07/remove-from-collection-and-clear-pxe-flag-vbscript-using-status-filter-rule/ , but I think now, the new cmdlets for powershell are more comfortable. So I decided to change my auto-remove to a powershell script.

This is what you need, that the script will run:
-Trust the Module that has to be imported
(This will be explained in the Blog)
-The script has to be executed in x86 mode
-The server that runs the rule has to be added with permissions

So, let’s start with the prerequisites, they are Powershell 3 and the SCCM 2012 SP1 Console, and you have to trust the module of the configuration manager psd file. This can be done through starting the powershell console via the SCCM console:
Start SCCM Powershell

You should decide to always trust this module, otherwise the script will always ask, and when run through Status Filter Rules, the script will fail to run.

Trust module

It is also necessary that the SCCM Server has right in SCCM itself. You can achieve this, when you add the SCCM Server via Console. I decided to use the Full Administrator role, it’s upon you, how far you want to go. If you don’t add the server, the script will fail, because the psdrive of your site will not be found. Typical error message is: “Cannot find drive. A drive with the name ‘$Sitecode’ does not exist.” When you start a powershell session with “NT AuthoritySystem” and try manually to import the module, when changing on the ps-drive, it will fail. So add your server as in the print-screen beyond.SCCM Server permissionThe Server also needs the DCOM Remote Access Permission:
DCOM SCCM Permission

You will have to change the variable “$CollectionIDs” to apply it on your environment. You can change the variable $bEventlogEntry to “0”, then the script will not write in the Application log of the Server. And with $bClearPXE = “1” the PXE flag will be cleared after the computer is removed from the collections.

Here is the script (It’s on my skydrive):
https://1drv.ms/t/s!Aq0GcVCqC0RlhTtNDcR9uJRgGf3X

————————–

#Call example:
#C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy ByPass RemoveFromCollection_1.0.ps1 %msgsc %msgsys
#%msgsc = Site-Code
#%msgsys = ComputerName


#Set required Input Parameters
Param(
[string]$SiteCode,
[string]$ComputerName
)


#--------------------
#User defined variables here

$CollectionIDs = "S0100025;S010002C;S010001E"
$bEventlogEntry = "1"
$bClearPXE = "0"


#End user defined variables
#--------------------

If($SiteCode -and $ComputerName){}
else{
Write-Host "Required Input is missing! Omit SiteCode and Computername."
exit
}

#$SiteCode = "S01"
#$ComputerName = "rudolph"

#Check for 32-bit execution
If ($env:Processor_Architecture -ne "x86") {
write-host "Script has to be executed in x86 mode!"
exit
}

#Import SCCM Module
$ModuleName = (get-item $env:SMS_ADMIN_UI_PATH).parent.FullName + "ConfigurationManager.psd1"
Import-Module $ModuleName
CD $SiteCode":"

#Remove Client from collections
#Get collection id array
$aCollections = ($CollectionIDs).Split(";")

#check for each collection if a directmember chip exist, and remove it
foreach($Collection in $aCollections){
If((Get-CMDeviceCollectionDirectMembershipRule -CollectionId $Collection -ResourceName $ComputerName).count -eq 1) {


#Write Eventlog entry
If($bEventlogEntry -eq 1){
write-eventlog -logname Application -source "SMS Client" -eventID 3001 -entrytype Information -message "Computer $ComputerName will be removed from Collection $Collection" -category 1 -rawdata 10,20
}


#Remove Client from collection
Remove-CMDeviceCollectionDirectMembershipRule -CollectionId $Collection -ResourceName $ComputerName -Force

#Clear PXE Flag
If($bClearPXE -eq 1){
Clear-CMPxeDeployment -DeviceName $ComputerName
}
}
}

————————–

When you have copied the script, then it’s time to create the Status Filter Rule:

Create Status Filter Rule

Fill up the following values in the Wizard:
Name: Remove Client when OSD finished
Component: Task Sequence Manager
Message ID: 11171

Status Filter Rule wizard

In the action tab, you can choose to create a eventlog entry, if you want to see, that the status filter rule really triggers. And you will have to specify the “Run a program” option as following, make sure that you are using the full Path of the powershell executable:
C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy ByPass “<path to script>RemoveFromCollection_1.0.ps1” %msgsc %msgsys

As written above, Powershell x86 is needed, probably you will have to define the execution policy and don’t forget the variables “%msgsc %msgsys”. The picture:
Stauts Filter Rule Action

Finish the wizard and enjoy the automatic removing of your clients from your OSD Collections.

Hope this helps, Martin 🙂

45 thoughts on “SCCM 2012 SP1 – Remove Client from Collection after OSD

  1. Do not underestimate the effect of this process in larger environments.
    What I found out when automating our worldwide os deployment was that if you want collection handling to scale (~ 100 osd preparations/finished installations a day, worldwide – so ~200 collection modifications a day) the collection evaluator (at least in SCCM 2007 SP2 R3) will not be fast enough to correctly handle all the collection modification requests.

    I came up with using a webservice that registers the job to remove the client from the collection, pools them and on a defined timer uses DeleteMembershipRules from SMS_Collection instead of DeleteMembershipRule.

    However, we’re using queries with the devices MAC instead of direct memberships (due to several reasons) and I haven’t looked at what exactly the SCCM 2012 SP1 cmdlets do in the background.
    From my experience however, I guess it still just calls DeleteMembershipRule.

  2. Hi Martin, very interesting this Approach..
    However, If i try to create the Status Filter rule, I canot find the Tasksequence Manager in the selection. Any Idea what this can be? I use SCCM 2012 SP1.

    Many thanks

    markus

  3. Hi Martin,

    the Eventlog Entry will generated now after succesfully OSD. But the Client is still in the OSD Collection. Any idea where I can check If the script is running correctly?

    “On 6/26/2013 4:36:00 PM, component Task Sequence Manager on computer TEST1234567 reported: The task sequence manager successfully completed execution of the task sequence.”

    The Commandline Looks like this.
    C:WindowsSysWOW64WindowsPowerShellv1.0powershell.exe -ExecutionPolicy ByPass “E:PSScriptsRemoveFromCollection.ps1” %msgsc %msgsys

    I have added also all the Collections IDs for OSD in the Script.
    The Site System is running on Server 2012.

    Would be great If you can give me a Information where/how I can fix this.

    Thanks

    Makrus

    • Just one more question about the Script..
      The beginning looks like this
      ————–
      #%msgsc = Site-Code
      #%msgsys = ComputerName

      #Set required Input Parameters
      Param(
      [string]$SiteCode,
      [string]$ComputerName
      ————————-
      MSGSC and MSGSys is commentet out and the Paramater site code is different.
      Should it not be like this

      ————-
      %msgsc = SiteCode
      %msgsys = ComputerName

      #Set required Input Parameters
      Param(
      [string]$SiteCode,
      [string]$ComputerName
      ————–

      Thanks

      Markus

      • no it should not. Those are commented out to declare what those SCCM variables do.
        in the part “#Set required Input Parameters” the command line variables are set to those two variables.

    • Hi Markus,

      so when the Eventlog is written through the Powershell Script, the script is started well.
      There can be now 2 Problems:
      1. Site Server has no rights to write to SMS Provider
      2. The “ConfigurationManager.psd1” is no from a trusted Publisher

      • Its strange… the script won’t be executed… No, glue what it can be at the moment………

      • I can execute the script manually, but nothing is happend. No Entry in the eventlog either a removal of the machine from the collection. No error message when i execute the script. I have also tried to set the execution policy to unrestricted. I have execute the script in Powershell 32bit.

  4. I am also trying the manual method by specifying my Site code and computer name, however it seems to take time to process the command (5 seconds) but then nothing has happened device still in collection not event log entry?

    could you please explain how the script it gets the site code and computername
    I see the entries hashed out
    #sitecode = “”
    #Computername = “” (I can understand this as we what this remain a variable)

  5. I think there may be an issue with the script unless I’m doing something completely wrong. The line: (Get-CMDeviceCollectionDirectMembershipRule -CollectionId $Collection -ResourceName $ComputerName).count -eq 1)… returns nothing for me, but if I remove the count and pipe the output to Measure-Object, I do get the correct count. This seems to be the issue in my case, but I’m not exactly sure how to fix it.

    • please look to comment #18, i think i had the same problem and solved it with Get-CMDeviceCollectionDirectMembershipRule -CollectionId $Collection -ResourceName $ComputerName).count -ne 0.

  6. Hi,
    we also tried to use the script in our environment. Current status, it only works if i start it manually.

    First nothing happened after executing the script, so i integrated some “debugging” steps and printed out variables and strings if the script goes in the for-loop or if-query. It seems correct, but i found that
    If((Get-CMDeviceCollectionDirectMembershipRule -CollectionId $Collection -ResourceName $ComputerName).count -eq 1)
    doesn’t work in our environment. Perhaps it is the same problem that you have.
    I replaced it with
    If((Get-CMDeviceCollectionDirectMembershipRule -CollectionId $Collection -ResourceName $ComputerName).count -ne 0)
    and voilá, it works, but only manually :-/

    We have the following situation:
    – Security settings are done
    – script starts
    – variables are all correct
    – Collection ID’s are correct
    – Computer is in the Collection

    –> Get-CMDeviceCollectionDirectMembershipRule -CollectionId $Collection -ResourceName $ComputerName doesn’t work, there is no result. There is only no result if the script is started from SCCM itself, if i start the script manually it works.

    Perhaps there is a problem with importing the module or with another subject, i’m at a loss. Martin do you have an idea?

    Thanks,
    Lukas

  7. I think it’s worth mentioning that I am running SCCM SP1 CU1 so this might affect how the script runs,

    I am still not having much luck

  8. I tested the script a few times again..

    I found out that cd S01: doesnt’ work –> So i try to start a powershell session with the System Account (I should do it at an earlier date), i manually import the module, try to change on the ps-drive, and …. it fails.
    However, i added the SCCM Server to the Administrative Users as Full Administrator and changed the DCOM Remote Access Permission.
    Do you have any idea?

  9. I’m having the same issue as Lukas – if you use psexec -s cmd.exe to invoke a SYSTEM command-prompt, and try loading the ConfigurationManager.psd1, it doesn’t error out when loading the module, but you can’t see the ConfigMgr PSDRIVE when you do a get-psdrive. If you do a get-module it also doesn’t show the ConfigurationManager module being loaded. So it doesn’t appear to actually load the module for some reason.

    • I solved the issue..
      Try to start the Configuration Manager Console as Administrator with Run as Administrator. As i clicked on Connect Via PowerShell the request to trust the configuration manager psd file comes up again. I chose again always trust this module.
      After this i started powershell console as system account with psexec -i -s C:WindowsSysWOW64WindowsPowerShellv1.0powershell.exe -ExecutionPolicy ByPass, checked that the PowerShell session runs under the system account with whoami and import the configuration manager module. After this i was able to change on PSDRIVE.
      Now the script runs well.

      • Yeah, thanks for everyone helping eachother 🙂
        But isn’t this step:
        -Trust the Module that has to be imported (This will be explained in the Blog)
        That you missed?

  10. I did this step. I started the Configuration Manager Console, connected with PowerShell and trusted the module. However, the different was that i started the Console in the one way normally and in the other way as administrator.

  11. We’re running SCCM 2012 SP1 with CU1 and the script works when run manually, but doesn’t remove the computer from the collection when run with the Status Filter rule. I see the script run because I changed the script to output to the event log when it attempts to find the computer in the collection, but it doesn’t find the computer to remove it from the collection. Finally gave up and went with the VBScript solution which worked with much less effort.

  12. hi, you said “And with $bClearPXE = “0″ the PXE flag will be cleared after the computer is removed from the collections” but then the last part in the script has this:
    #Clear PXE Flag
    If($bClearPXE -eq 1){
    Clear-CMPxeDeployment -DeviceName $ComputerName

    which is contradictory.

    Can you please confirm if 0 or 1 the right value to clear the PXE flag? Thanks.

  13. Thank you for this script. For me it is a real life saver!

    However, working with SCCM 2012 R2, the script, at first, did not seem to work. After some research I realised that the script was not properly executed by the ‘SYSTEM’ account.

    To solve this I had to run the ‘Configuration Console’ with the SYSTEM account and then connect via windows Powershell and trust the Configurationmanager module.

    After that, it works like a charm.

  14. I needed to restart the server after changing the permissions, after this it worked as expected.

  15. Hi all,

    By any chance, was anyone of you successful in implementing this script with SCCM 2012 R2? We see to be running into issues and looping on an error 123 in our Status Messages.

  16. After many struggle, I was able to make the script work in a full R2 environment (Win 2012 R2 and SCCM R2)

    I know there’s a 1.1 post about this but I think it’s a bit unclear.

    Since SCCM R2 supports the execution of 64bits cmdlets,

    I had to strip out the “Check for 32bits execution” (like in 1.1)

    The unclear part is that for the script to work, you have to call the 64 bits Powershell. It didn’t worked using the 32bit version and I had to add the “-file” parameter.

    C:WindowsSystem32WindowsPowerShellv1.0powershell.exe -ExecutionPolicy ByPass -file RemoveFromCollection_1.0.ps1 %msgsc %msgsys

    Hopes it helps someone 🙂

    Ben

    • Hey Ben, thanks for sharing your experiences 🙂
      In my Environment, it is not needed to add the Parameter -file, even I do start the Script from an UNC Fileshare. You see, it’s very hard, to make a easy cook-book article for this script, as it was with VB-Script.
      I’m running SCCM 2012 R2 on Server 2012 RTM.

  17. Anyone just came up with this error 2012 R2 on only one machine the rest went fine with windows updates. Ideas? Load Fail, OSD module client can login work in word but hangs with word perfect?

  18. I had to add a line 36 to make mine work: so it now looks like this and works well. Also just FYI, if you only want one collectionID, you MUST leave the semicolon or the split command will break it. So: CollectionIDs = “ABC00001;” is how it should look with one collection ID.

    Import-Module $ModuleName
    New-PSDrive -Name $SiteCode -PSProvider CMSite -Root “$ENV:ComputerName” -Description “SCCM Site”
    CD $SiteCode”:”

  19. This is a great script and solution. I had to add a line of code to get it to work properly though. That line of code is:

    New-PSDrive -Name $SiteCode -PSProvider CMSite -Root $env:COMPUTERNAME -Description “SMSSite”

    And this is the section it needs to be added to:

    #Import SCCM Module
    $ModuleName = (get-item $env:SMS_ADMIN_UI_PATH).parent.FullName + “\ConfigurationManager.psd1”
    Import-Module $ModuleName
    New-PSDrive -Name $SiteCode -PSProvider CMSite -Root $env:COMPUTERNAME -Description “SMSSite”
    CD $SiteCode”:”

  20. Also, there was one limitation to this solution I was stuck on for a while so there’s an important element to add. The limitation is that this status filter rule runs every single time a task sequence succeeds. Consider this scenario: your OSD fails, the device is still a member of the OSD collection, then if another task sequence is deployed (required) to that device, it will run, succeed and then trigger the script and remove the device from the collection. I also added to the script an Send-MailMessage cmdlet to notify that the OSD is successful which will also happen, even though it was not an OSD task sequence that successfully ran in this situation, which causes confusion to the recipients of the email.

    So I searched for a way to be more granular in running the status filter rule. Specifically, I wanted the rule to only run on certain task sequences, the OSD task sequences. In order to do that, you’d need to somehow capture and parse a unique property such as the Deployment ID. I then realised Status Filter Rules can do this too! You just need to also tick the “source” checkbox, refer to this image in this blog post:

    select “Client” and then the property and property value fields can be set. Choose Advertisement ID and then select the exact Deployment ID of your OSD. Setting this up means the rule action will only run when your OSD runs and won’t be triggered by other task sequences.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s