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:
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.
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.The Server also needs the DCOM Remote Access 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:
Fill up the following values in the Wizard:
Name: Remove Client when OSD finished
Component: Task Sequence Manager
Message ID: 11171
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:
Finish the wizard and enjoy the automatic removing of your clients from your OSD Collections.
Hope this helps, Martin 🙂
[…] http://sccmfaq.wordpress.com/2013/05/20/sccm-2012-sp1-remove-client-from-collection-after-osd/ […]
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.
Thank you for your advice.
It definitely makes WMI calls to the Provider I think also.
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
Unfortunately, you can’t find this Component, just manually copy and Paste this String as mentioned above. It will work.
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
The event 11171 is written into the APP log not the 3001 from the Script.
so then check your ” in yout copied pasted string it seems there are two different “
Its strange… the script won’t be executed… No, glue what it can be at the moment………
is it possible to execute the script manually? I am lost
at the Moment…….
THX
M.
yes of course. Just replace %msgsc with your site code and %msgsys with your ComputerName
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.
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)
When you start the script manually, you can’t use the SCCM variables. Mind to start the script with the two Parameters for the site and the computername.
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.
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
Are you really using SCCM 2012 SP1?
I implemented this script 3 times, always with some struggles, but finally it worked…
So you might consider to still use the VB-Script
Yes we are using SCCM 2012 SP1.
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
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?
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?
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.
Ah ok, that’s a nice info. Was normal User only an RBAC allowed User without local Administrator Permissions on the Site Server?
No, the user had local Administrator Permissions on the Site Server.
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.
This is a good choice. I also have often Problems to implement this script, finally it works, but as you said, implementing the VBScript is much easier.
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.
Thank you, I’ve corrected this, With 1 it will be cleared, with 0 nothing will happen.
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.
I needed to restart the server after changing the permissions, after this it worked as expected.
[…] read my last blog post about this Topic carefully (https://blog.hosebei.ch/2013/05/20/sccm-2012-sp1-remove-client-from-collection-after-osd/), as a small reminder: -Trust the Module that has to be imported -The server that runs the rule has […]
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.
Hey Stephan,
yes we do. Please mind to use the new Script if your running R2 (https://blog.hosebei.ch/2014/01/23/sccm-2012-r2-remove-client-from-collection-after-osd-1-1/)
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.
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?
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”:”
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”:”
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.