Service Pack 2 for Configuration Manager 2007 delivers new platform support for Windows 7, Windows Vista SP2, Windows Server 2008 R2 and Windows Server 2008 SP2.
After installing SP2 you will need to create collections for Windows 7, Server 2008 R2 and possibly Windows Vista and Server 2008 if you have not already done so, I used the following script to create 4 new collections:
Click View Source to viewcopy script
The script does not check for existing collections and I have only used it in a test environment so use at your own risk.
' Modified CreateDynamicCollection script from SCCM SDK. ' winDeploy 2009 Set swbemLocator=CreateObject("WbemScripting.SWbemLocator") Set swbemconnection=swbemLocator.ConnectServer(".", "rootsms") Set providerLoc=swbemconnection.InstancesOf("SMS_ProviderLocation") For Each Location In providerLoc If location.ProviderForLocalSite = True Then Set swbemconnection = swbemLocator.ConnectServer(Location.Machine, "rootsmssite_" + Location.SiteCode) Exit For End If Next Call CreateCollection(swbemconnection, "All Windows Vista Systems", "select sms_r_system.ResourceID,sms_r_system.ResourceType,sms_r_system.Name,sms_r_system.SMSUniqueIdentifier,sms_r_system.ResourceDomainORWorkgroup,sms_r_system.Client from sms_r_system where OperatingSystemNameandVersion like '%Workstation 6.0%'") Call CreateCollection(swbemconnection, "All Windows 7 Systems", "select sms_r_system.ResourceID,sms_r_system.ResourceType,sms_r_system.Name,sms_r_system.SMSUniqueIdentifier,sms_r_system.ResourceDomainORWorkgroup,sms_r_system.Client from sms_r_system where OperatingSystemNameandVersion like '%Workstation 6.1%'") Call CreateCollection(swbemconnection, "All Windows Server 2008 Systems", "select sms_r_system.ResourceID,sms_r_system.ResourceType,sms_r_system.Name,sms_r_system.SMSUniqueIdentifier,sms_r_system.ResourceDomainORWorkgroup,sms_r_system.Client from sms_r_system where OperatingSystemNameandVersion like '%Server 6.0%'") Call CreateCollection(swbemconnection, "All Windows Server 2008 R2 Systems", "select sms_r_system.ResourceID,sms_r_system.ResourceType,sms_r_system.Name,sms_r_system.SMSUniqueIdentifier,sms_r_system.ResourceDomainORWorkgroup,sms_r_system.Client from sms_r_system where OperatingSystemNameandVersion like '%Server 6.1%'") Sub CreateCollection(connection, newName, queryForRule) 'Update this collection on a schedule. Set Token = swbemconnection.Get("Sms_St_RecurInterval") Token.DaySpan = 1 'Use Token.HourSpan = 1 or for Token.MinuteSpan = 30 for test environment Token.StartTime = GetStartTime() ' Create the collection. Set newCollection = connection.Get("SMS_Collection").SpawnInstance_ newCollection.Name = newName newCollection.Comment = newName + "." newCollection.OwnedByThisSite = true newCollection.RefreshSchedule = Array(Token) newCollection.RefreshType = 2 ' Save the new collection and save the collection path for later. Set collectionPath = newCollection.Put_ ' IMPORTANT: If you do not specify the relationship, the new collection will not be visible in the console. Set newSubCollectToSubCollect = connection.Get("SMS_CollectToSubCollect").SpawnInstance_ newSubCollectToSubCollect.parentCollectionID = "COLLROOT" ' Define to what collection the new collection is subordinate. newSubCollectToSubCollect.subCollectionID = CStr(collectionPath.Keys("CollectionID")) newSubCollectToSubCollect.Put_ ' Save the subcollection information. ' Create a new collection rule object for validation. Set queryRule = connection.Get("SMS_CollectionRuleQuery") validQuery = queryRule.ValidateQuery(queryForRule) ' Validate the query (good practice before adding it to the collection). ' Continue with processing, if the query is valid. If validQuery Then ' Create the query rule. Set newQueryRule = QueryRule.SpawnInstance_ newQueryRule.QueryExpression = queryForRule newQueryRule.RuleName = newName + "." ' Add the new query rule to a variable. Set newCollectionRule = newQueryRule ' Get the collection. Set newCollection = connection.Get(collectionPath.RelPath) newCollection.AddMembershipRule newCollectionRule ' Add the rules to the collection. newCollection.RequestRefresh False ' Call RequestRefresh to initiate the collection evaluator. Else MsgBox("Invalid Query: " + queryForRule) End If End Sub Function GetStartTime() Set objSWbemServices = GetObject("winmgmts:{impersonationLevel=impersonate}!\.rootcimv2") Set colTimeZone = objSWbemServices.ExecQuery ("SELECT * FROM Win32_TimeZone") For Each objTimeZone in colTimeZone strBias = objTimeZone.Bias Next dtmCurrentDate = Date GetStartTime = Year(dtmCurrentDate) dtmMonth = Month(dtmCurrentDate) If Len(dtmMonth) = 1 Then dtmMonth = "0" & dtmMonth End If GetStartTime = GetStartTime & dtmMonth dtmDay = Day(dtmCurrentDate) If Len(dtmDay) = 1 Then dtmDay = "0" & dtmDay End If If Len(Hour(Now())) = 1 Then Hours = "0" & Hour(Now()) Else Hours = Hour(Now()) End If If Len(Minute(Now())) = 1 Then Minutes = "0" & Minute(Now()) Else Minutes = Minute(Now()) End If GetStartTime = GetStartTime & dtmDay & Hours & Minutes & "00.00000" GetStartTime = GetStartTime & Cstr(strBias) GetStartTime = GetStartTime & "+***" End Function
14 Comments
ChrisC · June 18, 2010 at 8:05 pm
Great work here! I have looked everyone for something like this. However, I tried to execute it and I am getting a “Type Mismatch” on line 21 “Set Token = swbemconnection.Get(“Sms_St_RecurInterval”)
Tone · June 19, 2010 at 9:29 am
Hi Chris, Are you running the script on the sccm server or remotely?
Think the problem is due to you not making a valid connection to SCCM.
The original scripts and more info can be found here:
http://msdn.microsoft.com/en-us/library/cc145272.aspx
http://msdn.microsoft.com/en-us/library/aa393720(VS.85).aspx
http://msdn.microsoft.com/en-us/library/cc143744.aspx
bitdoctor · March 17, 2011 at 1:11 pm
I have to agree with ChrisC – I copied the code exactly and I ran it on my SCCM server; and I also get the “type mismatch.
Mine says “Line 23, Character 2, Type Mismatch, Code: 80041005, Source: SWbemObjectEx”
So, there is definitely/clearly something wrong with your posted code. It would be kind of you to take the code and run it (modify the collection on your test server to “TestColl” and comment out the Vista, Win7 & Win Server collections; and you will see the error. (YES, I KNOW: THE THREAD/RESPONSES ARE OVER A YEAR OLD 🙂
Eventually, I will figure it out, and I also am referencing some of the links you mentioned; as well as other expert links regarding programmatically creating collections. It’s just extremely frustrating to have wonderful code like this that does not work, due to possibly one single line and/or some object/connection not being properly made/created.
The error is, as ChrisC mentioned, right around the swbemconnetion.Get command:
Sub CreateCollection(connection, newName, queryForRule)
‘Update this collection on a schedule.
Set Token = swbemconnection.Get(“Sms_St_RecurInterval”)
Token.DaySpan = 1 ‘Use Token.HourSpan = 1 or for Token.MinuteSpan = 30 for test environment
Token.StartTime = GetStartTime()
‘ Create the collection.
Seems to be the “Set Token” line – I tried changing Sms_St to SMS_ST, as that is the ‘official’ beginning designation of that class, but the problem seems to be a bit deeper than that.
So, the error seems to point back to the “Set swbemconnection command at the very beginning:
Set swbemLocator=CreateObject(“WbemScripting.SWbemLocator”)
Set swbemconnection=swbemLocator.ConnectServer(“.”, “rootsms”)
Set providerLoc=swbemconnection.InstancesOf(“SMS_ProviderLocation”)
Any hints or clues would be greatly appreciated; either way, I am still researching.
Cheers!
Jeff Mason
MDHA System Administrator
Nashville, TN, US
bitdoctor · March 17, 2011 at 1:24 pm
Ok, your “For Each Location In providerLoc” loop is not based on an iterative query, so I think I found it; I think you forgot your “SELECT * From SMS_ProviderLocation,” as in this similar example:
Set objLoc = CreateObject(“WbemScripting.SWbemLocator”)
Set objSMS= objLoc.ConnectServer(strSMSServer, “rootsms”)
Set Results = objSMS.ExecQuery _
(“SELECT * From SMS_ProviderLocation WHERE ProviderForLocalSite = true”)
For each Loc in Results
If Loc.ProviderForLocalSite = True Then
Set objSMS = objLoc.ConnectServer(Loc.Machine, “rootsmssite_” & _
Loc.SiteCode)
strSMSSiteCode = Loc.Sitecode
end if
Next
Tone · March 17, 2011 at 1:32 pm
Hi Bitdoctor,
I just copied and pasted from the blog onto a dev site server and the script ran fine and created the collections.
Glad you got it sorted though and posted a fix for others.
bitdoctor · March 17, 2011 at 1:36 pm
Ok, maybe not exactly. You did use “InstancesOf” – so, I am not exactly sure, but that may allow the ‘For Next’ loop to proceed properly.
BUT, I did find a spelling/syntax error: You had “location” vs. “Location” – and those are two completely separate strings, as far as I know; here is the place where one discrepancy resides:
For Each Location In providerLoc
If location.ProviderForLocalSite = True Then
Set swbemconnection = swbemLocator.ConnectServer(Location.Machine, “rootsmssite_” + Location.SiteCode)
Exit For
End If
Next
So, you have the “For Each Location” (upper-case “L”), but then you have “If location” (lower-case “l”).
Okay, I am still researching and still unable to get this to run. Either way, Thanks again for posting it!
bitdoctor · March 17, 2011 at 1:38 pm
Very curious how it gives 2 of the readers here (myself and ChrisC) a “Type mismatch” and yet it works for you?
I am on Windows Server 2003, SP2.
I am guessing you are on Server 2008.
Does that make a difference?
bitdoctor · March 17, 2011 at 1:43 pm
And I am on SCCM 2007 R2.
bitdoctor · March 17, 2011 at 2:33 pm
A couple thinks I found.
Actually on a Russian Systemcenter site:
http://systemscenter.ru/sccm_sdk.en/html/966d74a2-ccf5-4a43-9298-4ee7d9de66bd.htm
Turns out you must call such module/snippets using a ‘wrapper’ file from the SDK?
Also note: RUN the SDK wrapper VIA “CSCRIPT” ! Else the Wscript.StdOut.Write and Wscript.StdIn.ReadLine commands do not work!
I wrongly assumed you (we) could just save your code as “create-collection.vbs” and run it standalone; but, apparently, that is not the case?
Here is the note from the top of that Russian link:
“The following code samples show how to set up the calling code for the code examples that are used throughout the System Center Configuration Manager 2007 Software Development Kit (SDK).
Replace the SNIPPETMETHOD snippet with the snippet that you want to run. In most cases you will need to make changes, such as adding parameters, to make the code work.”
Does that sound correct? Are indeed using the SDK wrapper VBScript that is mentioned?
bitdoctor · March 17, 2011 at 2:34 pm
In above comment, I meant to ask: “Are [you] indeed using the wrapper that is mentioned?”
bitdoctor · March 17, 2011 at 2:53 pm
Okay, here is the troubleshooting
It never progresses past the “SMS_ST_RecurInterval” command:
Sub CreateCollection(connection, newName, queryForRule)
Wscript.Echo “Made it INTO the ‘CreateCollection’ subroutine!”
[I see the above echo just fine]
‘Update this collection on a schedule.
–> Set Token = swbemconnection.Get(“Sms_St_RecurInterval”)
[I never see ANY of the subsequent echo commands, so the “Set Token/RecurInterval,” as suspected, seems to be the issue, at least for me; and apparently for ChrisC]
wscript.Echo “past swbemconnection.Get cmd”
Token.DaySpan = 1 ‘Use Token.HourSpan = 1 or for Token.MinuteSpan = 30 for test environment
wscript.echo “attempting to call function GetStartTime…”
Token.StartTime = GetStartTime()
Wscript.Echo “Made it PAST Token setup”
bitdoctor · March 17, 2011 at 2:54 pm
And yes, I placed the “–>” in the above for emphasis only. It does not exist in the script. Again, tried with SMS_ST (upper-case) as well.
Clues? Hints? Help?
bitdoctor · March 17, 2011 at 3:02 pm
Okay, I commented out the section “Update collection on a schedule”
Now, it bombs at the “newCollection.Put_” command:
Wscript.Echo “Made it PAST Token setup”
‘ Create the collection.
Set newCollection = connection.Get(“SMS_Collection”).SpawnInstance_
newCollection.Name = newName
newCollection.Comment = newName + “.”
newCollection.OwnedByThisSite = true
newCollection.RefreshSchedule = Array(Token)
newCollection.RefreshType = 2
Wscript.Echo “Made it past CREATE COLLECTION”
[NOTE: I see the above ECHO, but no echos after that!]
‘ Save the new collection and save the collection path for later.
Set collectionPath = newCollection.Put_
[THEREFORE, it is crashing on the above “Put_” statement]
Wscript.Echo “Entering the SAVE NEW COLLECTION area…”
arboc66 · November 26, 2011 at 6:56 am
This worked for me (two problems with original script, typo in the CreateCollection function and wrong date format for the starttime argument of the token):
' Modified CreateDynamicCollection script from SCCM SDK.
' winDeploy 2009
Set swbemLocator=CreateObject("WbemScripting.SWbemLocator")
swbemLocator.Security_.AuthenticationLevel = 6 'Packet Privacy
Set swbemconnection=swbemLocator.ConnectServer(".", "rootsms")
Set providerLoc=swbemconnection.InstancesOf("SMS_ProviderLocation")
For Each Location In providerLoc
If location.ProviderForLocalSite = True Then
WScript.Echo Location.Machine
WScript.Echo Location.SiteCode
WScript.Echo "Connecting..."
Set swbemconnection = swbemLocator.ConnectServer(Location.Machine, "rootsmssite_" & Location.SiteCode)
If Err.Number0 Then
Wscript.Echo "Couldn't connect: " & Err.Description
WScript.Quit
End If
Exit For
End If
Next
Call CreateCollection(swbemconnection, "All Windows Vista Systems", "select sms_r_system.ResourceID,sms_r_system.ResourceType,sms_r_system.Name,sms_r_system.SMSUniqueIdentifier,sms_r_system.ResourceDomainORWorkgroup,sms_r_system.Client from sms_r_system where OperatingSystemNameandVersion like '%Workstation 6.0%'")
Call CreateCollection(swbemconnection, "All Windows 7 Systems", "select sms_r_system.ResourceID,sms_r_system.ResourceType,sms_r_system.Name,sms_r_system.SMSUniqueIdentifier,sms_r_system.ResourceDomainORWorkgroup,sms_r_system.Client from sms_r_system where OperatingSystemNameandVersion like '%Workstation 6.1%'")
Call CreateCollection(swbemconnection, "All Windows Server 2008 Systems", "select sms_r_system.ResourceID,sms_r_system.ResourceType,sms_r_system.Name,sms_r_system.SMSUniqueIdentifier,sms_r_system.ResourceDomainORWorkgroup,sms_r_system.Client from sms_r_system where OperatingSystemNameandVersion like '%Server 6.0%'")
Call CreateCollection(swbemconnection, "All Windows Server 2008 R2 Systems", "select sms_r_system.ResourceID,sms_r_system.ResourceType,sms_r_system.Name,sms_r_system.SMSUniqueIdentifier,sms_r_system.ResourceDomainORWorkgroup,sms_r_system.Client from sms_r_system where OperatingSystemNameandVersion like '%Server 6.1%'")
Sub CreateCollection(connection, newName, queryForRule)
'Update this collection on a schedule.
Set Token = connection.Get("Sms_St_RecurInterval")
Token.DaySpan = 1 'Use Token.HourSpan = 1 or for Token.MinuteSpan = 30 for test environment
Token.StartTime = GetStartTime()
' Create the collection.
Set newCollection = connection.Get("SMS_Collection").SpawnInstance_
newCollection.Name = newName
newCollection.Comment = newName + "."
newCollection.OwnedByThisSite = true
newCollection.RefreshSchedule = Array(Token)
newCollection.RefreshType = 2
' Save the new collection and save the collection path for later.
Set collectionPath = newCollection.Put_
' IMPORTANT: If you do not specify the relationship, the new collection will not be visible in the console.
Set newSubCollectToSubCollect = connection.Get("SMS_CollectToSubCollect").SpawnInstance_
newSubCollectToSubCollect.parentCollectionID = "COLLROOT" ' Define to what collection the new collection is subordinate.
newSubCollectToSubCollect.subCollectionID = CStr(collectionPath.Keys("CollectionID"))
newSubCollectToSubCollect.Put_ ' Save the subcollection information.
' Create a new collection rule object for validation.
Set queryRule = connection.Get("SMS_CollectionRuleQuery")
validQuery = queryRule.ValidateQuery(queryForRule) ' Validate the query (good practice before adding it to the collection).
' Continue with processing, if the query is valid.
If validQuery Then
' Create the query rule.
Set newQueryRule = QueryRule.SpawnInstance_
newQueryRule.QueryExpression = queryForRule
newQueryRule.RuleName = newName + "."
' Add the new query rule to a variable.
Set newCollectionRule = newQueryRule
' Get the collection.
Set newCollection = connection.Get(collectionPath.RelPath)
newCollection.AddMembershipRule newCollectionRule ' Add the rules to the collection.
newCollection.RequestRefresh False ' Call RequestRefresh to initiate the collection evaluator.
Else
MsgBox("Invalid Query: " + queryForRule)
End If
End Sub
Function GetStartTime()
Set objSWbemServices = GetObject("winmgmts:{impersonationLevel=impersonate}!.rootcimv2")
Set colTimeZone = objSWbemServices.ExecQuery ("SELECT * FROM Win32_TimeZone")
For Each objTimeZone in colTimeZone
strBias = objTimeZone.Bias
Next
dtmCurrentDate = Date
GetStartTime = Year(dtmCurrentDate)
dtmMonth = Month(dtmCurrentDate)
If Len(dtmMonth) = 1 Then
dtmMonth = "0" & dtmMonth
End If
GetStartTime = GetStartTime & dtmMonth
dtmDay = Day(dtmCurrentDate)
If Len(dtmDay) = 1 Then
dtmDay = "0" & dtmDay
End If
If Len(Hour(Now())) = 1 Then
Hours = "0" & Hour(Now())
Else
Hours = Hour(Now())
End If
If Len(Minute(Now())) = 1 Then
Minutes = "0" & Minute(Now())
Else
Minutes = Minute(Now())
End If
GetStartTime = GetStartTime & dtmDay & Hours & Minutes & "00.000000"
GetStartTime = GetStartTime & Cstr(strBias)
'GetStartTime = GetStartTime & "+***"
End Function
Good luck!