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

C# 列舉網路鄰居:獲取工作群組、電腦名稱與共享資料夾(DirectoryServices + WMI)

     編輯:關於C語言

場景:掃描區域網路拓撲,構建資產管理或遠端管理工具

需求:列出網路鄰居中的所有工作群組/網域、各群組下的電腦名稱、以及本機或遠端電腦的共享資料夾。.NET 提供兩大技術棧:

  • System.DirectoryServices (ADSI):透過 WinNT 提供者列舉網域/工作群組與電腦物件。
  • System.Management (WMI):查詢 Win32_Share 取得共享資料夾資訊。

核心代碼實作

1. 列舉工作群組/網域與電腦

using System.DirectoryServices;

public class NetworkBrowser {
    public List GetNetworkTopology() {
        var result = new List();

        using (var root = new DirectoryEntry("WinNT:")) { // 根節點:網路鄰居
            foreach (DirectoryEntry domain in root.Children) {
                // domain.Name 為工作群組或網域名稱
                var wg = new WorkgroupInfo { Name = domain.Name, Computers = new List() };

                foreach (DirectoryEntry computer in domain.Children) {
                    // 僅處理電腦物件
                    if (computer.SchemaClassName.Equals("Computer", StringComparison.OrdinalIgnoreCase)) {
                        wg.Computers.Add(computer.Name);
                    }
                }
                result.Add(wg);
            }
        }
        return result;
    }
}

public class WorkgroupInfo {
    public string Name { get; set; }
    public List Computers { get; set; }
}

2. 獲取指定電腦的共享資料夾(WMI)


using System.Management;

public List GetShares(string computerName = ".") {
    var shares = new List();
    // "." 代表本機,遠端電腦需格式 @"\\ServerName\root\cimv2"
    string scope = computerName == "." ? @"root\cimv2" : $@"\\{computerName}\root\cimv2";
    
    // 遠端連線需 ConnectionOptions (帳號/密碼/權限)
    var options = new ConnectionOptions {
        // Username = "admin", Password = "pwd", Authority = "ntlmdomain:DOMAIN"
        Impersonation = ImpersonationLevel.Impersonate,
        Authentication = AuthenticationLevel.PacketPrivacy
    };

    using (var mgmtScope = new ManagementScope(scope, options)) {
        mgmtScope.Connect();
        var query = new ObjectQuery("SELECT Name, Path, Description, Type FROM Win32_Share");
        using (var searcher = new ManagementObjectSearcher(mgmtScope, query)) {
            foreach (ManagementObject share in searcher.Get()) {
                shares.Add(new ShareInfo {
                    Name = share["Name"]?.ToString() ?? "",
                    Path = share["Path"]?.ToString() ?? "",
                    Description = share["Description"]?.ToString() ?? "",
                    Type = ParseShareType(share["Type"])
                });
            }
        }
    }
    return shares;
}

private string ParseShareType(object typeObj) {
    if (typeObj == null) return "Unknown";
    // Win32_Share Type: 0=Disk, 1=Print, 2=Device, 3=IPC, 2147483648=Admin
    return typeObj.ToString() switch {
        "0" => "Disk",
        "1" => "Print",
        "2" => "Device",
        "3" => "IPC",
        "2147483648" => "Admin$",
        _ => "Other"
    };
}

public class ShareInfo {
    public string Name { get; set; }
    public string Path { get; set; }
    public string Description { get; set; }
    public string Type { get; set; }
}

WinForms 整合範例:三層級 TreeView 展示


private void LoadNetworkTree() {
    tvNetwork.Nodes.Clear();
    var browser = new NetworkBrowser();
    var topology = browser.GetNetworkTopology();

    foreach (var wg in topology) {
        var wgNode = tvNetwork.Nodes.Add(wg.Name, wg.Name);
        wgNode.Tag = "Workgroup";

        foreach (var comp in wg.Computers) {
            var compNode = wgNode.Nodes.Add(comp, comp);
            compNode.Tag = "Computer";
            compNode.Nodes.Add("Shares", "共享資料夾 (點擊展開)"); // 虛擬節點,延遲載入
        }
    }
}

private void tvNetwork_BeforeExpand(object sender, TreeViewCancelEventArgs e) {
    if (e.Node.Tag?.ToString() == "Computer" && e.Node.Nodes.Count == 1 && e.Node.Nodes[0].Name == "Shares") {
        e.Node.Nodes.Clear(); // 移除虛擬節點
        string compName = e.Node.Name;
        var shares = new NetworkBrowser().GetShares(compName);
        foreach (var sh in shares) {
            var shareNode = e.Node.Nodes.Add(sh.Name, $"{sh.Name} ({sh.Type}) - {sh.Path}");
            shareNode.Tag = "Share";
            shareNode.ToolTipText = sh.Description;
        }
    }
}

關鍵技術細節與避坑指南

議題說明與對策
WinNT 提供者限制僅能列舉同網段/廣播域內的工作群組與電腦,無法跨路由器列舉 Active Directory 網域物件。跨網域需改用 LDAP 提供者 (LDAP://) 查詢 AD。
WMI 遠端連線權限需目標電腦開啟 WMI 服務、防火牆允許 WMI/RPC、呼叫端具備管理員權限或 DCOM 權限。建議提供 ConnectionOptions 參數化帳密。
效能與延遲網路列舉涉及廣播與 RPC,耗時不可預測。UI 必須放入 BackgroundWorker/Task.Run 非同步執行,避免凍結主執行緒。
重複電腦名稱不同工作群組可能有同名電腦,TreeView 節點 Key 需加前綴 (如 WORKGROUP1\PC01) 避免衝突。
共享類型過濾Win32_Share 包含管理用共享 (Admin$, C$, IPC$),UI 可依 Type 過濾僅顯示 Disk 類型。
.NET Core / 5+ 相容性System.DirectoryServices、System.Management 需安裝對應 NuGet 套件 (System.DirectoryServices, System.Management),且僅支援 Windows 平台。

現代化替代方案

  • 網路掃描:使用 System.Net.NetworkInformation.Ping 掃描 IP 區段,配合 ARP 表解析 MAC/廠商。
  • SMB/共享列舉:SharpCifs、SMBLibrary 等純 managed 實作,無需 WMI/DCOM,跨平台支援較好。
  • Active Directory 管理:System.DirectoryServices.Protocols (LdapConnection) 或 Microsoft.Graph (Azure AD)。

總結

結合 DirectoryServices (WinNT:) 列舉網域/電腦 與 WMI (Win32_Share) 獲取共享,即可構建功能完整的網路鄰居瀏覽器。注意權限、效能、平台相容性三大挑戰,並在 UI 採用非同步延遲載入,打造流暢好用的網路資產管理工具。

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