/// <summary>
        /// Returns a deduplicated list of all computers in the NetworkNeighborhood
        /// </summary>
        /// <returns>List of computers in the NetworkNeighborhood</returns>
        private async Task <ICollection <IPHostEntry> > GetHostsAsync()
        {
            if (!_browsers.Any())
            {
                ServiceRegistration.Get <ILogger>().Error("NeighborhoodBrowserService: No Browsers enabled in NeighborhoodBrowserServiceSettings.xml");
                return(new List <IPHostEntry>());
            }

            var stopWatch = System.Diagnostics.Stopwatch.StartNew();
            ICollection <IPHostEntry> result = null;
            var tasks = _browsers.Select(browser => browser.GetHostsAsync()).ToList();

            try
            {
                await Task.WhenAll(tasks);

                result = Combine(tasks.Select(task => task.Result).ToList());
                NeighborhoodBrowserHelper.LogResult(result, GetType().Name, stopWatch.ElapsedMilliseconds);
            }
            catch (Exception e)
            {
                ServiceRegistration.Get <ILogger>().Error("NeighborhoodBrowserService: Error collecting neighborhood computers", e);
            }
            return(result);
        }
    /// <summary>
    /// Asynchronously returns a collection of IPHostEntries of all computers found in the NetworkNeighborhood
    /// </summary>
    /// <returns></returns>
    private async Task<ICollection<IPHostEntry>> DoGetHostsAsync()
    {
      var stopWatch = Stopwatch.StartNew();

      // Enumerate all computers in the NetworkNeighborhood for all Domains / Workgroups
      var hosts = new Dictionary<String, Task<IPHostEntry>>();
      try
      {
        using (var root = new DirectoryEntry(PROVIDER_STRING))
        {
          foreach (DirectoryEntry domain in root.Children)
          {
            using (domain)
            {
              foreach (DirectoryEntry computer in domain.Children)
              {
                using (computer)
                {
                  if (computer.SchemaClassName == COMPUTER_OBJECT)
                  {
                    ServiceRegistration.Get<ILogger>().Info("DirectoryEntryNeighborhoodBrowser: Adding '{0}' to hosts list.", computer.Name);
                    hosts[computer.Name] = Dns.GetHostEntryAsync(computer.Name);
                  }
                }
              }
            }
          }
        }
      }
      catch (Exception e)
      {
        ServiceRegistration.Get<ILogger>().Error("DirectoryEntryNeighborhoodBrowser: Error while enumerating computers in the NetworkNeighborhood", e);
      }

      // Wait until an IPHostEntry was found for all computers
      try
      {
        await Task.WhenAll(hosts.Values);
      }
      catch (System.Net.Sockets.SocketException) { }
      catch (Exception e)
      {
        ServiceRegistration.Get<ILogger>().Error("DirectoryEntryNeighborhoodBrowser: Error while getting IPHostEntries", e);
      }

      // Assemble the result
      var result = new HashSet<IPHostEntry>();
      foreach (var kvp in hosts)
      {
        // If the call to GetHostEntryAsync was successful, we return the retrieved IPHostEntry
        // If not, we return a new IPHostEntry object just with its HostName property set.
        var host = kvp.Value.IsFaulted ? new IPHostEntry { HostName = kvp.Key } : kvp.Value.Result;
        NeighborhoodBrowserHelper.ConvertDnsHostNameToNetBiosName(host);
        result.Add(host);
      }
      NeighborhoodBrowserHelper.LogResult(result, GetType().Name, stopWatch.ElapsedMilliseconds);
      return result;
    }
        /// <summary>
        /// Asynchronously returns a collection of IPHostEntries of all computers found in the NetworkNeighborhood
        /// </summary>
        /// <returns></returns>
        private async Task <ICollection <IPHostEntry> > DoGetHostsAsync()
        {
            var stopWatch = System.Diagnostics.Stopwatch.StartNew();
            var networks  = NetworkUtils.GetAllLocalIPv4Networks();

            ServiceRegistration.Get <ILogger>().Debug("NetbiosNameServiceNeighborhoodBrowser: Found {0} local IPv4 network(s) with IP address(es) {1}", networks.Count, String.Join(" / ", networks.Select(i => i.Address + " (" + i.IPv4Mask + ")")));

            networks = RemoveLargeSubnets(networks);
            ServiceRegistration.Get <ILogger>().Debug("NetbiosNameServiceNeighborhoodBrowser: {0} local IPv4 network(s) are used: {1}", networks.Count, String.Join(" / ", networks.Select(i => i.Address + " (" + i.IPv4Mask + ")")));

            var tasks = new Dictionary <IPAddress, Task <NbNsNodeStatusResponse> >();

            using (var client = new NbNsClient())
            {
                foreach (var target in networks.SelectMany(NetworkUtils.GetAllAddressesInSubnet))
                {
                    if (!tasks.ContainsKey(target))
                    {
                        tasks.Add(target, client.SendUnicastNodeStatusRequestAsync(NbNsNodeStatusRequest.WildCardNodeStatusRequest, target));
                    }
                }
                await Task.WhenAll(tasks.Values);

                // Uncomment the following two lines for extensive logging
                // foreach (var kvp in tasks.Where(kvp => kvp.Value.Result != null))
                //   ServiceRegistration.Get<ILogger>().Debug("NetbiosNameServiceNeighborhoodBrowser: Found {0} ({1})\r\n{2}", kvp.Value.Result.WorkstationName, kvp.Key, kvp.Value.Result);
            }

            // If the computer has multiple network interfaces, it is found multiple times - once for each network interface.
            // Every occurence of the computer then has a different IP address (the one of the respective network interface).
            // As result we want this computer only as one IPHostEntry, but IPHostEntry.AddressList should show all IP addresses.
            var result    = new HashSet <IPHostEntry>();
            var responses = tasks.Where(kvp => kvp.Value.Result != null);

            foreach (var kvp in responses)
            {
                var alreadyPresentHost = result.FirstOrDefault(host => host.HostName == kvp.Value.Result.WorkstationName);
                if (alreadyPresentHost == null)
                {
                    result.Add(new IPHostEntry {
                        AddressList = new[] { kvp.Key }, HostName = kvp.Value.Result.WorkstationName
                    });
                }
                else
                {
                    if (!alreadyPresentHost.AddressList.Any(address => address.Equals(kvp.Key)))
                    {
                        alreadyPresentHost.AddressList = alreadyPresentHost.AddressList.Union(new[] { kvp.Key }).ToArray();
                    }
                }
            }
            NeighborhoodBrowserHelper.LogResult(result, GetType().Name, stopWatch.ElapsedMilliseconds);
            return(result);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Asynchronously returns a collection of IPHostEntries of all computers found in the NetworkNeighborhood
        /// </summary>
        /// <returns></returns>
        private async Task <ICollection <IPHostEntry> > DoGetHostsAsync()
        {
            var stopWatch = Stopwatch.StartNew();

            // Enumerate all computers in the NetworkNeighborhood for all Domains / Workgroups
            var hosts = new Dictionary <String, Task <IPHostEntry> >();
            ICollection <String> hostNames;

            // The WNetEnum API requires at least to be impersonated as NetworkService; this is the fallback credential used for
            // the root path of NetworkNeighborhoodResourceProvider if no other credentials have been entered.
            using (ServiceRegistration.Get <IImpersonationService>().CheckImpersonationFor(NetworkNeighborhoodResourceProvider.RootPath))
                hostNames = NetworkResourcesEnumerator.EnumerateResources(ResourceScope.GlobalNet, ResourceType.Disk, ResourceUsage.All, ResourceDisplayType.Server);

            // The hostNames returned by the NetworkResourceEnumerator are in the form \\COMPUTERNAME
            // We have to remove the leading \\ to be able to pass the hostName to GetHostEntryAsync
            foreach (var hostName in hostNames)
            {
                hosts[hostName.Substring(2)] = Dns.GetHostEntryAsync(hostName.Substring(2));
            }

            // Wait until an IPHostEntry was found for all computers
            try
            {
                await Task.WhenAll(hosts.Values);
            }
            catch (Exception e)
            {
                ServiceRegistration.Get <ILogger>().Error("WNetEnumNeighborhoodBrowser: Error while getting IPHostEntries", e.Message);
            }

            // Assemble the result
            var result = new HashSet <IPHostEntry>();

            foreach (var kvp in hosts)
            {
                // If the call to GetHostEntryAsync was successful, we return the retrieved IPHostEntry
                // If not, we return a new IPHostEntry object just with its HostName property set.
                var host = kvp.Value.IsFaulted ? new IPHostEntry {
                    HostName = kvp.Key
                } : kvp.Value.Result;
                NeighborhoodBrowserHelper.ConvertDnsHostNameToNetBiosName(host);
                result.Add(host);
            }
            NeighborhoodBrowserHelper.LogResult(result, GetType().Name, stopWatch.ElapsedMilliseconds);
            return(result);
        }