60 votes

Comment détecter si une machine est jointe à un domaine ?

Comment puis-je détecter si la machine est jointe à un domaine Active Directory (par opposition au mode Workgroup) ?

93voto

Joe Clancy Points 819

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.

3 votes

J'aime toujours trouver qu'il existe une version gérée de presque tout.

14 votes

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.

3 votes

Il y a un problème avec cet appel car il prend environ 2 minutes sur de nombreuses configurations.

30voto

Rob Points 24505

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
    }

}

1 votes

Cool. Mais n'y a-t-il pas une fuite de mémoire dans votre fonction, les données pDomain retournées par NetGetJoinInformation ?

0 votes

(non pas qu'une fuite ait trop d'importance... car je ne l'appellerai qu'une fois et la mettrai en cache)

1 votes

Ahh - l'exemple de code dont je me suis inspiré sur le site PInvoke appelait NetApiBufferFree - je l'ai ajouté à l'exemple =)

23voto

Eric Herlitz Points 6313

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

5 votes

C'est la meilleure réponse car c'est à la fois une solution gérée et la plus rapide.

2 votes

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.

1 votes

@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/

9voto

Stephan Points 4119
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

0 votes

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.

0 votes

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.

2 votes

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.

3voto

blak3r Points 5096

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.

  1. Permet d'obtenir le domaine auquel l'ordinateur est connecté.
  2. 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.com

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.

Powered by:

X