4

私のアプリは、Active Directory ドメインに参加しているコンピューターで実行されています。WinAPI メソッドを使用してそのドメインの DNS 名を取得する方法はありますか? DNS サーバーやドメイン コントローラーが利用できない場合でも機能するものが必要です。

現在、私が見つけることができる唯一の方法は、Win32_ComputerSystem WMI クラスの Domain プロパティを使用することです。

using System.Management;

public class WMIUtility
{
    public static ManagementScope GetDefaultScope(string computerName)
    {
        ConnectionOptions connectionOptions = new ConnectionOptions();
        connectionOptions.Authentication = AuthenticationLevel.PacketPrivacy;
        connectionOptions.Impersonation = ImpersonationLevel.Impersonate;
        string path = string.Format("\\\\{0}\\root\\cimv2", computerName);
        return new ManagementScope(path, connectionOptions);
    }

    public static ManagementObject GetComputerSystem(string computerName)
    {
        string path = string.Format("Win32_ComputerSystem.Name='{0}'", computerName);
        return new ManagementObject(
            GetDefaultScope(computerName),
            new ManagementPath(path),
            new ObjectGetOptions()
        );
    }

    public static string GetDNSDomainName(string computerName)
    {
        using (ManagementObject computerSystem = GetComputerSystem(computerName))
        {
            object isInDomain = computerSystem.Properties["PartOfDomain"].Value;
            if (isInDomain == null) return null;
            if(!(bool)isInDomain) return null;
            return computerSystem.Properties["Domain"].Value.ToString();
        }
    }
}

WinAPI で見つけることができる唯一のものは、NetBIOS ドメイン名を返す NetGetJoinInformation メソッドです。

using System.Runtime.InteropServices;

public class PInvoke
{
    public const int NERR_SUCCESS = 0;

    public enum NETSETUP_JOIN_STATUS
    {
        NetSetupUnknownStatus = 0,
        NetSetupUnjoined,
        NetSetupWorkgroupName,
        NetSetupDomainName
    }

    [DllImport("netapi32.dll", CharSet = CharSet.Unicode)]
    protected static extern int NetGetJoinInformation(string lpServer, out IntPtr lpNameBuffer, out NETSETUP_JOIN_STATUS BufferType);

    [DllImport("netapi32.dll", SetLastError = true)]
    protected static extern int NetApiBufferFree(IntPtr Buffer);

    public static NETSETUP_JOIN_STATUS GetComputerJoinInfo(string computerName, out string name)
    {
        IntPtr pBuffer;
        NETSETUP_JOIN_STATUS type;
        int lastError = NetGetJoinInformation(computerName, out pBuffer, out type);
        if(lastError != NERR_SUCCESS)
        {
            throw new System.ComponentModel.Win32Exception(lastError);
        }
        try
        {
            if(pBuffer == IntPtr.Zero)
            {
                name = null;
            }
            else
            {
                switch(type)
                {
                    case NETSETUP_JOIN_STATUS.NetSetupUnknownStatus:
                    case NETSETUP_JOIN_STATUS.NetSetupUnjoined:
                    {
                        name = null;
                        break;
                    }
                    default:
                    {
                        name = Marshal.PtrToStringUni(pBuffer);
                        break;
                    }
                }
            }
            return type;
        }
        finally
        {
            if(pBuffer != IntPtr.Zero)
            {
                NetApiBufferFree(pBuffer);
            }
        }
    }
}
4

1 に答える 1

3

あなたが探しているのは、最初のパラメーターとしてのものだと思いGetComputerNameExますComputerNameDnsDomain。しかし、他のタイプのいずれかが必要になる可能性があります。それでも、GetComputerNameEx私が質問をどのように理解しているかから、あなたが探している機能です。

PInvoke の詳細はこちら

あなたはコメントで公正な点を指摘しているので、確かに、この場合LsaQueryInformationPolicyPolicyDnsDomainInformationコンピューターがメンバーであるドメインの DNS 名を取得するためのより良い方法かもしれません。

しかし、それは特別なケースであり、あなたの質問はそのような特別なケースについて言及していません. これは、プライマリ DNS サフィックスが設定されていて、マシンがメンバーである DNS ドメイン名と異なる場合にのみ発生します。すべての実用的な目的のためGetComputerNameExに、あなたが望むことを正確に行います。

于 2012-06-13T19:15:10.530 に答える