Script to fix duplicate SMS/SCCM GUID’s

I recently had an interesting issue come about with a bunch of old school legacy machines scattered around several offices that contained identical disk images and SMS/SCCM agent GUID’s. The unintended consequences of this situation are computers improperly referenced in a collection plan. In addition machines were improperly re-imaged and applications inadvertently deployed. Our in-house solution was to create a script to parse a CSV (comma delimited) file including all machine names with duplicate GUID’s and run the following tasks:

Sponsors, article continues below...

1) Make sure machine is pingable
2) Stop SMS/SCCM Agent
3) Delete SMSCFG.ini
4) Start SMS/SCCM Agent to generate new SMSCFG.ini including GUID.
5) Report results to c:\FixSMSGUID_Results.csv

NOTE: Be sure you have sufficient rights on the destination machines before running this script!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
'###########################################################################
'## VB Script: FixSMSGUID.vbs ##############################################
'## Purpose: Delete SMS.ini and restart SMS service. #######################
'## Author: Stephen Leuthold http://www.blogmynog.com #####################################
'## Created: 2008-04-22 ####################################################
'## Last Modified: 2008-09-30 ##############################################
'###########################################################################
'## Changelog
 
On Error Resume Next
 
Const wbemFlagReturnImmediately = &h10
Const wbemFlagForwardOnly = &h20
Const ForReading = 1
Const strOutputFile = "c:\FixSMSGUID_Results.csv"
'****************************************************************************
' Obtain CSV list of file.
'****************************************************************************
 
'Set objArgs = WScript.Arguments
'If objArgs.Count > 0 Then
'	Set str = WScript.Arguments.Item(1)
'	Set intMode = WScript.Arguments.Item(2)
'ElseIf objArgs.Count = 0 Then
 
'Via browse dialog box if cmd line arguments null
 
MsgBox "Select duplicate GUID CSV"
Set objDialog = Createobject("Useraccounts.Commondialog")
objDialog.Filter = "Duplicate GUID CSV|*.csv"
'objDialog.Flags = &H0200
objDialog.Filterindex = 1
objDialog.InitialDir = "C:\"
'objDialog.dialogTitle = "Select a file"
intResult = objDialog.Showopen
If(intResult = 0) Then
	Wscript.Echo "No duplicate GUID CSV file selected! Exiting.."
	Wscript.quit
Else
  strHostList = objDialog.FileName
End If
 
'****************************************************************************
'END CSV file.
'****************************************************************************
 
'****************************************************************************
 
Dim arrDupGUID(1)
Dim i, sleepDur, intSleep, strService, objService, errReturn, strMsg
intSleep = 10000
sleepDur = 0
intSleepRetry = 1000
strService = "ccmexec"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile _
	(strHostList, ForReading)
Wscript.echo "Removing duplicate GUID's...."
Wscript.echo
 
'Create Fix SMS GUID status CSV
If objFSO.FileExists(strOutputFile) Then
	objFSO.DeleteFile(strOutputFile)
End If
Set objOutputFile = objFSO.CreateTextFile(strOutputFile, True)
 
'Loop through each line of file
Do Until objTextFile.AtEndOfStream
	strNextLine = objTextFile.Readline
	i = 0
	For Each strItem In CSVParse(strNextLine)
		arrDupGUID(i) = strItem
		i = i + 1
	Next
 
	strHost = arrDupGUID(0)
	strStatus = arrDupGUID(1)
 
	Wscript.Echo "Hostname: "& strHost
 
	'Wscript.echo "Machines status: "& strStatus
	'If machines GUID has not already been fixed.
	If strStatus = "Done" Then
		Wscript.echo "Host already done, skipping: "& strHost
		strMsg = "Done"
		Wscript.echo
	Else
		If fctIsAlive(strHost) = False Then
			strMsg = "Ping timeout"
			Wscript.echo strMsg
			Wscript.echo
		Else
			If Len(strHost) = 0 Then
				Wscript.echo "Hostname string is null, check your IMPORT file!...Exiting..."
				Wscript.quit
			End If
 
			Set objWMIService = GetObject("winmgmts:" _
				& "{impersonationLevel=impersonate}!\\" & strHost)
			If Err.Number Then
				'Wscript.Echo Err.Number
				Wscript.Echo "Error: "& Err.Description
				'Wscript.Echo "Could not connect to the WMI Service"
				Wscript.Echo
				strMsg = Err.Description
			Else
				Set objService = objWMIService.Get("Win32_Service.Name='" & strService & "'")
 
				'Get Windows Directory
				Set objOS = objWMIService.ExecQuery("Select * from Win32_OperatingSystem")
				For Each colOS In objOS
					strWindowsDir = colOS.WindowsDirectory
				Next
				'Wscript.Echo "Windows Dir: "& strWindowsDir
				Set objIniDel = GetObject("winMgmts:CIM_DataFile.Name='" & strWindowsDir & "\SMSCFG.INI'")
 
				'##########################################################
				'Stop the service, delete SMSCFG.INI and start the service.
				'##########################################################
 
				'Stop SMS Host Agent Service
				Wscript.Echo "Stopping SMS Agent Host service"
				errReturn = objService.StopService()
				If errReturn > 0 Then
					'Wscript.Echo "Error: " & errReturn
					strMsg = errReturn.Description
					Wscript.Echo strMsg
				End If
				Wscript.Echo "Waiting..."
				'Wscript.Echo "State: "& objService.State
				Wscript.Sleep intSleep
				strState = objService.State
 
				'Make sure service is stopped before continuing
				Do Until strState = "Stopped"
					Wscript.Echo "Service still stopping, waiting..."
					Wscript.Sleep intSleepRetry
					Set objState = objWMIService.Get("Win32_Service.Name='" & strService & "'")
					strState = objState.State
					sleepDur = sleepDur + 1
					If sleepDur = 30 Then
						strMsg = "Timeout Could not stop SMS Agent service"
						strState = "Stopped"
					End If
					'Wscript.Echo "State: "& strState
				Loop
 
				'Delete SMSCFG.ini file
				Wscript.Echo "Deleting SMSCFG.ini file"
				errReturn = objIniDel.delete
				If errReturn > 0 Then
					'Wscript.Echo "Error: " & errReturn
					Wscript.Echo "Could not delete SMSCFG.ini file"
					strMsg = "Could not delete SMSCFG.ini file"
				End If
 
				'Start SMS Host Agent Service
				Wscript.Echo "Starting SMS Agent Host service"
				errReturn = objService.StartService()
				If errReturn > 0 Then
					'Wscript.Echo "Error: " & errReturn
					Wscript.Echo "Service could not start"
				End If
 
				'Reset sleep duration
				sleepDur = 0
 
				'Make sure service is started before continuing
				Do Until strState = "Running"
					Wscript.Echo "Service still starting, waiting..."
					Wscript.Sleep intSleepRetry
					Set objState = objWMIService.Get("Win32_Service.Name='" & strService & "'")
					strState = objState.State
					'Wscript.Echo "State: "& strState
					sleepDur = sleepDur + 1
					If sleepDur = 30 Then
						strMsg = "Timeout Could not Start SMS Agent service"
						strState = "Running"
					End If
				Loop
				Wscript.echo "SMS Host Service is Running"
				'Wscript.echo "Done with: "& strHost
				If Len(StrMsg) = 0 Then
					strMsg = "Done"
				End If
 
				Wscript.echo
			End If 'END If cannot connect
		End If ' If cannot ping
	End If 'END If machines GUID has not already been fixed.
	Err.Clear
	objOutputFile.Writeline strHost & ","& strMsg
	StrMsg = ""
Loop 'END - Loop through line of file
'END - Reading CSV
'Close file for Writing
objOutputFile.Close
Wscript.quit
 
Function fctIsAlive(strHostOrIP)
	'Function to make sure machine is pingable.
	'Stolen from http://www.fpschultze.de/uploads/wmiping.vbs.txt
Dim objSh, objCmd, strCmd
	strCmd     = "%ComSpec% /C %SystemRoot%\system32\ping.exe -n 1 " & strHostOrIP & " | " _
			   & "%SystemRoot%\system32\find.exe /c /i " & Chr(34) & "ttl=" & Chr(34)
	Set objSh  = WScript.CreateObject("WScript.Shell")
	Set objCmd = objSh.Exec(strCmd)
	fctIsAlive = CBool(Trim(objCmd.StdOut.ReadAll))
	Set objCmd = Nothing
	Set objSh  = Nothing
End Function
 
Function CSVParse(ByVal strLine)
    ' Function to parse comma delimited line and return array
    ' of field values.
	' Stolen from http://www.rlmueller.net/Programs/ReadCSV.txt
 
    Dim arrFields
    Dim blnIgnore
    Dim intFieldCount
    Dim intCursor
    Dim intStart
    Dim strChar
    Dim strValue
 
    Const QUOTE = """"
    Const QUOTE2 = """"""
 
    ' Check for empty string and return empty array.
    If (Len(Trim(strLine)) = 0) then
        CSVParse = Array()
        Exit Function
    End If
 
    ' Initialize.
    blnIgnore = False
    intFieldCount = 0
    intStart = 1
    arrFields = Array()
 
    ' Add "," to delimit the last field.
    strLine = strLine & ","
 
    ' Walk the string.
    For intCursor = 1 To Len(strLine)
        ' Get a character.
        strChar = Mid(strLine, intCursor, 1)
        Select Case strChar
            Case QUOTE
                ' Toggle the ignore flag.
                blnIgnore = Not blnIgnore
            Case ","
                If Not blnIgnore Then
                    ' Add element to the array.
                    ReDim Preserve arrFields(intFieldCount)
                    ' Makes sure the "field" has a non-zero length.
                    If (intCursor - intStart > 0) Then
                        ' Extract the field value.
                        strValue = Mid(strLine, intStart, _
                            intCursor - intStart)
                        ' If it's a quoted string, use Mid to
                        ' remove outer quotes and replace inner
                        ' doubled quotes with single.
                        If (Left(strValue, 1) = QUOTE) Then
                            arrFields(intFieldCount) = _
                                Replace(Mid(strValue, 2, _
                                Len(strValue) - 2), QUOTE2, QUOTE)
                        Else
                            arrFields(intFieldCount) = strValue
                        End If
                    Else
                        ' An empty field is an empty array element.
                        arrFields(intFieldCount) = Empty
                    End If
                    ' increment for next field.
                    intFieldCount = intFieldCount + 1
                    intStart = intCursor + 1
                End If
        End Select
    Next
    ' Return the array.
    CSVParse = arrFields
End Function

‘————- END COPY ——————‘

Please note that an alternative solution might be found within a Microsoft Technet SMSANDMOM blog entry I recently happened upon.

MY NORMAL DISCLAIMER APPLIES: Although I have used this script with success in my environment, every environment varies. You run this script at your own risk blogmynog.com and associates are in no way responsible for damages incurred running any provided scripts on blogmynog.com or associated websites. Be sure to test this in a non-production environment first before using it in production.

This entry was posted in Microsoft.

5 Responses to Script to fix duplicate SMS/SCCM GUID’s

  1. rob says:

    Get a syntax error on line 12 char 35

  2. Andrew says:

    Thank you!

  3. Mike says:

    If there's anyone on this still can you please tell me where to get a script or SQL query to find duplicated guids on SMS 2.0, I know is old but is what we have in place and it looks like we have tons of duplicates 🙁

    Please let me know and thank you in advance

  4. Tayyab says:

    hi, if anyone still there, can you please help me. when I am running the script, it just gave me a message box saying " select a file" but there is no brows button nothing just a "OK" button. what should I have to do when it shows select the file or is there any changes happened in the original script?.

    Regards,

Leave a Reply to rob Cancel reply