Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

SMS ODS need netbootGUID in Active Directory for Managed Systems

23 views
Skip to first unread message

Erik

unread,
Apr 3, 2006, 2:31:01 PM4/3/06
to
'*******************************************************************************
'*******************************************************************************
' We recently adopted Microsoft Systems Management Server (SMS) and have been
' interested in adopting the Operating System Deployment (OSD) capabilities
of
' this software. One of the intrinsic requirements of OSD is that the
' "netbootGUID attribute of a computer object in Active Directory is set to
' either the computer's GUID, if available, or a calculated value based on
' the network card address for a computer that has been enabled to use
' Remote Installation Services (RIS). The netbootGUID attribute is set
' during the client computer's prestaging phase. By using Active Directory
' Services Interface (ADSI), the client computer can be programmatically
' prestaged by setting the computer object's netbootGUID attribute in
' Active Directory."
'
' Although Micrsoft provides some code samples, they do not provide functional
' code samples nor ones which can be used together to accomplish the implicit
' goal of actually prestaging each computer in Active Directory. A rather
' time consuming and hopefully comprehensive search of the Internet also
' failed to produce an existing means to this goal.
'
' This Script is intended to accomplish that goal. I've left a few extra
' subroutines in the script for future reference in case I have to travel
' down a simlar road again, but the processing script is fairly simple and
' easy to understand.
'
' The script, as it is currently written must be run in a security context
' such as Domain Administrator which has rights to modify the properties on
' an Active Directory computer object.
'
' Implementation of this script is currently envisioned as part of a common
' logon script domain wide so that hardware modifications to a NIC or
' mainboard do not 'break' the OSD functionality to the specified PC as those
' changes will cause the system UUID to change due to new hardware.
' Alternatively it might be run via SMS at logon, on another schedule.
'
' Erik McCarty (emcc...@parkercc.edu, er...@texastar.com)
' Systems Administrator / Maintenance Programmer
' Information Services Department
' Parker College of Chiropractic
' 2500 Walnut Hill Lane
' Dallas, Texas 75229
' 2006/04/03
'
' Bibliography:
'
' Microsoft Support - How to prestage an RIS client computer by using ADSI
' http://support.microsoft.com/?kbid=302467
'
' Michael B. Smith's Blog
' http://blogs.brnets.com/michael/archive/2005/03/09/387.aspx
'
' Richard Mueller's Printer Script also contributed a bit of insight
' http://www.codecomments.com/message824046.html
'
' McKirahan's PackGuid() subroutine with corrections
' http://www.codecomments.com/archive299-2005-10-658988.html
'*******************************************************************************
'*******************************************************************************


Option Explicit


'*******************************************************************************
' Initialize the variables
Dim Com, Conn, Rs ' for ADO
Dim ADsEncodeBinaryData, strQuery, objRootDSE, strNamingContext
Dim newArr, strGUID
Dim objSysInfo
Dim strComputerDN
Dim objComputer
Dim boolWFMCapable
Dim str_WBEM_UUID
Dim szMac
Dim SystemSet
Dim szAdapterDescription
Dim SystemItem
Dim NetworkAdapterSet
Dim NetworkAdapter
Dim iMacCount
Dim cmdline
Dim oComp
Dim retval
Dim pGUID
Dim cnvt
Dim mymsg


'*******************************************************************************
' Connect to Active Directory and get the Root
Set objRootDSE = GetObject ("LDAP://RootDSE")
strNamingContext = objRootDSE.Get ("defaultNamingContext")
Set objRootDSE = Nothing

'*******************************************************************************
' Connect to Active Directory and get the local computer name
' and get the computer object for processing
Set objSysInfo = CreateObject("ADSystemInfo")
strComputerDN = objSysInfo.ComputerName
Set objComputer = GetObject("LDAP://" & strComputerDN)

'*******************************************************************************
' Connect to WBEM and try to retreive the UUID
Set SystemSet = GetObject("winmgmts:").InstancesOf
("Win32_ComputerSystemProduct")

For Each SystemItem In SystemSet
str_WBEM_UUID = SystemItem.UUID
If str_WBEM_UUID = "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF" Then
mymsg = "No system UUID could be found. This system does " & _
"not appear to support Intel's Wired For Management " & _
"specification. This script will now try and retrive " & _
"a MAC based UUID."
boolWFMCapable = 0
Else
mymsg = "Successfully retrieved a system UUID: " & str_WBEM_UUID & "."
boolWFMCapable = 1
End If
Next
wscript.echo mymsg


'*******************************************************************************
' Get a MAC based UUID if not available from above
If boolWFMCapable = 0 Then
Set NetworkAdapterSet = GetObject("winmgmts:").InstancesOf
("Win32_NetworkAdapter")

iMACCount = 0
For Each NetworkAdapter In NetworkAdapterSet
If NetworkAdapter.AdapterType = "Ethernet 802.3" Then
szAdapterDescription = NetworkAdapter.Description
If NetworkAdapter.Description <> "Packet Scheduler Miniport" Then
szMAC = NetworkAdapter.MACAddress
str_WBEM_UUID = "00000000-0000-0000-0000-"&Replace(szMAC, ":", "")
mymsg = "Based on the network adapter with the description """ & _
szAdapterDescription & """, your system's UUID would " & _
"be " & str_WBEM_UUID & ". "
End If
End If
iMACCount = iMACCount + 1
Next
wscript.echo mymsg
End If
wscript.echo ""


'*******************************************************************************
' Display the guid
mymsg = "str_WBEM_UUID = " & str_WBEM_UUID
wscript.echo mymsg

'*******************************************************************************
' Pack the guid and display it again
str_WBEM_UUID = PackGUID(str_WBEM_UUID)
mymsg = "str_WBEM_UUID = " & str_WBEM_UUID
wscript.echo mymsg

'*******************************************************************************
' Convert the packed GUID to a Byte Array
Call ConvertHexStringToByteArray (str_WBEM_UUID, newArr)

'*******************************************************************************
' and write the Byte Array value into the Active Directory.
objComputer.Put "netbootGUID", newArr
objComputer.SetInfo

'Call Debug

Set objComputer = Nothing


'*******************************************************************************
'*******************************************************************************
' the rest of this is available for debugging purposes if needed
Sub Debug ()
ADsEncodeBinaryData = myADsEncodeBinaryData (objComputer.netbootGUID)
wscript.echo "ADsEncodeBinaryData = " & ADsEncodeBinaryData
strGUID = ConvertOctetToHexStr (objComputer.netbootGUID)
wscript.echo "strGUID = " & strGUID
wscript.echo "objComputer.netbootGUID Type = " & Typename
(objComputer.netbootGUID)
wscript.echo "objComputer.netbootGUID Size = " & LenB
(objComputer.netbootGUID)

Call InitializeADSI

strQuery = "<LDAP://" & strNamingContext & ">;" & _
"(netbootGUID=" & ADsEncodeBinaryData & ");" & _
"name,distinguishedName;" & _
"subtree"

wscript.echo strquery

Call DoLDAPQuery (strQuery, Rs)

wscript.echo "recordcount = " & rs.recordcount

While not rs.eof
wscript.echo "name = " & rs.fields ("name")
wscript.echo "dn = " & rs.fields ("distinguishedname")

rs.MoveNext
Wend

Call ConvertHexStringToByteArray (strGUID, newArr)
wscript.echo "newArr Type = " & Typename (newArr)
wscript.echo "newArr Size = " & LenB (newArr)

If strGUID = ConvertOctetToHexStr (newArr) Then
wscript.echo "Same!"
Else
wscript.echo "Different!"
End If

Call FinishLDAPQuery (rs)

Call DoneWithADSI

End Sub


'*******************************************************************************
'*******************************************************************************
' Converts an array of Bytes to a "\" separated string
Function myADsEncodeBinaryData (arrByte)
Dim str, s, i
WScript.Echo ""

str = ConvertOctetToHexStr (arrByte)
WScript.Echo "Length = " & len(str) & " '" & str & "'"

s = ""
For i = 1 to Len (str) Step 2
s = s & "\" & Mid (str, i, 2)
Next
WScript.Echo s

myADsEncodeBinaryData = s
End Function


'*******************************************************************************
'*******************************************************************************
' Function to convert OctetString (byte array) to Hex string.
' Code from Richard Mueller, a MS MVP in Scripting and ADSI
Function ConvertOctetToHexStr (arrbytOctet)
Dim k

ConvertOctetToHexStr = ""

For k = 1 To Lenb (arrbytOctet)
ConvertOctetToHexStr = ConvertOctetToHexStr _
& Right("0" & Hex(Ascb(Midb(arrbytOctet, k, 1))), 2)
Next
End Function


'*******************************************************************************
'*******************************************************************************
' This is an elegant way to convert a hex string to a Byte
' array. Typename(pByteArray) will return Byte(). pByteArray
' should be a null variant upon entry. strHexString should be
' an ASCII string containing nothing but hex characters, e.g.,
' FD70C1BC2206240B828F7AE31FEB55BE
' Code from Michael Harris, a MS MVP in Scripting
Sub ConvertHexStringToByteArray (ByVal strHexString, ByRef pByteArray)
WScript.echo ""
WScript.echo "ConvertHexStringToByteArray (" & strHexString & ")"
Dim fso, stream, temp, ts, n
Set fso = CreateObject ("scripting.filesystemobject")
Set stream = CreateObject ("adodb.stream")

temp = fso.gettempname ()
Set ts = fso.createtextfile (temp)

For n = 1 To (Len (strHexString) - 1) step 2
ts.write Chr ("&h" & Mid (strHexString, n, 2))
Next

ts.close

stream.type = 1
stream.open
stream.loadfromfile temp

pByteArray = stream.read

stream.close
fso.deletefile temp

Set stream = Nothing
Set fso = Nothing
End Sub

'*******************************************************************************
'*******************************************************************************
Sub InitializeADSI
Set Com = WScript.CreateObject ("ADODB.Command")
Set Conn = WScript.CreateObject ("ADODB.Connection")

' Open the connection.
Conn.Provider = "ADsDSOObject"
Conn.Open "ADs Provider"
End Sub

'*******************************************************************************
'*******************************************************************************
Sub DoneWithADSI
Conn.Close

Set Com = Nothing
Set Conn = Nothing
End Sub

'*******************************************************************************
'*******************************************************************************
Sub DoLDAPQuery (strLDAPQuery, resultSet)
Com.ActiveConnection = Conn
Com.CommandText = strLDAPQuery
Set resultSet = Com.Execute
End Sub

'*******************************************************************************
'*******************************************************************************
Sub FinishLDAPQuery (resultSet)
resultSet.Close
Set resultSet = Nothing
End Sub

'*******************************************************************************
'*******************************************************************************
' To convert a GUID like {E09B48B5-E141-427A-AB0C-D3605127224A} to
' the packed (commonly used in the registry) format like
' 5B84B90E141EA724BAC03D06157222A4
Function PackGUID(guid)
PackGUID = ""

' Remove brackets if they exist
Dim temp
temp = Replace( guid, "{", "")
temp = Replace( temp, "}", "")

' split the guid on the hyphen
Dim part
part = Split(temp,"-")

' build the packed version of the guid
Dim pack
pack = ""
Dim i, j
' reversing the sequence of the first 3 parts from the left
For i = 0 To 2 'UBound(part)
For j = Len(part(i))-1 To 1 Step -2
pack = pack & Mid(part(i),j,2)
Next
Next
For i = 3 To 4
For j = 1 to Len(part(i)) Step 2
pack = pack & Mid(part(i),j,2)
Next
Next

PackGUID = pack
End Function

0 new messages