Wednesday, November 28, 2007

SMS tool: What collection is a computer or User in?

[NOTE: I have updated this with a new version to work with SCCM and Maintenance windows collections-with-maintenance-windows (May 2008)]
OK I have this pulled from my C# app to vbscript. It isn't pretty but it works. The one problem is that I didn't create an array to sort the list so if you wanted sorted you will need to do it. I will update this later with the sort feature. Obviously I make no warranty. You will need to add the sever data and change the path to match your computer. Copy the vbscript to your folder, run the reg file and you will then see it in the MMC when you right click on a computer.

This will work with SMS 2003. To work with SCCM you will need to change the GUID and possible look at the WMI query for changes
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MMC\NodeTypes\{4D26C0D4-A8A8-11D1-9BD9-00C04FBBD480}\Extensions\SMS_tools\xCol Mem]
"Name"="Collection Membership"
"Description"="Show what collections a computer is in"
"CommandLine"="wscript.exe \"c:\\Program Files\\MCNS\\Collections\\computercols.vbs\" ##SUB:ResourceID##"

'------------ SCCM console -----------------
c:\program files Files\Microsoft Configuration Manager\AdminUI\XmlStorage\Extensions\Actions\7ba8bf44-2344-4035-bdb4-16630291dcf6


<actiondescription class="Group" displayname="MCNS" mnemonicdisplayname="MCNS" description="MCN Tools" sqmdatapoint="100">
<actiondescription class="Executable" displayname="Collection Listing" mnemonicdisplayname="Collection Listing" description="Display machine Collection membership">
<filepath>C:\Program Files\MCNS\collections\computercols07.vbs


---------------------------computercols.vbs -----------------------------------------------
Dim CollectionArray(100)

Set objArgs = WScript.Arguments
if (objArgs.count > 0) then
MyPos = InStr(objArgs(0), ":")
ResourceID = wscript.arguments.item(0)
end if

Set Shell = CreateObject("Wscript.Shell")
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set SWbemLocator=CreateObject("WbemScripting.SWbemLocator")
set SWbemServices = SWbemLocator.ConnectServer("server","root\SMS\site_XXX")
strQuery = "select * from SMS_CollectionMember_a where ResourceID='"+ ResourceID +"'"
Set Collections = SWbemServices.ExecQuery(strQuery)
for each Collection in Collections
set Collectionfound=SWbemServices.Get("SMS_Collection='" & Collection.CollectionID & "'" )
'Sort Collection list
for i = count - 2 To 0 Step -1
for j= 0 to i
if CollectionArray(j)>CollectionArray(j+1) then
end if

''' print out the collection listing
For NC = 0 to count-1
WhatCollections= WhatCollections & CollectionArray(NC) & VbCrLf
Wscript.echo WhatCollections

Friday, November 23, 2007

Add computer to collection, Vbscript

Edit: October 25, 2008
I have added a better way of doing this via a right click
Here at This uses a HTA file so you can right click on a computer and add it to collections or right click on a computer in a collection or query and add it to multiple collections.


I didn't create the script but someone had asked if there was a way to add a computer to a collection. I have the .Net code to do it but here is the vbscript method. This can be used to add the current computer to a collection as soon as the computer has imaged or performed some other action.

' *************************************************************************
' === Initialize Variables and Constants
' *************************************************************************
Option Explicit ' --- Force Declaration of variables
' === Script arguments override ====
' These variables are for testing only. To test, assign values to the variables and then comment out
' the Comment-out the ValdateArguments()subrourtine. To restur, comment out the variables below, and
' uncomment the ValdateArguments() subroutine to allow original argument values to be passed to the script.
'TargetCollectionName = "#Test-AddUser"
'NewComputerName = "LT01385"
' *************************************************************************
' == SMS Envronment Variables
CONST SMSSiteCode = "xxx" ' --- SMS Server Central Site Code
CONST SMSServer = "xxxxx" ' --- SMS Server
' -------------------------------------------------------------
' === Script varables
DIM lLocator ' --- Object handle for WMI Scripting "Locator object" ?
DIM gService ' --- Object hanlde for WMI object model ConnectServer object ?
DIM ResID ' --- Store the SMS ResourceID for the desired resource
DIM RuleName ' --- Name for Membership Rule (label seen in SMS collection properties)
DIM AllComputersSet ' --- Object handle to store the query results of the SMS System_R_System table
DIM AllComputersItem ' --- Index variable used for the AllComputersSet Object Collection (Array)
DIM CollectionRule ' --- CollectionRule
DIM oCollectionSet ' --- Object handle to store collection names from table SMS_Collection
DIM CollListItem ' --- Index variable for Collection Object (Array)
DIM WshShell ' --- Object handle for WshShell object (Windows Script Host Shell)
DIM oFSO ' --- Object handle for the FSO (File System Object)
DIM AddMembRuleSuccess ' --- Flag to track added collection membership rule status
Public TargetCollectionName ' --- Store command-line argument for desired collection name to add a computer resource
Public NewComputerName ' --- Store command-line argument for desired computer resource to add to the collection
' === Script Environment
' *********************************************************************************************
' ===== Connect to provider namespace for local computer.
' *********************************************************************************************
Set lLocator = CreateObject("WbemScripting.SWbemLocator")
Set gService = lLocator.ConnectServer(SMSServer, "Root\SMS\Site_" & SMSSiteCode)
' -- /// FileSytemObject already instantiated in subroutine ScriptPath() into object handle oFSO
' ********************************************
' ===== Script Start =======================
' ********************************************
ValdateArguments() ' --- Load command-line arguments into variables
ValidateComputerResource() ' --- Find computer name match in SMS "All Systems" table SMS_R_System
FindCollandAddMembRule() ' --- Find specific collection and add membership rule to the collection
' *************************************************************************************
' *************************************************************************************
' Subroutines
' *************************************************************************************
' *************************************************************************************
' *************************************************************************************
' **** Validate command-line parameters and load them into variables to be used
' **** by the script. Otherwise, display an error message and exit the script
' *************************************************************************************
Sub ValdateArguments() ' --- Load command-line arguments into variables
If wscript.arguments.count<> 2 Then
wscript.echo "Two arguments please - The collection followed by Computer Name"
wscript.quit ' --- quit if invalid number of arguments
TargetCollectionName = wscript. arguments(0)
NewComputerName = wscript. arguments(1)
End if
End Sub
' **************************************************************************
' **** Search the SMS_R_System table for a match to the computer name passed by the
' **** command-line argument, then store the corresponding SMS ResourceID
' **** in a variable.
' **************************************************************************
Sub ValidateComputerResource() ' --- Find computer name match in SMS "All Systems" table SMS_R_System
' --- Create object with query results from the SMS SQL table SMS_R_System
Set AllComputersSet = gService.ExecQuery("Select * From SMS_R_System WHERE Name LIKE ""%" + NewComputerName + "%""")
' --- Iterate through the SMS_R_System table resultset (loaded into the variable "AllComputersSet")
' and match the name to be added. Then retreive the ResourceID for the corresponding computer record.
For Each AllComputersItem In AllComputersSet
If UCase(AllComputersItem.Name) = UCase(NewComputerName) Then
ResID = AllComputersItem.ResourceID
RuleName = "ResourceID = " & ResID & " " & AllComputersItem.NetBiosName
End If
End Sub
'**** Walk through the the whole list of SMS collections and search for a match to the
'**** desired collection. If the desired collection is sucessfully found, then
'**** add the Membership rule created in the subrioutine CreateSMSDirectRule() to the
'**** existing matched collection.
Sub FindCollandAddMembRule() ' --- Find specific collection and add membership rule to the collection
' --- Create object with query results from the SMS_Collection table
Set oCollectionSet = gService.ExecQuery("Select * From SMS_Collection")
AddMembRuleSuccess = "False" ' --- Initialize flag to indicate Added Collection Membership Rule Failed
' --- Walk through the list of SMS collections and find a match to the collection name passed by the
' command-line argument. If the collection exists, then add the new direct rule that includes
' the new computer name to the collection.
For Each CollListItem In oCollectionSet
If CollListItem.Name = TargetCollectionName Then
'**** Create a direct membership rule (spawn a blank instance) to add to an existing collection.
'**** Then give that instance the values it needs - this is REQUIRED
Set CollectionRule = gService.Get("SMS_CollectionRuleDirect").SpawnInstance_()
CollectionRule.ResourceClassName = "SMS_R_System"
CollectionRule.RuleName = RuleName
CollectionRule.ResourceID = ResID
' ***** Add the direct membership rule to matched collection. ************
CollListItem.AddMembershipRule CollectionRule
If Err.Number = 0 Then ' --- If Error = 0, then adding membership was successful.
AddMembRuleSuccess = "True" ' --- Set flag to "True" to indicate memb. rule added Successfully
End If
End If
End Sub