Finding computer in Active Directory based on the netbootGuid
A couple weeks ago I got a question from a norwegian fellow. They prestage all computers in Active Directory based on their UUID and he wanted to be able to query AD to get the computer name for their Deployments.
The UUID of a computer can be stored in the Active Directory property netbootGuid. This property is e.g. also used by the RIS Deployment process. During a RIS Deployment it would be able to find an already existing computer object based on this property or create a new computer account with this property (WDS doesn’t use this property anymore). And I actually like the idea of being able to uniquely identify a computer without the need for another database.
So even if not used that often these days I thought it might be worth to enable the webservice to handle GUID values in Active Directory. As this is not as easy as it sounds 😉
What is a UUID?
A UUID (Universally Unique IDentifier) or GUID (Globally Unique IDentifier) is generally a 16-byte number typically written as a sequence of hexadecimal digits like {4C4C4544-0038-5310-804B-C4C04F31344A}. It should, as the name implies, be unique. Sometimes the GUID is derived from some other values like Serial Number or MAC Address which could result in repetition but generally treat it as unique. The UUID of a computer is stored in the BIOS and can be read via WMI (e.g. use “wmic csproduct get uuid” to see the UUID of your computer).
UUID/GUID and the Active Directory
Active Directory is also using GUIDs for unique identification. Each object in Active Directory does have an objectGUID attribute. As said already, computer objects can also have an attribute netbootGuid which can store a UUID. But working with the UUIDs in Active Directory raises two problems:
- UUIDs are stored as an array of bytes To store a UUID in AD you would need to convert each pair of hexadecimal digits into the decimal value e.g. 4C=76 , 4C=76 , 45=69 , 44=68 …. and add each to an array. To get the value you need to do this the other way round and convert each byte into the hexadecimal value and concatenate it.
- UUIDs are stored in a different order than displayed
I skip the part about little-endian and big-endian on Intel based systems (see Wikipedia – Endianness). As the most important thing for you to know is, that the bytes stored in AD are a little bit “mixed up”. It will swap the byte order of the first three parts separated by the dash. Let me show you this on the example from above.4C4C4544-0038-5310-804B-C4C04F31344A
would become
44454C4C-3800-1053-804B-C4C04F31344A
Finding a computer based on the UUID
Taking everything together we heard so far we now can search for a computer using tools like AdFind, dsquery or a custom script using ADSI. The necessary query string to find the computer with a netbootGUID from the example would look like
(&(objectClass=computer)(netbootGuid=44454C4C38001053804BC4C04F31344A))
That’s almost self-explanatory, isn’t it? 😉
If you are using the .Net Framework (e.g. with Powershell) your life get’s a lot easier as with Version 3 of the .Net Framework it has built-in support for this conversion. Each System.GUID object now has a function called “ToByteArray()” which will not only convert each hex-value into a byte, it will also re-order the GUID appropriately.
The easier way
Sure, all this can be scripted (and a lot of people have done this already. You will find a lot of published scripts for this on the internet) but I would prefer to be able to call a webservice during my Deployment and let it return the Computername if it exists already. And I really don’t want to deal with all this stuff described before. So as said already in the last post, the Deployment webservice has been just updated to Version 6 (Find the Download on CodePlex) which now supports a wide variety of properties to work with. And it is now also capable of handling such UUIDs. So all you now need to do is getting the UUID from the BIOS (actually MDT will do this for you during the gather step and store it in the property “UUID”) and then call the webservice function GetComputerNameByNetbootGuid supplying the UUID. The result will be the computername if known or an empty string if not known. To do this, add the following section to your customsettings.ini
1 2 3 4 5 6 7 8 9 10 |
[Settings] Priority=Default, GetComputerNameByNetbootGuid [Default] [GetComputerNameByNetbootGuid] WebService=http://YourWebServer/DeploymentWebservice/AD.asmx/GetComputerNameByNetbootGuid Parameters=UUID UUID=netbootGUID OSDComputerName=string |
In the last article we used a custom script to execute the webservice and set the Computer Description. In this example here we now don’t even need to call a script to parse the result and set the OSDComputername. MDT has some built-in logic which will automatically take the result (if any) and put it into the property “OSDComptuerName”. In our case the result is stored in the xml element “string”. The important line here is
OSDComputerName=string
This way of assigning webservice results directly to Properties will work for most common types. So there are (as always) different ways to achieve the same result, giving you always the flexibility to choose the most appropriate for your requirements.
Compressed Format
As we are speaking about UUIDs a small side note, there is another format of UUIDs you might hit from time to time, especially if dealing with UUIDs stored in the Registry which is the “compressed Format”. It is e.g. used to store the UpgradeCodes of Applications within the registry. This is even more fun as it completely reverses each character within the first three parts of the UUID and reverses each hex pair value within the last two parts. Taking the example
4C4C4544-0038-5310-804B-C4C04F31344A
becomes
4454C4C48300013508B44C0CF41243A4
Scott Hanselman wrote a nice article about this (BATCH FILE VOODOO: Determine if multiple (and which) versions of an MSI-installed Product are installed using UpgradeCode). In the article he also posted a small application from John Walker that can be used in your scripts to handle this conversion. The webservice itself has also a built-in function to do this conversion for you and which you could use in a customized version.
While writing this article (yes, I`m a bit slow sometimes 😉 ) I just saw that Michael Niehaus also wrote a similar article about this (RIS-style naming with MDT 2010: use a web service), so it seems a couple of people get regularly questioned with this topic. In his article he wrote a small webservice function (with source code 😉 ) which not only gives the computername back if the computer exists already, it will auto generate a computername if it does not exist based on some supplied parameters. Actually a quite nice idea and for the targeted problem more powerful then this simpler scenario. So make sure you also have a look on his article.
As said already, I will also publish parts of the source code later and show you how to extend and change functions in there. This way you would be able to insert Michaels function into this more general based webservice.
Find the most current bits of the Deployment Webservice on Codeplex. And as always, if you have any comments, suggestions, feedback whatsoever just drop me a note.
Hi
There seems to be a typo in this article. This line:
WebService=http://YourWebServer/DeploymentWebservice/AD.asmx/GetComputerNameByNetbootGuidParameters=UUID
Should be:
WebService=http://YourWebServer/DeploymentWebservice/AD.asmx/GetComputerNameByNetbootGuid
Parameters=UUID
Regards,
Marko
Hey Marko,
you are absolutely correct and I’ve updated the post accordingly. Thanks for the hint. 😉
Regards
Maik