首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 依電腦名稱解析 IP 位址:Dns 類別與 DirectoryServices 兩種場景實戰

     編輯:關於C語言

澄清:兩種不同的「依名稱取 IP」場景

原始代碼實際演示的是「建立 Windows 本地使用者」,而非解析 IP。本文釐清兩種常見需求並提供正確實作:

  1. DNS 解析:主機名/網域名 → IP 位址(System.Net.Dns)。
  2. AD/本機帳戶管理:在 Active Directory 或本機 SAM 建立/查詢使用者物件(System.DirectoryServices)。

場景一:DNS 解析主機名稱取得 IP(最常用)

同步 API(.NET Framework / .NET Core 通用)


using System.Net;

public static class DnsResolver {
    /// 取得主機名稱對應的所有 IPv4 位址
    public static List GetIpv4Addresses(string hostName) {
        var ips = new List();
        try {
            IPHostEntry entry = Dns.GetHostEntry(hostName);
            foreach (IPAddress ip in entry.AddressList) {
                if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) // IPv4
                    ips.Add(ip.ToString());
            }
        } catch (SocketException ex) {
            // 處理解析失敗:主機不存在、DNS 伺服器無回應等
            Console.WriteLine($"DNS 解析失敗:{ex.Message}");
        }
        return ips;
    }

    /// 取得第一個 IPv4 位址(或 null)
    public static string GetFirstIpv4(string hostName) 
        => GetIpv4Addresses(hostName).FirstOrDefault();
}

非同步 API(高併發/避免阻塞 UI 必用)


public static async Task> GetIpv4AddressesAsync(string hostName) {
    var ips = new List();
    try {
        IPHostEntry entry = await Dns.GetHostEntryAsync(hostName);
        ips.AddRange(entry.AddressList
            .Where(ip => ip.AddressFamily == AddressFamily.InterNetwork)
            .Select(ip => ip.ToString()));
    } catch (SocketException ex) {
        // 記錄錯誤
    }
    return ips;
}

反向解析:IP → 主機名稱


public static string GetHostNameFromIp(string ipAddress) {
    try {
        IPHostEntry entry = Dns.GetHostEntry(ipAddress);
        return entry.HostName; // 完整網域名稱 (FQDN)
    } catch (SocketException) {
        return string.Empty;
    }
}

場景二:DirectoryServices 操作本機/AD 使用者(原代碼修正版)

原代碼意圖在本機建立使用者,但方法名誤導。以下是正確、健壯的實作:

建立本機 Windows 使用者


using System.DirectoryServices;

public class LocalUserManager {
    /// 在本機建立使用者帳號
    /// 空字串=成功,否則回傳錯誤訊息
    public string CreateLocalUser(string userName, string password, string fullName = "") {
        try {
            using (var computer = new DirectoryEntry("WinNT://" + Environment.MachineName + ",computer"))
            using (var users = computer.Children) {
                // 檢查是否已存在
                if (users.Cast().Any(u => u.Name.Equals(userName, StringComparison.OrdinalIgnoreCase)))
                    return $"使用者 [{userName}] 已存在";

                using (var user = users.Add(userName, "user")) {
                    if (!string.IsNullOrEmpty(fullName))
                        user.Properties["FullName"].Value = fullName;
                    
                    user.Invoke("SetPassword", new object[] { password });
                    user.CommitChanges();
                }
            }
            return string.Empty; // 成功
        } catch (Exception ex) {
            return $"建立失敗:{ex.Message}";
        }
    }

    /// 查詢本機使用者是否存在
    public bool UserExists(string userName) {
        using (var computer = new DirectoryEntry("WinNT://" + Environment.MachineName + ",computer")) {
            return computer.Children.Cast()
                .Any(u => u.SchemaClassName == "User" && u.Name.Equals(userName, StringComparison.OrdinalIgnoreCase));
        }
    }
}

查詢 AD 使用者屬性(含 IP 相關屬性?無直接關聯)

AD 使用者物件不儲存 IP 位址。IP 屬於電腦/裝置層級(computer 物件的 ipHostNumber 或 DHCP 租約),非使用者屬性。若需「某使用者登入過哪些 IP」,需查詢 DC 安全性事件日誌 (Event ID 4624) 或 RADIUS/VPN 登入記錄。

進階:解析本機所有網卡 IP(非 DNS)


using System.Net.NetworkInformation;

public static List GetLocalIpv4Addresses() {
    return NetworkInterface.GetAllNetworkInterfaces()
        .Where(nic => nic.OperationalStatus == OperationalStatus.Up 
                   && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback)
        .SelectMany(nic => nic.GetIPProperties().UnicastAddresses)
        .Where(addr => addr.Address.AddressFamily == AddressFamily.InterNetwork)
        .Select(addr => addr.Address.ToString())
        .Distinct()
        .ToList();
}

避坑指南與最佳實踐

陷阱對策
Dns.GetHostEntry 可能回傳 IPv6務必檢查 AddressFamily.InterNetwork 過濾 IPv4
同步 DNS 封鎖執行緒UI/高併發場景必須用 GetHostEntryAsync
主機名稱大小寫DNS 不分大小寫,但最佳實踐統一 ToLower()
DirectoryEntry 路徑格式本機:WinNT://MachineName,computer;AD:LDAP://DC=domain,DC=com
建立使用者需管理員權限應用程式需以 Administrator 執行,或配置 UAC 清單
SetPassword 參數型別Invoke 需傳 object[] { password },非直接字串

總結

  • 解析主機名稱取 IP → Dns.GetHostEntry[Async],簡單、跨平台、標準。
  • 管理本機/AD 使用者 → DirectoryEntry (WinNT:/LDAP:),需 Windows、管理員權限。
  • 兩者無直接關聯:使用者物件不含 IP,電腦物件才有網路位址屬性。

釐清需求、選對 API,即可避免「方法名不符功能」的困擾,編寫正確且可維護的網路與身分管理代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved