In one of my old posts (September 2005) I had some vbscript code to convert an octet string GUID to a friendly GUID string. Well I recently received an email from fellow MVP Michael Smith letting me know he found a bug and a new function that was corrected.
First thought in my mind was… NFW. I am exceedingly careful about things I post, especially code/scripts. But I knew that I had a good function because I used it all over the place and it always aligned with AdFind output…
So I copied from the blog entry and mine and his function into a script and fired in an octet string GUID and sure enough, my function screwed up and his worked…
So I went to one of my scripts that used this function heavily and was used Active Directory Third Edition for decoding Security Descriptors because by darn, if my function was broken that meant that was wrong in the book too which would REALLY SUCK.
I ran the sdlist.vbs script and it worked perfectly fine… So I look again at my function in the test script and I look at the function in sdlist.vbs and they looked the same for all of the logic… wtf…
I copy both functions into separate text files and run windiff against them and get
And think well shoot, so my spacing is off… I see that all the time when doing compares like that… So who cares that isn’t going to hurt the script so I go over the logic in the script line by line and the logic is identical…. <BLINK>IDENTICAL</BLINK>.
I start getting very frustrated because I figure I am not seeing something obvious because of a massive headache I have been fighting off all day…
On the third pass through the script I notice one small thing… the function I posted previously had this line
str = “”
the function in sdlist.vbs had this line
str = ” “
Do you see it??? One bloody space character…. ASCII 32/0x20…. $^%$#^&*(@%$#
What difference does that single space make?
G:\Temp>guidc1
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
Object DN : OU=Users,OU=My,DC=test,DC=loc
String GUID : ba1ee8b7248b34408c34841740211a81
BLOG POST Func: {728BEEA1-B348-0844-C348-41740211A81}
Michael Func : {B7E81EBA-8B24-4034-8C34-841740211A81}
sdlist Func : {B7E81EBA-8B24-4034-8C34-841740211A81}
and here is the actual answer
G:\Temp>adfind -b OU=Users,OU=My,DC=test,DC=loc objectguid -s base
AdFind V01.37.00cpp Joe Richards (joe@joeware.net) June 2007
Using server: TEST-DC1.test.loc:389
Directory: Windows Server 2003
dn:OU=Users,OU=My,DC=test,DC=loc
>objectGUID: {B7E81EBA-8B24-4034-8C34-841740211A81}
1 Objects returned
So here is the updated and correct script, this time copied and pasted straight out of sdlist.vbs which is on page 649 of Active Directory Third Edition.
‘****************************************************************************
‘Convert a binary GUID to a string GUID
‘ Convert GUID octet string to Hex characters then arrange in proper order
‘ and add brackets {}
‘****************************************************************************
Function GuidToStr(Guid)
Dim i, str
str = ” “
For i = 1 To Lenb(Guid)
str = str & Right(“0” & Hex(Ascb(Midb(Guid, i, 1))), 2)
Next
GuidToStr = “{“
For i = 1 to 4
GuidToStr = GuidToStr & Mid(str,10-(i*2),2)
Next
GuidToStr = GuidToStr & “-“
For i = 1 to 2
GuidToStr = GuidToStr & Mid(str,14-(i*2),2)
Next
GuidToStr = GuidToStr & “-“
For i = 1 to 2
GuidToStr = GuidToStr & Mid(str,18-(i*2),2)
Next
GuidToStr = GuidToStr & “-“
For i = 1 to 2
GuidToStr = GuidToStr & Mid(str,16+(i*2),2)
Next
GuidToStr = GuidToStr & “-“
For i = 1 to 6
GuidToStr = GuidToStr & Mid(str,20+(i*2),2)
Next
GuidToStr = GuidToStr & “}”
End Function
For completeness and since he went through the trouble of figuring it out and sending it to me… here is Michael’s version as well. You will note he solved it by changing the start points of the MID function in each line. Both solutions work equally well. I would say I probably prefer his version. Less chance for mistake obviously. 🙂
‘****************************************************************************
‘Convert a binary GUID to a string GUID
‘ Convert GUID octet string to Hex characters then arrange in proper order
‘ and add brackets {}
‘****************************************************************************
Function GuidToStr(Guid)
Dim i, str
str = “”
For i = 1 To Lenb(Guid)
str = str & Right(“0” & Hex(Ascb(Midb(Guid, i, 1))), 2)
Next
GuidToStr = “{“
For i = 1 to 4
GuidToStr = GuidToStr & Mid(str,9-(i*2),2)
Next
GuidToStr = GuidToStr & “-“
For i = 1 to 2
GuidToStr = GuidToStr & Mid(str,13-(i*2),2)
Next
GuidToStr = GuidToStr & “-“
For i = 1 to 2
GuidToStr = GuidToStr & Mid(str,17-(i*2),2)
Next
GuidToStr = GuidToStr & “-“
For i = 1 to 2
GuidToStr = GuidToStr & Mid(str,15+(i*2),2)
Next
GuidToStr = GuidToStr & “-“
For i = 1 to 6
GuidToStr = GuidToStr & Mid(str,19+(i*2),2)
Next
GuidToStr = GuidToStr & “}”
End Function
joe
Much Easier in Powershell 🙂
function ConvertTo-GuidtoString{
Param($bGuid)
$hGuid = $bGuid | %{$_.ToString(‘x2’)}
$guid = “{$($hGuid[3..0])-$($hGuid[5..4])-$($hGuid[7..6])-$($hGuid[8..9])-$($hGuid[10..16])}” -replace “\s”,””
$guid.ToUpper()
}
cpp:
wchar_t* pwszGuid=new wchar_t[39];
StringFromGUID2(*pGuid,pwszGuid,39)
perl (been a bit but this should be it)
Use Win32::LanMan;
my $strGUID = Win32::Lanman::GuidToString($binGuid);
Alternately since perl is all about timtowtdi you could also use Win32::API and call StringFromGUID2 directly.
Oh… if you going to use external API’s
Get-QADUser | select objectGUID
That isn’t the same thing at all. The other examples take a blob and convert to a friendly GUID string. Yours takes the objectGUID for a user and gives that to you in friendly format. That would be like saying use adfind for my cpp example[1].
Next!
joe
[1] Though adfind would be more flexible because I could pull any GUID format attribute off any object and display it that way.
The problem with perl script and the cpp is that only do guid translation. Get-QADUSer does everything [1]
[1] So far every attribute I see that is a Binary GUID gets translated automagically.
This post is entirely about converting a blob GUID to a string GUID… not getting everything…
Well… that is flawed logic. Everything has a point. What point is there in just translating a Binary GUID just to translate one. The implied purpose of the post was in regards to objectguid. Get-QADUser and Get-QADObject both do everything that is needed to provide implied goal.
Anyway… I just wanted to show the Powershell way to do the useless task of converting 🙂
Yes you are using flawed logic as well as trying to apply your assumptions to my writing. The only part on objectGUID was the example to test if the function worked properly. The original post was about schemaIdGUIDs so that has an even stronger opportunity to be the implied purpose and even that isn’t it. It is why the subject was “Converting octetstring GUID values to GUID strings using vbscript” for the first one and not “Outputting objectGUID in a friendly way” or even “Outputting schemaIdGUIDs in a friendly way”.
Anyway, I wasn’t implying any purpose, it was a generic routine for converting something from one format to another. You may be surprised to hear that GUIDs are not just used in Active Directory and those folks who need to do it outside of Active Directory may not consider it so useless. 🙂
I understand what you were showing. Its why I showed the same thing from cpp and perl. VBScript is the most painful of the bunch.
BTW, something I forgot to mention before; StringFromGUID2 isn’t an external API, it is in the OS.
Is there a way to to it in perl without using Win32::* ?
I assume some combination of unpack() could be used. It’d be nice to get these out of AD on non-MS systems.