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 中唯一能找到的是 NetGetJoinInformation 方法,它返回 NetBIOS 域名:

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

我认为您正在寻找的是GetComputerNameExComputerNameDnsDomain一个参数。但是您可能想要其中一种其他类型。不过,GetComputerNameEx从我对问题的理解来看,您正在寻找的功能是什么。

P在此处调用详细信息。

您在评论中提出了一个公平的观点,所以可以肯定的是,在这种情况下LsaQueryInformationPolicyPolicyDnsDomainInformation可能是获取计算机所属域的 DNS 名称的更好方法。

但这是一个特例,你的问题没有提到任何这样的特例。只有当主 DNS 后缀已设置且与机器所属的 DNS 域名不同时,才会出现这种情况。出于所有实际目的,GetComputerNameEx将完全按照您的意愿行事。

于 2012-06-13T19:15:10.530 回答