Working with Binary Data (GUIDs) in VBScript
Originally published March 9, 2005
Recently, I've spent a great deal of time learning to deal with GUIDs and other somewhat arbitrary binary data within VBScript. While it isn't easy to figure out how, and the conventional wisdom says “don't do it”, after establishing some basic rules and tools, it's actually pretty easy.
Don't expect that the performance will be superb...here are the fruits of my investigations and labors.
This program does a couple of silly things, just for testing:
1) Get a GUID from a user object (note that this is returned to VBScript as a Byte() array - which VBScript doesn't handle easily, natively).
2) Convert the GUID to a string array so that it can be easily handled in VBScript.
3) Escape the string array so that it can be used in an LDAP query for that GUID.
4) Do an LDAP search
5) Convert the string array GUID back to a byte array and compare them.
That's all, folks!
Option Explicit
Dim Com, Conn, Rs ' for ADO
Dim objUser, s, strQuery, objRootDSE, strNamingContext
Dim newArr, strGUID
Set objRootDSE = GetObject ("LDAP://RootDSE")
strNamingContext = objRootDSE.Get ("defaultNamingContext")
Set objRootDSE = Nothing
Set objUser = Getobject ("LDAP://CN=Michael B. Smith,CN=Users," & strNamingContext)
s = myADsEncodeBinaryData (objUser.msExchMailboxGUID)
strGUID = OctetToHexStr (objUser.msExchMailboxGUID)
wscript.echo "objUser.msExchMailboxGUID Type = " & Typename (objUser.msExchMailboxGUID)
wscript.echo "objUser.msExchMailboxGUID Size = " & LenB (objUser.msExchMailboxGUID)
Call InitializeADSI
strQuery = "<LDAP://" & strNamingContext & ">;" & _
"(msExchMailboxGuid=" & s & ");" & _
"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 = OctetToHexStr (newArr) Then
wscript.echo "Same!"
Else
wscript.echo "Different!"
End If
Set objUser = Nothing
Call FinishLDAPQuery (rs)
Call DoneWithADSI
Function myADsEncodeBinaryData (arrByte)
Dim str, s, i
str = OctetToHexStr (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 OctetToHexStr (arrbytOctet)
' Function to convert OctetString (byte array) to Hex string.
' Code from Richard Mueller, a MS MVP in Scripting and ADSI
Dim k
OctetToHexStr = ""
For k = 1 To Lenb (arrbytOctet)
OctetToHexStr = OctetToHexStr _
& Right("0" & Hex(Ascb(Midb(arrbytOctet, k, 1))), 2)
Next
End Function
Sub ConvertHexStringToByteArray (ByVal strHexString, ByRef pByteArray)
Dim fso, stream, temp, ts, n
' 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
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