Every Active Directory object is assigned a unique Globally Unique Identifier (GUID) upon creation. This 128-bit value remains constant even if the object is renamed or moved within the directory structure. The GUID is stored in the objectGUID
attribute and serves as the most reliable way to reference objects programmatically.
Using the ActiveDirectory module:
# Convert GUID string to byte array
$guid = [guid]"a1b2c3d4-e5f6-7890-abcd-ef0123456789"
$byteGuid = $guid.ToByteArray()
# Search using LDAP filter
Get-ADObject -LDAPFilter "(objectGUID=$byteGuid)"
Alternative using DirectorySearcher:
$searcher = [ADSISearcher]"(objectGUID=\\a1\\b2\\c3\\d4\\e5\\f6\\78\\90\\ab\\cd\\ef\\01\\23\\45\\67\\89)"
$searcher.FindOne()
Using System.DirectoryServices:
using System.DirectoryServices;
string guidString = "a1b2c3d4-e5f6-7890-abcd-ef0123456789";
Guid guid = new Guid(guidString);
DirectoryEntry entry = new DirectoryEntry("LDAP://dc=domain,dc=com");
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.Filter = $"(objectGUID={ConvertToLdapGuid(guid)})";
SearchResult result = searcher.FindOne();
private static string ConvertToLdapGuid(Guid guid)
{
byte[] bytes = guid.ToByteArray();
return $"\\{BitConverter.ToString(bytes).Replace("-", "\\")}";
}
When working with GUIDs in LDAP queries:
- The byte order is different from standard GUID string representation
- Escape each byte with backslashes in the LDAP filter
- Consider using attribute-scoped queries for better performance
GUID-based lookups are particularly useful for:
- Service accounts that might be renamed
- Cross-domain object references
- Audit logging where names might change
- Automation scripts requiring stable references
Every object in Active Directory (AD) is assigned a unique Globally Unique Identifier (GUID) upon creation. This 128-bit identifier remains constant even if the object is renamed or moved within the directory. GUIDs are stored in the objectGUID
attribute and are essential for reliable object references in programming scenarios.
While GUIDs are unique identifiers, querying them directly presents technical challenges because:
- GUIDs are stored as binary data in AD
- LDAP requires special formatting for binary data searches
- The byte order of GUIDs differs between AD storage and .NET representation
To search for an object by GUID in Active Directory, you need to convert the GUID to a format that LDAP can understand. The correct format is a hexadecimal string representation with backslash escapes for each byte:
// C# Example using System.DirectoryServices
string guidString = "5b8a7c2e-1d3f-49b1-a13c-8d3d7f8a9b0c";
Guid guid = new Guid(guidString);
byte[] bytes = guid.ToByteArray();
string ldapGuid = "";
foreach (byte b in bytes)
{
ldapGuid += "\\" + b.ToString("x2");
}
string ldapFilter = $"(objectGUID={ldapGuid})";
Here's a full implementation for searching AD by GUID in PowerShell:
# PowerShell function to find AD object by GUID
function Get-ADObjectByGUID {
param(
[Parameter(Mandatory=$true)]
[string]$GUID
)
try {
$guidObj = [guid]$GUID
$searcher = [adsisearcher]""
$searcher.Filter = "(&(objectClass=*)(objectGUID=$(ConvertTo-LDAPGUID $guidObj)))"
$result = $searcher.FindOne()
if ($result) {
return $result.GetDirectoryEntry()
}
else {
Write-Warning "No object found with GUID: $GUID"
}
}
catch {
Write-Error "Error searching for GUID $GUID : $_"
}
}
function ConvertTo-LDAPGUID {
param([guid]$Guid)
$bytes = $Guid.ToByteArray()
$hex = $bytes | ForEach-Object { '\' + $_.ToString('X2') }
return $hex -join ''
}
Using DirectorySearcher in C#
DirectoryEntry entry = new DirectoryEntry("LDAP://dc=domain,dc=com");
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.Filter = $"(objectGUID={ConvertToLdapGuid(new Guid("5b8a7c2e-1d3f-49b1-a13c-8d3d7f8a9b0c"))})";
SearchResult result = searcher.FindOne();
Using Get-ADObject in PowerShell
If you have the ActiveDirectory module available:
Get-ADObject -Filter "objectGUID -eq '$((New-Object GUID '5b8a7c2e-1d3f-49b1-a13c-8d3d7f8a9b0c').Guid)'"
When searching across large directories:
- Always specify the search base to limit the scope
- Consider caching frequently accessed GUIDs
- For batch operations, use paging with
DirectorySearcher.PageSize
- Index the
objectGUID
attribute if performing frequent searches
Common problems and solutions:
Issue | Solution |
---|---|
Invalid format exception | Ensure GUID string is properly formatted (8-4-4-4-12) |
No results found | Verify GUID exists and check for byte order issues |
Performance problems | Limit search scope and add proper indexing |
Access denied | Check authentication and permissions |