How get list of local network computers?
Asked Answered
I

6

22

I am trying to get a list of local network computers. I tried to use NetServerEnum and WNetOpenEnum API, but both API return error code 6118 (ERROR_NO_BROWSER_SERVERS_FOUND). Active Directory in the local network is not used.

Most odd Windows Explorer shows all local computers without any problems.

Are there other ways to get a list of computers in the LAN?

Irmine answered 1/4, 2010 at 1:5 Comment(2)
This is the same question basically: https://mcmap.net/q/587941/-get-a-list-of-all-computers-on-a-network-w-o-dnsIsotherm
No. Nmap is not suitable for me. Parse output from other program is not very goodIrmine
I
13

I found solution using interface IShellItem with CSIDL_NETWORK. I get all network PC.

C++: use method IShellFolder::EnumObjects

C#: you can use Gong Solutions Shell Library

using System.Collections;
using System.Collections.Generic;
using GongSolutions.Shell;
using GongSolutions.Shell.Interop;

    public sealed class ShellNetworkComputers : IEnumerable<string>
    {
        public IEnumerator<string> GetEnumerator()
        {
            ShellItem folder = new ShellItem((Environment.SpecialFolder)CSIDL.NETWORK);
            IEnumerator<ShellItem> e = folder.GetEnumerator(SHCONTF.FOLDERS);

            while (e.MoveNext())
            {
                Debug.Print(e.Current.ParsingName);
                yield return e.Current.ParsingName;
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
Irmine answered 1/4, 2010 at 17:28 Comment(6)
The value of CSIDL.NETWORK is 18, right? The same as Environment.SpecialFolder.NetworkShortcuts, right? So I can use straight .Net for this, right?Tlaxcala
@user34660 Yes, if you only use .Net 4.0 or higher (3.5 doesn't support it)Irmine
Is this package available through NuGet?Khania
@Suit Boy Apps: Click the link, download, unzip and add the DLL as Reference.Feretory
Thanks for this. I was pulling my hair out. Still works well in 2021!Timofei
@user34660 looks like Environment.SpecialFolder.NetworkShortcuts is 19, not 18 (at least in .NET 5)Rayner
C
16

You will need to use the System.DirectoryServices namespace and try the following:

DirectoryEntry root = new DirectoryEntry("WinNT:");

foreach (DirectoryEntry computers in root.Children)
{
    foreach (DirectoryEntry computer in computers.Children)
    {
        if (computer.Name != "Schema")
        {
             textBox1.Text += computer.Name + "\r\n";
        }
    }
}

It worked for me.

Cohdwell answered 27/1, 2014 at 9:52 Comment(7)
Hmm it does also list every Domain-User and Domain-GroupDementia
Yeah, need to add computer.SchemaClassName == "Computer" in that if statement. Otherwise, works great!Keratosis
I don't get the list of computers, i get the list of users, any idea?Outlier
Network Discovery must be turned on for this to work.Laurent
does not list non windows computers when i tried itBinary
I don't get anything 🤷Timofei
That gets computer list from AD, but I have a bunch showing up that haven't existed for years, is there one that gets list of currently active computers?Ortrude
I
13

I found solution using interface IShellItem with CSIDL_NETWORK. I get all network PC.

C++: use method IShellFolder::EnumObjects

C#: you can use Gong Solutions Shell Library

using System.Collections;
using System.Collections.Generic;
using GongSolutions.Shell;
using GongSolutions.Shell.Interop;

    public sealed class ShellNetworkComputers : IEnumerable<string>
    {
        public IEnumerator<string> GetEnumerator()
        {
            ShellItem folder = new ShellItem((Environment.SpecialFolder)CSIDL.NETWORK);
            IEnumerator<ShellItem> e = folder.GetEnumerator(SHCONTF.FOLDERS);

            while (e.MoveNext())
            {
                Debug.Print(e.Current.ParsingName);
                yield return e.Current.ParsingName;
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
Irmine answered 1/4, 2010 at 17:28 Comment(6)
The value of CSIDL.NETWORK is 18, right? The same as Environment.SpecialFolder.NetworkShortcuts, right? So I can use straight .Net for this, right?Tlaxcala
@user34660 Yes, if you only use .Net 4.0 or higher (3.5 doesn't support it)Irmine
Is this package available through NuGet?Khania
@Suit Boy Apps: Click the link, download, unzip and add the DLL as Reference.Feretory
Thanks for this. I was pulling my hair out. Still works well in 2021!Timofei
@user34660 looks like Environment.SpecialFolder.NetworkShortcuts is 19, not 18 (at least in .NET 5)Rayner
T
8

I made a function out of it. The SchemaClassName has to be Computer

    public List<string> NetworkComputers()
    {
        return (
        from Computers 
        in (new DirectoryEntry("WinNT:")).Children
        from Computer 
        in Computers.Children
        where Computer.SchemaClassName == "Computer"
        orderby Computer.Name
        select Computer.Name).ToList;
    }
Todd answered 7/2, 2015 at 2:10 Comment(2)
This one works. Essentially its the line where Computer.SchemaClassName == "Computer" which does Filter out every group and user in the network, which still will be listed in @Cohdwell 's anwer, until it's beeing changed.Dementia
I had to add .Cast<DirectoryEntry>() to the Children collection to make it enumerable.Barry
S
3

Here a property that uses a LINQ query

private List<string> NetworkHosts
    {
        get
        {
            var result = new List<string>();

            var root = new DirectoryEntry("WinNT:");
            foreach (DirectoryEntry computers in root.Children)
            {
                result.AddRange(from DirectoryEntry computer in computers.Children where computer.Name != "Schema" select computer.Name);
            }
            return result;
        }
    }
Sanyu answered 25/8, 2016 at 17:51 Comment(0)
R
2

A minor extension to toddmo's answer, if you don't really like LINQ query style syntax and want to also include workgroups as an option:

public IEnumerable<string> VisibleComputers(bool workgroupOnly = false) {
        Func<string, IEnumerable<DirectoryEntry>> immediateChildren = key => new DirectoryEntry("WinNT:" + key)
                .Children
                .Cast<DirectoryEntry>();
        Func<IEnumerable<DirectoryEntry>, IEnumerable<string>> qualifyAndSelect = entries => entries.Where(c => c.SchemaClassName == "Computer")
                .Select(c => c.Name);
        return (
            !workgroupOnly ?
                qualifyAndSelect(immediateChildren(String.Empty)
                    .SelectMany(d => d.Children.Cast<DirectoryEntry>())) 
                :
                qualifyAndSelect(immediateChildren("//WORKGROUP"))
        ).ToArray();
    }
Raphael answered 21/11, 2015 at 17:3 Comment(0)
N
1

Solution with LINQ lambda syntax and unmanaged resource resolver

 public List<String> GetNetworkHostNames()
 {
        using (var directoryEntry = new DirectoryEntry("WinNT:"))
        {
            return directoryEntry
                     .Children
                     .Cast<DirectoryEntry>()
                     .SelectMany(x=>x.Children.Cast<DirectoryEntry>())
                     .Where(c => c.SchemaClassName == "Computer")
                     .Select(c => c.Name)
                     .ToList();
        }
 }
Nasa answered 6/9, 2019 at 7:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.