2010-04-01 7 views
14

J'essaye d'obtenir une liste d'ordinateurs de réseau local. J'ai essayé d'utiliser NetServerEnum et WNetOpenEnum API, mais les deux API retournent le code d'erreur 6118 (ERROR_NO_BROWSER_SERVERS_FOUND). Active Directory dans le réseau local n'est pas utilisé.Comment obtenir la liste des ordinateurs du réseau local?

Le plus étrange Windows Explorer affiche tous les ordinateurs locaux sans aucun problème.

Existe-t-il d'autres moyens d'obtenir une liste d'ordinateurs sur le réseau local?

+0

C'est la même question essentiellement: [http://stackoverflow.com/ questions/105676/get-a-list-of-all-computers-on-a-network-wo-dns] (http://stackoverflow.com/questions/105676/get-a-list-of-all-computers -on-a-network-wo-dns) – Avitus

+4

N ° Nmap ne me convient pas. La sortie d'analyse d'un autre programme n'est pas très bonne. – KindDragon

Répondre

10

J'ai trouvé la solution en utilisant l'interface IShellItem avec CSIDL_NETWORK. Je reçois tout le PC du réseau.

C++: Méthode utilisation IShellFolder :: EnumObjects

C#: vous pouvez utiliser 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(); 
     } 
    } 
+1

La valeur de 'CSIDL.NETWORK' est 18, n'est-ce pas? La même chose que 'Environment.SpecialFolder.NetworkShortcuts', non? Donc je peux utiliser directement. Net pour ça, non? – user34660

+0

@ user34660 Oui, si vous n'utilisez que .Net 4.0 ou supérieur (3.5 ne le supporte pas) – KindDragon

11

Utilisez l'espace de noms System.DirectoryService et essayez le

suivant
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"; 
     } 
    } 
} 

Il a travaillé pour moi .

+4

Hmm ça liste aussi tous les Domain-User et Domain-Group – LuckyLikey

+1

Ouais, besoin d'ajouter 'computer.SchemaClassName ==" Ordinateur "' dans cette déclaration "if". Sinon, ça marche super! – vapcguy

5

J'en ai fait une fonction. Le SchemaClassName doit être 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; 
    } 
+0

Celui-ci fonctionne. Essentiellement, c'est la ligne 'où Computer.SchemaClassName ==" Computer "' qui filtre tous les groupes et utilisateurs du réseau, qui seront toujours listés dans la réponse de @Cynfeal, jusqu'à ce qu'elle change. – LuckyLikey

1

Une extension mineure à la réponse de toddmo, si vous ne faites pas vraiment LINQ syntaxe de style de requête et que vous voulez inclure également les groupes de travail en 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(); 
    } 
1

Voici une propriété qui utilise une requête LINQ

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; 
     } 
    } 
Questions connexes