Hi,
You can use this function count the number of objects in the domain, it will also display how many of the user objects are active, which might be what is shewing you numbers.
https://nettools.net/object-counts/
Gary.
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
When we try to fetch all the Users or Computers objects present in AD using the below code which binds with AD using ADsOpenObject(), it returns excessive number of objects which are not really part of the AD.
For e.g. We have around 8000 Users and 9000 Computers in AD. But when we try to fetch them, the total object count finally will be 25000 Users and 67000 Computers.
We tried to verify the returned objects, but they are not like randomly generated objects, have some meaningful names and properties. But unfortunately they are not part of our directory.
Please find the server details below that I have attached for reference.
------------------------------------------------------------
Domain Functional Level --> Windows Server 2012 R2
Forest Functional Level --> Windows Server 2012 R2
Number of DCs --> 3
-----------------------------------------------------------
Kindly help us finding out what we're doing wrong here.
void GetMembers(wchar_t* szFilter, IDirectorySearch* pDirSearch, LPWSTR* attributes, DWORD attributeCount, bool allMembers)
{
HRESULT hr;
USES_CONVERSION;
ADS_SEARCH_HANDLE hSearch = NULL;
ADS_SEARCH_COLUMN col;
ADS_SEARCHPREF_INFO SearchPref[2];
SearchPref[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
SearchPref[0].vValue.dwType = ADSTYPE_INTEGER;
SearchPref[0].vValue.Integer = ADS_SCOPE_SUBTREE;
SearchPref[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
SearchPref[1].vValue.dwType = ADSTYPE_INTEGER;
SearchPref[1].vValue.Integer = 1000;
pDirSearch->SetSearchPreference(SearchPref, 2);
hr = pDirSearch->ExecuteSearch(szFilter, attributes, attributeCount, &hSearch);
int ObjectCount = 0;
LPWSTR pszColumn = NULL;
PSID pObjectSID = NULL;
LPWSTR szSID = NULL;
printf("\n\n---------------------------Fetching Object Started--------------------------------\n");
while ((hr = pDirSearch->GetNextRow(hSearch)) != S_ADS_NOMORE_ROWS) {
ObjectCount++;
std::cout << "\n" << ObjectCount << "\n";
int index = 0;
int co = 0;
while (pDirSearch->GetNextColumnName(hSearch, &pszColumn) != S_ADS_NOMORE_COLUMNS)
{
hr = pDirSearch->GetColumn(hSearch, attributes[index], &col);
if (SUCCEEDED(hr)) {
if ((_wcsicmp(col.pszAttrName, L"distinguishedName") == 0)) {
wprintf(L"%-20s %-20s\n", attributes[index], col.pADsValues->CaseIgnoreString);
}
}
else {
printf("Error null value in %ws\n", attributes[index]);
}
index++;
}
}
if (hr != 0x00005012) {
printf("herror in GetMembers of get next row %0x", hr);
}
printf("\n\nTotal ObjectCount : % d\t\n", ObjectCount); // Here we're getting the count as 25000 for users and 67000 for computers objects
printf("\n\n---------------------------Fetching Object completed--------------------------------\n\n\n");
if (hSearch)pDirSearch->CloseSearchHandle(hSearch);
pDirSearch->Release();
CoUninitialize();
}
void GetObjects()
{
LPWSTR pwd = (LPWSTR)L"password";
LPWSTR dcname = (LPWSTR)L"password";
LPWSTR distinguishedName = (LPWSTR)L"DC=domain,DC=com";
LPWSTR username = (LPWSTR)L"username";
LPOLESTR rootStr = new OLECHAR[wcslen(L"LDAP://") + wcslen(dcname) + wcslen(L"/") + wcslen((LPWSTR)distinguishedName) + 1];
wcscpy(rootStr, L"LDAP://");
wcscat(rootStr, dcname);
wcscat(rootStr, L"/");
wcscat(rootStr, (LPWSTR)distinguishedName);
printf("\n\nLDAP DC path = %ws\n\n", rootStr);
HRESULT hr;
USES_CONVERSION;
DWORD attributeCount = 1;
LPWSTR attributes[] = {(LPWSTR)L"distinguishedName"};
IDirectorySearch* pDirSearch = NULL;
LPWSTR szFilter = new WCHAR[MAX_PATH];
wcscpy(szFilter, L"(&(objectCategory=person)(objectClass=user)(!(sAMAccountType=805306370)))");
CoInitialize(NULL);
hr = ADsOpenObject(rootStr,
username,
pwd,
ADS_SECURE_AUTHENTICATION, IID_IDirectorySearch, (void**)&pDirSearch);
if (SUCCEEDED(hr)) {
GetMembers(szFilter, pDirSearch, attributes, attributeCount, false);
}
else {
if (hr == 0x8007200a) {
printf("\nNo View Permission");
}
else {
printf("\n\nAuthentication failure");
}
printf("\n\nObject Bind Failed, error code : %x", hr);
}
}
Hi,
You can use this function count the number of objects in the domain, it will also display how many of the user objects are active, which might be what is shewing you numbers.
https://nettools.net/object-counts/
Gary.
I have to say I haven't seen this problem before, so personally I would do loads of testing to try and understand what is going on and why, below are some of the steps that I would try to identify the cause of the issue.
I would dump the database and do a compare to see if the object exist in both databases
Check the health of the DC with DCdiag /v /c
Check the health of the replication repadmin /showrepl and repadmin /replsummary
Check for Lingering Objects - https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/information-lingering-objects
Check the integrity of the AD database - https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/complete-semantic-database-analysis-ad-db
I would use the Object Replication option of the NetTools to check if the objects exist on both DCs
Ultimately the fix might be to dcpromo the affected DC out of the domain and add it back in again.
Gary.