Comment puis-je détecter si la machine est jointe à un domaine Active Directory (par opposition au mode Workgroup) ?
J'aime toujours trouver qu'il existe une version gérée de presque tout.
Comment puis-je détecter si la machine est jointe à un domaine Active Directory (par opposition au mode Workgroup) ?
Ne faites pas l'idiot avec Pinvoke si vous n'y êtes pas obligé.
Référence System.DirectoryServices, puis appel :
System.DirectoryServices.ActiveDirectory.Domain.GetComputerDomain()
Lance un ActiveDirectoryObjectNotFoundException
si la machine n'est pas reliée à un domaine. L'objet Domain qui est renvoyé contient la propriété Name que vous recherchez.
Note aux autres.. assurez-vous d'utiliser GetComputerDomain() (comme suggéré ci-dessus) et pas GetCurrentDomain() . GetCurrentDomain() se bloque pendant des lustres si vous n'êtes pas joint à un domaine.
Il y a un problème avec cet appel car il prend environ 2 minutes sur de nombreuses configurations.
Vous pouvez invoquer les API Win32 telles que NetGetDcName qui renverra une chaîne nulle/vide pour une machine non reliée à un domaine.
Encore mieux, c'est NetGetJoinInformation qui vous indiquera explicitement si une machine est non jointe, dans un groupe de travail ou dans un domaine.
Utilisation de NetGetJoinInformation
J'ai mis en place ceci, qui a fonctionné pour moi :
public class Test
{
public static bool IsInDomain()
{
Win32.NetJoinStatus status = Win32.NetJoinStatus.NetSetupUnknownStatus;
IntPtr pDomain = IntPtr.Zero;
int result = Win32.NetGetJoinInformation(null, out pDomain, out status);
if (pDomain != IntPtr.Zero)
{
Win32.NetApiBufferFree(pDomain);
}
if (result == Win32.ErrorSuccess)
{
return status == Win32.NetJoinStatus.NetSetupDomainName;
}
else
{
throw new Exception("Domain Info Get Failed", new Win32Exception());
}
}
}
internal class Win32
{
public const int ErrorSuccess = 0;
[DllImport("Netapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern int NetGetJoinInformation(string server, out IntPtr domain, out NetJoinStatus status);
[DllImport("Netapi32.dll")]
public static extern int NetApiBufferFree(IntPtr Buffer);
public enum NetJoinStatus
{
NetSetupUnknownStatus = 0,
NetSetupUnjoined,
NetSetupWorkgroupName,
NetSetupDomainName
}
}
Cool. Mais n'y a-t-il pas une fuite de mémoire dans votre fonction, les données pDomain retournées par NetGetJoinInformation ?
(non pas qu'une fuite ait trop d'importance... car je ne l'appellerai qu'une fois et la mettrai en cache)
Ahh - l'exemple de code dont je me suis inspiré sur le site PInvoke appelait NetApiBufferFree - je l'ai ajouté à l'exemple =)
Peut également être appelé en utilisant system.net
string domain = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName
Si la chaîne de domaine est vide, la machine n'est pas liée.
Documentation sur le bien restitué https://docs.microsoft.com/en-us/dotnet/api/system.net.networkinformation.ipglobalproperties.domainname?view=netframework-4.7.2#System_Net_NetworkInformation_IPGlobalProperties_DomainName
Cela renvoie le suffixe DNS primaire de l'ordinateur, ce qui n'est pas nécessairement une indication qu'il est dans AD. Si vous ajoutez un suffixe DNS à un PC qui fait partie d'un groupe de travail, cette option renvoie le nom du suffixe et non une chaîne vide.
@MikeLowery Selon la documentation "Une instance de type String qui contient le nom de domaine de l'ordinateur. Si l'ordinateur n'appartient pas à un domaine, renvoie Empty." docs.microsoft.com/fr/us/dotnet/api/
ManagementObject cs;
using(cs = new ManagementObject("Win32_ComputerSystem.Name='" + System.Environment.MachineName + "'" ))
{
cs.Get();
Console.WriteLine("{0}",cs["domain"].ToString());
}
Cela devrait vous permettre d'obtenir le domaine. Je crois qu'il sera nul ou vide si vous faites partie d'un groupe de travail et non d'un domaine.
Assurez-vous de faire référence à System.Management
Elle renvoie "WORKGROUP" si elle n'est pas dans le domaine. Cela fonctionnera (à moins que vous ne soyez dans un domaine nommé "WORKGROUP" !), mais je vais attendre un peu pour voir s'il existe une approche non basée sur WMI avant de la choisir comme la bonne réponse.
Merci de me le faire savoir. Je n'ai que ma machine de travail pour tester et je ne peux pas vraiment la supprimer du domaine pour tester.
A la réflexion, je ne pense pas que cela va fonctionner. Il s'avère que le nom du groupe de travail de ma boîte de test est en fait WORKGROUP. Je pense qu'il renvoie le nom du groupe de travail, et non une valeur fixe, ce qui, du point de vue de l'API, est plus logique, mais cela signifie que vous ne pouvez pas l'utiliser pour déterminer si le domaine est joint.
Voici mes méthodes avec traitement des exceptions / commentaires que j'ai développées sur la base de plusieurs des réponses de ce post.
Ne renvoie le nom de domaine que si l'utilisateur est effectivement connecté sur un compte de domaine.
/// <summary>
/// Returns the domain of the logged in user.
/// Therefore, if computer is joined to a domain but user is logged in on local account. String.Empty will be returned.
/// Relavant StackOverflow Post: http://stackoverflow.com/questions/926227/how-to-detect-if-machine-is-joined-to-domain-in-c
/// </summary>
/// <seealso cref="GetComputerDomainName"/>
/// <returns>Domain name if user is connected to a domain, String.Empty if not.</returns>
static string GetUserDomainName()
{
string domain = String.Empty;
try
{
domain = Environment.UserDomainName;
string machineName = Environment.MachineName;
if (machineName.Equals(domain,StringComparison.OrdinalIgnoreCase))
{
domain = String.Empty;
}
}
catch
{
// Handle exception if desired, otherwise returns null
}
return domain;
}
/// <summary>
/// Returns the Domain which the computer is joined to. Note: if user is logged in as local account the domain of computer is still returned!
/// </summary>
/// <seealso cref="GetUserDomainName"/>
/// <returns>A string with the domain name if it's joined. String.Empty if it isn't.</returns>
static string GetComputerDomainName()
{
string domain = String.Empty;
try
{
domain = System.DirectoryServices.ActiveDirectory.Domain.GetComputerDomain().Name;
}
catch
{
// Handle exception here if desired.
}
return domain;
}
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.