Come si determina a livello di codice se un computer Windows è membro di un dominio?
Domanda
Ho bisogno di un modo per determinare se il computer che esegue il mio programma è unito a qualsiasi dominio. Non importa di quale dominio specifico faccia parte, solo se è collegato a qualcosa. Sto codificando in vc ++ con l'API Win32.
Soluzione
Direttamente da Microsoft:
Come determinare se un computer Windows NT / Windows 2000 è un membro di dominio
Questo approccio utilizza l'API di Windows. Dal riassunto dell'articolo:
Questo articolo descrive come determinare se un computer che è che esegue Windows NT 4.0 o Windows 2000 è un membro di un dominio, è un membro di un gruppo di lavoro o è autonomo computer che utilizza la sicurezza locale API di autorità.
L'articolo fornisce anche un codice di esempio per un piccolo programma che indica se il computer su cui è in esecuzione il programma fa parte di un dominio, parte di un gruppo di lavoro o un computer autonomo.
Altri suggerimenti
Penso che la funzione NetServerEnum ti aiuterà in quello che vuoi; Chiederei i controller di dominio primari con la costante SV_TYPE_DOMAIN_CTRL
per il parametro servertype . Se non ne ottieni, non sei in un dominio.
È possibile controllare la chiave di registro HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Winlogon per il valore di "CachePrimaryDomain".
Il codice nell'esempio MSDN è un po 'obsoleto. Questa è la funzione che mi è venuta in mente che funziona.
bool ComputerBelongsToDomain()
{
bool ret = false;
LSA_OBJECT_ATTRIBUTES objectAttributes;
LSA_HANDLE policyHandle;
NTSTATUS status;
PPOLICY_PRIMARY_DOMAIN_INFO info;
// Object attributes are reserved, so initialize to zeros.
ZeroMemory(&objectAttributes, sizeof(objectAttributes));
status = LsaOpenPolicy(NULL, &objectAttributes, GENERIC_READ | POLICY_VIEW_LOCAL_INFORMATION, &policyHandle);
if (!status)
{
status = LsaQueryInformationPolicy(policyHandle, PolicyPrimaryDomainInformation, (LPVOID*)&info);
if (!status)
{
if (info->Sid)
ret = true;
LsaFreeMemory(info);
}
LsaClose(policyHandle);
}
return ret;
}
Ecco un semplice approccio morto che non vedo menzionato.
TCHAR UserDnsDomain[128] = { 0 };
DWORD Result = 0;
Result = GetEnvironmentVariable("USERDNSDOMAIN", UserDnsDomain, sizeof(UserDnsDomain));
if (Result == 0 || Result >= sizeof(UserDnsDomain) || GetLastError() == ERROR_ENVVAR_NOT_FOUND)
{
return(FALSE); // Not logged in to a domain
}
Questo si basa sull'idea che se l'utente che esegue questo codice non è attualmente connesso a un dominio, la variabile di ambiente USERDNSDOMAIN sarà vuota o non disponibile. Ma ci sono alcuni avvertimenti a cui dovresti pensare.
Pro:
- Molto facile da implementare.
- affidabile al 99%.
Contro:
- Potrebbe non riuscire o restituire risultati falsi se il computer fa parte del dominio, ma l'utente che esegue questo codice è connesso a quel computer con un account locale.
- Potrebbe non riuscire o restituire risultati falsi se il computer fa parte del dominio, ma la connettività di rete a un controller di dominio non era disponibile al momento dell'accesso / accesso dell'utente con credenziali memorizzate nella cache.
Evita LSA che è un metodo sbagliato. Devi utilizzare DS api (2 righe di codice)
che dire dal nome del computer?
modifica: questa era una "risposta" schifosa dal lontano passato. Ciò che intendevo era scegliere il modulo domain \ name
nel nome del computer. Ciò ovviamente implica che conosci il nome del dominio, non risolve il problema di sapere se il computer si trova in un dominio.