Mar
During a project it was required to do extensive and recurring cleanups of applications within that specific company. The cleanup was done in Active Directory by checking who wasn’t supposed to be a member of the application groups, but also through SCCM.
For the SCCM cleanup 3 different Collections were used: Uninstall Query, Install Overview and a User Overview. These collections were created by hand and took quite some time, because a lot applications had to be cleaned from time to time (mainly licensed applications).
To easen things we decided to create a VBScript to auto create the uninstall collections, based on an input.csv.
Note #1: Check an example of the input.csv at the bottom of the page.
Note #2: This script also contains a logging / output function which outputs the actions to an output.csv.
create_uninstall_collections.vbs
''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' AUTHOR : http://www.hican.net - @hicannet ' DATE : 06-03-2012 ' COMMENT : This script auto creates (removal) ' Collections based on an input csv file. ' Including Logging. ''''''''''''''''''''''''''''''''''''''''''''''''''''''' Option Explicit Const ForWriting = 2 Const ForReading = 1 Const ForAppending = 8 Dim objWshShell, objFso, objFile, objEnv, objLogFileFSO, objLogFile Dim swbemLocator, swbemconnection, providerLoc, Location Dim sConnect, sCurPath, sInputFile, sOutputFile, sNextLine, sSplit Dim sParent, sAppName, sAll, sC2R, sInstalls, sUsers, sUsrName, sComment Dim sColCheck, Collection, objCollection, newCollection, collectionPath Dim sCollectionID, objContainerNode, Container, ParentFolderID, sResourceID Dim newCollectionRelation, Token, objNewCollection, sColInput, sLimitID Dim newQueryRule, newCollectionRule, sQueryC2R, sQueryInstalls, sQueryUsers Dim sGroupName, sProductID sConnect = "<SERVER_NAME>" sCurPath = left(WScript.ScriptFullName,(Len(WScript.ScriptFullName))-(len(WScript.ScriptName))) sInputFile = sCurPath + Chr(92) + "input.csv" sOutputFile = sCurPath + Chr(92) + "output.csv" Set objWshShell = WScript.CreateObject("WScript.Shell") Set objFso = CreateObject("Scripting.FileSystemObject") Set objFile = objFso.OpenTextFile(sInputFile, ForReading) Set objEnv = objWshShell.Environment("process") 'Try to make a connection with the SCCM server. ConnectToSCCM OpenLogFile() WriteToLog "-------------------------------------------------------------------" & VbCrLf WriteToLog "START LOG (" + FormatDateTime(Now(), vbGeneralDate) Do Until objFile.AtEndOfStream sNextLine = objFile.Readline sSplit = Split(sNextLine, ";") sParent = sSplit(0) sAppName = sSplit(1) sProductID = sSplit(2) sGroupName = sSplit(3) sAll = "All_" + sAppName sC2R = "C2R_" + sAppName sInstalls = "Installs_" + sAppName sUsers = "Users_" + sAppName sQueryC2R = "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 INNER JOIN SMS_R_User ON SMS_R_System.LastLogonUserName = SMS_R_User.UserName WHERE (SMS_R_System.Name NOT IN (SELECT SMS_R_System.Name FROM SMS_R_User INNER JOIN SMS_R_System ON SMS_R_User.Username = SMS_R_System.LastLogonUserName WHERE (SMS_R_User.UserGroupName = 'Hican.net\\" + sGroupName + "'))) AND (SMS_R_System.Name IN (SELECT SMS_R_System.Name FROM SMS_R_System AS SMS_R_System INNER JOIN SMS_G_System_ADD_REMOVE_PROGRAMS ON SMS_R_System.ResourceID = SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID WHERE (SMS_G_System_ADD_REMOVE_PROGRAMS.ProdID = '" + sProductID + "')))" sQueryInstalls = "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 inner join SMS_G_System_ADD_REMOVE_PROGRAMS on SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId where SMS_G_System_ADD_REMOVE_PROGRAMS.ProdID = '" + sProductID + "'" sQueryUsers = "select SMS_R_USER.ResourceID,SMS_R_USER.ResourceType,SMS_R_USER.Name,SMS_R_USER.UniqueUserName,SMS_R_USER.WindowsNTDomain from SMS_R_USER WHERE (SMS_R_USER.USERGROUPNAME = 'Hican.net\\" + sGroupName + "')" sUsrName = objEnv("USERNAME") sComment = "Created via script by " + sUsrName + " on " + Replace(FormatDateTime(Now(), vbShortDate), "/", "-") sColCheck = "" If (Left(sNextLine, 1) = "*") Then WriteToLog "LINE: " & sNextLine & " DISABLED FOR PROCESSING..." Else CreateCollections(sAll) CreateCollections(sC2R) CreateCollections(sInstalls) CreateCollections(sUsers) End If Loop objFile.Close WriteToLog "-------------------------------------------------------------------" & VbCrLf CloseLogFile() Wscript.Echo "Finished creating the Collections!" Wscript.Quit ''''''''''''''''''''''''''''' ' FUNCTIONS ' ''''''''''''''''''''''''''''' Function ConnectToSCCM On Error Resume Next Set swbemLocator = CreateObject("WbemScripting.SWbemLocator") Set swbemconnection = swbemLocator.ConnectServer(sConnect, "root\sms") Set providerLoc = swbemconnection.InstancesOf("SMS_ProviderLocation") For Each Location In providerLoc If location.ProviderForLocalSite = True Then Set swbemconnection = swbemLocator.ConnectServer(Location.Machine, "root\sms\site_" + Location.SiteCode) Exit For End If Next If Err.Number <> 0 Then Wscript.echo "Unable to connect to the SCCM provider. " & _ "Check the connection and / or the settings in the script!" & _ "The script will be stopped now." WScript.Quit End If On Error GoTo 0 End Function Sub OpenLogFile() Set objLogFileFSO = CreateObject("Scripting.FileSystemObject") If objLogFileFSO.FileExists(sOutputFile) Then Set objLogFile = objLogFileFSO.OpenTextFile(sOutputFile, ForAppending) Else Set objLogFile = objLogFileFSO.CreateTextFile(sOutputFile) End If End Sub Sub CloseLogFile() objLogFile.Close Set objLogfileFSO = Nothing End Sub Function WriteToLog(sLogMessage) objLogFile.WriteLine(sLogMessage) End Function Function ConvertToWMIdate(sDate) 'Attempts to convert the date into a WMI date-time! Dim sYear, sMonth, sDay, sHour, sMinute sYear = year(sDate) sMonth = month(sDate) sDay = day(sDate) sHour = hour(sDate) sMinute = minute(sDate) If len(sMonth) = 1 Then sMonth = "0" & sMonth End If If len(sDay) = 1 Then sDay = "0" & sDay End If If len(sHour) = 1 Then sHour = "0" & sHour End If If len(sMinute) = 1 Then sMinute = "0" & sMinute End If ConvertToWMIdate = sYear & sMonth & sDay & sHour & sMinute & "00.000000+***" End Function Function CreateCollections(sColInput) 'Attempts to check if the collection already exists. If it does, 'the script will skip this creation! Set Collection = swbemconnection.ExecQuery ("select * from SMS_Collection where Name='" & sParent & "'") For Each objCollection In Collection sColCheck = "This collection exists with the collection ID of: " & objCollection.CollectionID Next If sColCheck = "" Then WScript.Echo "ParentFolder " + sParent + " is not present in Collections - " & _ "Management Collections - Special Collections - SMS Cleanup " & _ ", please create that folder first. The script will be stopped now." WScript.Quit Else 'Attempts to create the new collections. Set newCollection = swbemconnection.Get("SMS_Collection").SpawnInstance_() newCollection.Name = sColInput newCollection.OwnedByThisSite = True newCollection.Comment = sComment Set collectionPath = newCollection.Put_ 'Attempts to obtain the collection ID of the 'newly created collection! Set Collection = swbemconnection.ExecQuery ("select * from SMS_Collection where Name='" & sColInput & "'") For Each objCollection in Collection sCollectionID = objCollection.CollectionID Next If sCollectionID = "" Then WScript.Echo "Unable to obtain a collection ID for the newly created collection." WScript.Quit Else 'WScript.Echo sCollectionID End If If sColInput = sAll Then Set objContainerNode = swbemconnection.ExecQuery("select * from SMS_Collection where Name='" & sParent & "'") Else Set objContainerNode = swbemconnection.ExecQuery("select * from SMS_Collection where Name='" & sAll & "'") End If 'ParentFolderID = "" For Each Container In objContainerNode If Container.name = sParent Then ParentFolderID = Container.CollectionID Elseif Container.name = sAll Then ParentFolderID = Container.CollectionID Else 'WScript.Echo ParentFolderID End If Next 'Attempts to move the newly created collection into the 'desired parent collection. Set newCollectionRelation = swbemconnection.Get("SMS_CollectToSubCollect").SpawnInstance_() newCollectionRelation.parentCollectionID = ParentFolderID newCollectionRelation.subCollectionID = sCollectionID newCollectionRelation.Put_ 'Attempts to create and add the query rule group 'to the collection! If sColInput = sC2R OR sColInput = sInstalls OR sColInput = sUsers Then Set Collection = swbemconnection.ExecQuery ("select * from SMS_Collection where Name='All Managed Workstations'") For Each objCollection in Collection sLimitID = objCollection.CollectionID Next Set newQueryRule = swbemconnection.Get("SMS_CollectionRuleQuery").SpawnInstance_() If sColInput = sC2R Then newQueryRule.QueryExpression = sQueryC2R newQueryRule.LimitToCollectionID = sLimitID Elseif sColInput = sInstalls Then newQueryRule.QueryExpression = sQueryInstalls newQueryRule.LimitToCollectionID = sLimitID Elseif sColInput = sUsers Then newQueryRule.QueryExpression = sQueryUsers End If newQueryRule.RuleName = sColInput 'Add the new query rule to a variable. Set newCollectionRule = newQueryRule 'Get the collection. Set newCollection = swbemconnection.Get(collectionPath.RelPath) 'Add the rules to the collection. newCollection.AddMembershipRule newCollectionRule newCollection.RequestRefresh False End If 'Attempts to set the membership update schedule on the 'collection (weekly recurrance)! Set Token = swbemconnection.Get("SMS_ST_RecurWeekly") Token.StartTime = ConvertToWMIdate(Now()) Set objNewCollection = swbemconnection.Get ("SMS_Collection.CollectionID='" & sCollectionID & "'") objNewCollection.RefreshSchedule = Array(Token) objNewCollection.RefreshType = 2 objNewCollection.Put_ WriteToLog "CREATED: " & sColInput End If End Function
The input.csv has a format like this:
<PARENT_SCCM_FOLDER>;<APPLICATION_NAME>;<PRODUCT_ID>;<AD_GROUP_NAME>
Example input.csv
'MicrosoftProducts;Microsoft_MapPoint_2007;{C82185E8-C27B-4EF4-2010-2222BC2C2B6D};GG.APP.MICROSOFT_MAPPOINT_2007 'AdobeProducts;Adobe_Reader_X;{C82185E8-C27B-4EF4-2010-2222BC2C2B6D};GG.APP.ADOBE_READER_X