Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

InStr not finding stuff that I can see is in there... 1

Status
Not open for further replies.

Jerz

MIS
Sep 10, 2004
102
US
The overall goal of this script is to hit all the servers, and if the description field does not contain the S/N, then it will put it there. BUT if it sees it is already there anywhere, it is to skip on to the next server. For starters I'm just gathering info & echoing to test the logic. Then I'll modify the AD records after I'm certain what the results will be.
Code:
'****************************************************************
'*             Update Description with S/N                      *
'*               Written by David J. 3/24/9                     *
'****************************************************************
'****************************************************************
'*                      Create output log file                  *
'****************************************************************
Set objFSO4 = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO4.CreateTextFile(".\reports\UpdateSNreport.csv", True)
On error resume next
'****************************************************************
'*      loop through all computers in AD                        *
'****************************************************************
Set objRootDSE = GetObject("LDAP://RootDSE") 
strDNSDomain = objRootDSE.Get("defaultNamingContext") 
Set objCommand = CreateObject("ADODB.Command") 
Set objConnection = CreateObject("ADODB.Connection") 
objConnection.Provider = "ADsDSOObject" 
objConnection.Open "Active Directory Provider" 
objCommand.ActiveConnection = objConnection
strDNSDomain = objRootDSE.Get("DefaultNamingContext") 
strBase = "<LDAP://" & strDNSDomain & ">" 
strFilter = "(&(objectCategory=computer)(objectClass=computer))" 
strAttributes = "name,distinguishedName"
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree" 
objCommand.CommandText = strQuery 
objCommand.Properties("Page Size") = 100 
objCommand.Properties("Timeout") = 30 
objCommand.Properties("Cache Results") = False 
Set RecordSet0 = objCommand.Execute 
Do Until RecordSet0.EOF
  strComputer = RecordSet0.Fields("name")
  dn = RecordSet0.Fields("distinguishedName")
  Set objComputer = GetObject("LDAP://" & dn )
'****************************************************************
'*    Check AD to see if it's a server                          *
'****************************************************************
  strOSName = objComputer.Get("OperatingSystem")
  If instr(strOSName,"Server") <> 0 or instr(strOSName,"NT") <> 0 then
'****************************************************************
'*             Get  info                         *
'****************************************************************
    desc = objComputer.description
    Err.Clear
    Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
    If err.number = 0 then
	    Set colSMBIOS = objWMIService.ExecQuery("Select * from Win32_SystemEnclosure") 
	    For Each objSMBIOS in colSMBIOS 
	      strNumber = objSMBIOS.SerialNumber
	    Next
FirstDigit = instr(desc, strNumber) 
	    If instr(desc, strNumber) = 0 then
wscript.echo strcomputer & vbcrlf & dn & vbcrlf & desc & vbcrlf & strNumber & vbcrlf & FirstDigit
	    Else
wscript.echo "Skipping this one" & strcomputer & vbcrlf & dn & vbcrlf & desc & vbcrlf & strnumber & vbcrlf & FirstDigit
	    End If
    Else
      objTextFile.Writeline "Could not connect to ," & strComputer
    End if
  End if
  strNumber = ""
  Set colSMBIOS = nothing
  RecordSet0.MoveNext
Loop
objFSO4.Close
wscript.echo "Done"

Sample results:

NMS2
CN=NMS2,OU=Servers,OU=Corp,DC=thadmin,DC=com
Hp,ProLiant DL380 G3,7250LDN10151,1/30/2004 17:01
7250LDN10151
0
XX-CORP-FPS01
CN=XX-CORP-FPS01,OU=Servers,OU=Corp,DC=thadmin,DC=com
Hp,ProLiant DL380 G3,D247LDN1D154,1/30/2004 18:01
D247LDN1D154
0

How in the world does InStr NOT see 'D247LDN1D154' in 'Hp,ProLiant DL380 G3,D247LDN1D154,1/30/2004 18:01'?



 
2 Items I see...

1) WMI may return strNumber with blank spaces at the end as padding. You will have to strip this off. You can test by putting quotes around the string in your WScript.Echo statements...
Code:
...& """" & strNumber & """" &...

2) Try making your InStr method case insensitive...
Code:
FirstDigit = InStr(1, desc, strNumber, VbTextCompare)

PSC

Governments and corporations need people like you and me. We are samurai. The keyboard cowboys. And all those other people out there who have no idea what's going on are the cattle. Mooo! --Mr. The Plague, from the movie "Hackers
 
Answer #1 hit the nail on the head.

Threw in a
Code:
strNumber = RTrim(strNumber)
and the problem I cound't see vanished into thin air like a bunch of spaces.....

Now that the logic is working, it's time to do the work.

Thanks again.
 
I liked the concept of your code so I spent a few minutes with it. I think a few pointers are in order:

1) Declare all your variables. Use Option Explicit. This will help you later when trouble shooting.

2) Don't put On Error Resume Next at the top of your script. Put it only where the script is likely to crash. Testing and experience will show you where these are. Always return the script to normal mode after you've trapped the error by using On Error Goto 0. Each On Error statement will automatically do an Err.Clear.

3) For more efficient code, A) Use With...End With statements. These cause the script interpreter to only check the Object's status once, instead of on every object call. B) Make as few calls to external data sources as possible. In this script you are potentially making 100s of calls to AD where the minimum could be only 2. Because you are using ADO to query AD, you should get all the properties you need to make a decision in one shot, instead of making a separate call later to check OS version or description fields. You can filter for only servers, and have the recordset include the description.

In terms of my last comment, see this FAQ on writing LDAP filters: faq774-5667

To that end, here is my take on your code:

Code:
Option Explicit

Dim objFSO, objTextFile, objRootDSE, strDNSDomain, objCommand
Dim objConnection, strBase, strFilter, strAttributes, strQuery
Dim objRecordSet, strComputer, strDN, strDesc, objComputer
Dim colSMBIOS, objSMBIOS

[green]' Create Log file[/green]
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.CreateTextFile(".\reports\UpdateSNreport.csv", True)

[green]' Bind to AD.  Efficient because future binds will use same connection[/green]
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")

[green]' Create ADO Connection to AD[/green]
Set objConnection = CreateObject("ADODB.Connection")
With objConnection
	.Provider = "ADsDSOObject"
	.Open "Active Directory Provider"
End With

[green]' Query starts from root of the domain[/green]
strBase = "<LDAP://" & strDNSDomain & ">" 
[green]' Filter restricts results to servers only[/green]
strFilter =	"(&" & _
				"(objectCategory=computer)" & _
				"(objectClass=computer)" & _
				"(operatingSystem=*Server*)" & _
			")" 
[green]' Query returns only listed attributes[/green]
strAttributes = "name,distinguishedName,description"
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree" 

[green]' Create ADO Command and configure[/green]
Set objCommand = CreateObject("ADODB.Command")
With objCommand
	.ActiveConnection = objConnection
	.Properties("Page Size") = 100
	.Properties("Timeout") = 30
	.Properties("Cache Results") = False
	.CommandText = strQuery
End With

[green]' Get ADO record set from AD[/green]
Set objRecordSet = objCommand.Execute 

Do Until objRecordSet.EOF
	[green]' Place attributes in variables[/green]
	strComputer = objRecordSet.Fields("name")
	strDN = objRecordSet.Fields("distinguishedName")
	strDesc = objRecordSet.Fields("description")

	[green]' Attempt to bind to server using WMI.  Will fail if server is offline.[/green]
	On Error Resume Next
	Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
	If Err = 0 Then
		Set colSMBIOS = objWMIService.ExecQuery("Select * from Win32_SystemEnclosure") 

		[green]' Serial number returned as an array with 1 element[/green]
		For Each objSMBIOS In colSMBIOS 
			strNumber = objSMBIOS.SerialNumber
		Next

		On Error GoTo 0

		[green]' Check if Serial number is in AD description[/green]
		If InStr(1, strDesc, Trim(strNumber)) = 0 Then
			[green]' Description is incorrect, bind to computer object and update[/green]
			Set objComputer = GetObject("LDAP://" & strDN)
			[green]' ********* Code to add description *********[/green]
		End If
	Else
		On Error GoTo 0
		objTextFile.Writeline "Could not connect to ," & strComputer
	End If

	[green]' Move forward in ADO record set[/green]
	objRecordSet.MoveNext
Loop

wscript.echo "Done"

PSC

Governments and corporations need people like you and me. We are samurai. The keyboard cowboys. And all those other people out there who have no idea what's going on are the cattle. Mooo! --Mr. The Plague, from the movie "Hackers
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top