9/9/2011 - The script in this posting has been updated to handle assigning a new machine name during the deployment.
[Today’s post comes from Minfang Lv ]
This post describes how and when you might see duplicate records when you use unknown computer support with Active Directory Delta-Discovery in Configuration Manager 2007 R3, what problems you might see, and some suggested workarounds.
Unknown computer support is an operating system deployment feature that was introduced in Configuration Manager 2007 R2. It allows you to find unmanaged computers so that you can install an operating system on them, and optionally, install the Configuration Manager client:
http://technet.microsoft.com/en-us/library/cc431374.aspx . Active Directory Delta Discovery is a new feature in Configuration Manager 2007 R3 that enhances the discovery capabilities of the product by discovering only new or changed resources in Active Directory Domain Services instead of performing a full discovery cycle: http://technet.microsoft.com/en-us/library/ff977086.aspx .
If you use these two features at the same time, you might see duplicate records for the unknown computer in Configuration Manager database. In this scenario, you will see two records in the Configuration Manager console that have the same name of the computer that installed an operating system by using unknown computer support: One record shows that it is a client and assigned; the other record shows that it is not a client and not assigned.
The Technical Details
When you install an operating system by using unknown computer support, the following processes happen:
If the DDR is created (number 3) after the computer installs (number 4), you won’t see a duplicate record because Configuration Manager has enough information to merge the Active Directory DDR with the computer record. However, if the DDR is created before the computer installs and registers (in the order listed above), Configuration Manager cannot match and merge the two records, which results in the duplicate record.
This problem is a timing issue, which has always existed in the product. However, the introduction of Active Directory Delta Discovery in Configuration Manager 2007 R3 means that you are now more likely to see the duplicate records.
Potential Issues
There are two potential issues as a result of this problem:
Workarounds
Use one of the two workarounds for Configuration Manager 2007 R3:
Use the following steps:
A. In the Configuration Manager console, navigate to System Center Configuration Manager / Site Database / Site Management / < site name > / Site Settings / Status Filter Rules .
B. Right-click Status Filter Rules , click New , and then click New Status Filter Rule .
C. On the General page of the New Status Filter Rule Wizard , specify a name for the new status filter rule and configure the following for the message-matching criteria:
D. On the Actions page of the New Status Filter Rule Wizard , specify the following action:
Sample scripts
Disclaimer: These are sample scripts that use the Configuration Manager 207 SDK. Make sure that you test your scripts in a test environment before you run them on a production network.
CMDWrapper.bat
call cscript c:DeleteDuplicatedRecord.vbs %1 %2 %3
DeleteDuplicatedRecord.vbs
'======Delete duplicate recorde '======Usage DeleteDuplicateRecords <sitecode> <SystemNetBIOSName> <servername> Const ForAppending = 8 Const Interval = 30 'in minutes, only support 30 and 60. Please Const Tolerent = 10 'in minutes, make sure the good record has the name now. 'implement if you want another value Const sFileName = "c:DeleteDuplicatedRecordsLog.log" '======Create/Append Log Files Dim oFilesys, oFiletxt, sPath Set oFilesys = CreateObject("Scripting.FileSystemObject") if (oFilesys.FileExists(sFileName)) Then Set oFiletxt = oFileSys.OpenTextFile(sFileName, ForAppending, True) else Set oFiletxt = oFilesys.CreateTextFile(sFileName, False) End if oFiletxt.WriteLine("DeleteDuplicatedRecordsLog") oFiletxt.WriteLine("============" &Now()) '======Check Parameters if (WScript.arguments.count <> 3) then oFiletxt.WriteLine("Usage DeleteDuplicatedRecords <sitecode> <SystemNetBIOSName> <servername>") WScript.Quit else oFiletxt.WriteLine("SiteCode = " & WSCript.arguments(0)) oFiletxt.WriteLine("Machine name = " & WSCript.arguments(1)) oFiletxt.WriteLine("ServerName = " & WSCript.arguments(2)) end if SiteCode=WSCript.arguments(0) MachineName=WSCript.arguments(1) ServerName=WSCript.arguments(2) '======Connect to SMS Provider Set lLocator = CreateObject("WbemScripting.SWbemLocator") Set gService = lLocator.ConnectServer(".","rootsmssite_" + SiteCode) Set swbemContext = CreateObject("WbemScripting.SWbemNamedValueSet") swbemContext.Add "SessionHandle", gService.ExecMethod("SMS_SiteControlFile", "GetSessionHandle").SessionHandle '=============================================================================================================================================== '======If you give the computer a new machine name, you need to query for the new machine name oFiletxt.WriteLine("Wait for 5 minutes for the client to register successfully") WScript.Sleep 1000*60*5 oFiletxt.WriteLine("wake up: " &Now()) oFiletxt.WriteLine("Check to see if the machine name has been changed") statusMessageQuery = "select RecordID from SMS_StatMsg where MessageID = 11171 and MachineName = '" & MachineName & "' order by RecordID desc" Set statusMessages = gService.ExecQuery(statusMessageQuery) if (statusMessages.Count < 1) then oFiletxt.WriteLine("No Status Message with ID = 11171 and MachineName = " & MachineName & ", exiting...") WScript.Quit end if For each statusMessage in statusMessages RecordID = statusMessage.RecordID exit for Next oFiletxt.WriteLine("Status Message RecordID = " & RecordID) statusMessageAttributeQuery = "select AttributeValue from SMS_StatMsgAttributes where RecordID = '" & RecordID & "' and AttributeID = 408" Set statusMessagesAttributes = gService.ExecQuery(statusMessageAttributeQuery) if (statusMessagesAttributes.Count < 1) then oFiletxt.WriteLine("No Status Message Attribute with AttributeID = 408 and RecordID = " & RecordID & ", exiting...") WScript.Quit end if For each statusMessagesAttribute in statusMessagesAttributes GUID = statusMessagesAttribute.AttributeValue exit for Next oFiletxt.WriteLine("SMS Client GUID = " & GUID) machineNameQuery = "select NetbiosName from SMS_R_System where SMSUniqueIdentifier = '" & GUID & "'" Set machineNames = gService.ExecQuery(machineNameQuery) if (statusMessagesAttributes.Count < 1) then oFiletxt.WriteLine("No Systems with SMSGUID = " & GUID & ", using the Machine Name in the status message") else For each newMachineName in machineNames MachineName= newMachineName.NetbiosName exit for Next oFiletxt.WriteLine("New MachineName = " & MachineName) end if '================================================================================================================================================= '======Find the system with the specific machine name. duplicateRecordsQuery = "select * from SMS_R_System where NetBIOSName = '" + MachineName + "'" Set duplicatedRecords = gService.ExecQuery(duplicateRecordsQuery) if (duplicatedRecords.Count < 1) then oFiletxt.WriteLine("Didn't find the machine, exiting...") WScript.Quit end if '======Delete if the Client, Client Type, Hardware ID, SMBIOSGUID, SMSUniqueIdentifier is null Deleted = 0 for each item in duplicatedRecords Active = item.Properties_.Item("Active") AgentName= item.Properties_.Item("AgentName") Client = item.Properties_.Item("Client") ClientType = item.Properties_.Item("ClientType") HardwareID = item.Properties_.Item("HardwareID") Name = item.Properties_.Item("Name") NetbiosName = item.Properties_.Item("NetbiosName") ResourceId = item.Properties_.Item("ResourceId") SMBIOSGUID = item.Properties_.Item("SMBIOSGUID") SMSUniqueIdentifier = item.Properties_.Item("SMSUniqueIdentifier") oFiletxt.WriteLine("Active: " & Active) for each AgentNameInstance in AgentName oFiletxt.WriteLine("AgentName: " & AgentNameInstance) Next oFiletxt.WriteLine("Client: " & Client) oFiletxt.WriteLine("ClientType: " & ClientType) oFiletxt.WriteLine("HardwareID: " & HardwareID) oFiletxt.WriteLine("Name: " & Name) oFiletxt.WriteLine("NetbiosName: " & NetbiosName) oFiletxt.WriteLine("RecourceId: " & ResourceId) oFiletxt.WriteLine("SMBIOSGUID: " & SMBIOSGUID) oFiletxt.WriteLine("SMSUniqueIdentifier: " & SMSUniqueIdentifier) if (IsNull(Active) and IsNull(Client) and IsNull(ClientType) and IsNull(HardwareID) and IsNull(SMBIOSGUID) and IsNull(SMSUniqueIdentifier)) then oFiletxt.WriteLine("Delete this one: ResourceId = " & ResourceId) 'Delete Record when there's duplicate and it's active/SMBIOSGUID, etc is null item.Delete_ oFiletxt.WriteLine("Deleted item: ResourceId = " & ResourceId) Deleted = 1 end if Next if (Deleted <> 1) then oFiletxt.WriteLine("Didn't delete anything, exiting...") WScript.Quit end if '======If there's delete operation, trigger a full AD Group/SG discovery in no later than half hour. '======Get the Current Time & Calculate Next full schedule time. CurrentTime = Now CurrentTime = DateAdd("n", Tolerent, CurrentTime) oFiletxt.WriteLine("Defined Interval: " & Interval) oFiletxt.WriteLine("Current Time: "& CurrentTime) MinusSec = 0 - Second(CurrentTime) MinusMin = 0 - Minute(CurrentTime) CurrentTime = DateAdd("s",MinusSec,CurrentTime) if (Interval = 60) then CurrentTime = DateAdd("n",MinusMin,CurrentTime) CurrentTime = DateAdd("h",1,CurrentTime) else if (Interval = 30) then if (Minute(CurrentTime) <= 30) then CurrentTime = DateAdd("n", 30 + MinusMin, CurrentTime) else CurrentTime = DateAdd("n", MinusMin,CurrentTime) CurrentTime = DateAdd("h",1,CurrentTime) end if end if end if NextPlannedTime = CreateWMITime(CurrentTime) oFiletxt.WriteLine("Next Planned Full Sync Time: "& NextPlannedTime) '======Set the Startup Time of the next full discovery Call ScheduleFullSync("SMS_AD_SYSTEM_GROUP_DISCOVERY_AGENT", SiteCode, ServerName, NextPlannedTime) Call ScheduleFullSync("SMS_AD_SECURITY_GROUP_DISCOVERY_AGENT", SiteCode, ServerName, NextPlannedTime) oFiletxt.WriteLine("Successfully Configured, exiting...") wScript.Quit '======End of the script Function ScheduleFullSync(DiscoveryMethodName, SiteCode, ServerName, NextPlannedTime) oFiletxt.WriteLine("Now Configure " & DiscoveryMethodName) Dim DeltaEnabled 'Whether the delta discovery is enabled Dim StartupPropertyName 'Startup Schedule or Full Sync Schedule depends on whether delta discovery is enabled or not. Dim StartUpTime DeltaEnabled = false Query = "SELECT * FROM SMS_SCI_Component " & _ "WHERE ItemName = '" & DiscoveryMethodName & "|" & ucase(serverName) & "' " & _ "AND SiteCode = '" & siteCode & "'" oFiletxt.WriteLine("[Debug]Query = " & Query) 'Get the Discovery Agent properties. Set SCIComponentSet = gService.ExecQuery(Query, ,wbemFlagForwardOnly Or wbemFlagReturnImmediately, swbemContext) 'First Loop to see if delta discovery is enabled For Each SCIComponent In SCIComponentSet ' Loop through the array of embedded SMS_EmbeddedProperty instances. For Each vProperty In SCIComponent.Props ' Setting: Delta Discovery Enabled or not if (vProperty.PropertyName = "Enable Incremental Sync") then oFiletxt.WriteLine ("Delte Discovery value: " & vProperty.value) DeltaEnabled = vProperty.Value end if ' Setting: if full schedule is enabled or not if (vProperty.PropertyName = "SETTINGS") then oFiletxt.WriteLine ("Active: " & vProperty.value1) if (vProperty.value1 = "INACTIVE") then oFiletxt.WriteLine ("Discovery not enabled, exist Function") exit Function end if end if Next Next '======If Delta Discovery is enabled, then PropertyName is "Startup Schedule", else, it's "Full Sync Schedule". if (DeltaEnabled = false) then StartupPropertyName = "Startup Schedule" else StartupPropertyName = "Full Sync Schedule" end if 'Second loop to get the Startup time For Each SCIComponent In SCIComponentSet ' Loop through the array of embedded SMS_EmbeddedProperty instances. For Each vProperty In SCIComponent.Props oFiletxt.WriteLine("check Property Name: " & StartupPropertyName) ' Setting: Startup Schedule If vProperty.PropertyName = StartupPropertyName Then StartUpScheduleToken = vProperty.Value1 oFiletxt.WriteLine("Original StartUpScheduleToken: " & StartUpScheduleToken) Set InParams = gService.Get("SMS_ScheduleMethods").Methods_("ReadFromString").InParameters.SpawnInstance_ InParams.StringData = StartUpScheduleToken set outParams = gService.ExecMethod("SMS_ScheduleMethods","ReadFromString",InParams,,swbemContext) oFiletxt.WriteLine("**DayDuration:" & outParams.TokenData(0).DayDuration) oFiletxt.WriteLine("**HourDuration:" & outParams.TokenData(0).HourDuration) oFiletxt.WriteLine("**MinuteDuration:" & outParams.TokenData(0).MinuteDuration) oFiletxt.WriteLine("**DaySpan:" & outParams.TokenData(0).DaySpan) oFiletxt.WriteLine("**HourSpan:" & outParams.TokenData(0).HourSpan) oFiletxt.WriteLine("**MinuteSpan:" & outParams.TokenData(0).MinuteSpan) oFiletxt.WriteLine("**StartTime:" & outParams.TokenData(0).StartTime) oFiletxt.WriteLine("**IsGMT:" & outParams.TokenData(0).IsGMT) StartUpTime = outParams.TokenData(0).StartTime 'If Startup Time not equal to planned next schedule time, update is. if (StartUpTime <> NextPlannedTime) then oFiletxt.WriteLine("Original Startup time != Planned time, update it") outParams.TokenData(0).StartTime = NextPlannedTime Set clsScheduleMethod = gService.Get("SMS_ScheduleMethods") clsScheduleMethod.WriteToString Array(outParams.TokenData(0)), NextPlannedTimeScheduleToken oFiletxt.WriteLine("NextPlannedTimeScheduleToken:" & NextPlannedTimeScheduleToken) vProperty.value1 = NextPlannedTimeScheduleToken Set SCICompPath = SCIComponent.Put_(wbemChangeFlagUpdateOnly, swbemContext) ' Commit the change to the actual site control file. Set InParams = gService.Get("SMS_SiteControlFile").Methods_("CommitSCF").InParameters.SpawnInstance_ InParams.SiteCode = siteCode gService.ExecMethod "SMS_SiteControlFile", "CommitSCF", InParams, , swbemContext else oFiletxt.WriteLine("Next schedule time is within 30 minutes, will not change") End If End If Next Next End Function Function CreateWMITime(StringTime) Dim iYear,iMonth, iDay, iHour, iMinute, iSecond iYear = Year(StringTime) iMonth = Month(StringTime) iDay = Day(StringTime) iHour = Hour(StringTime) iMinute = Minute(StringTime) iSecond = Second(StringTime) if len(iMonth)<2 then iMonth = "0" & iMonth End if if len(iDay)<2 then iDay = "0" & iDay End if if len(iHour)<2 then iHour = "0" & iHour End if if len(iMinute)<2 then iMinute = "0" & iMinute End if if len(iSecond)<2 then iSecond = "0" & iSecond End if CreateWMITime = iYear & iMonth & iDay & iHour & iMinute & iSecond & ".000000+***" if len(CreateWMITime)<25 or len(CreateWMITime)>25 then CreateWMITime = "" end if End Function-- Minfang Lv
This posting is provided "AS IS" with no warranties and confers no rights.You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.