using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Net; using System.Runtime.InteropServices; using Vanara.PInvoke.NetListMgr; namespace Vanara.Network { /// Provides a set of methods to perform network list management functions. public static partial class NetworkListManager { private static NetworkConnectionIterator connIter; private static INetworkCostManager costmgr; private static INetworkListManager manager; private static NetworkIterator netIter; /// An enumerable list that supports a length and indexer. /// The type of the item. /// The type of the parameter used by the indexer. /// public interface IEnumerableList : IEnumerable { /// Gets the length of the list. int Length { get; } /// Gets the with the specified identifier. /// The found item type. /// The identifier. /// The item found by the identifier. T this[TLookup id] { get; } } /// Gets the current connectivity state. /// The connectivity state. public static NLM_CONNECTIVITY Connectivity => Manager?.GetConnectivity() ?? NLM_CONNECTIVITY.NLM_CONNECTIVITY_DISCONNECTED; /// Gets a value indicating whether a network is connected. /// true if a network is connected; otherwise, false. public static bool IsConnected => Manager?.IsConnected ?? false; /// Gets a value indicating whether connectivity to the Internet is available. /// true if connectivity to the Internet is available; otherwise, false. public static bool IsConnectedToInternet => Manager?.IsConnectedToInternet ?? false; /// Gets the network connections for this device. /// The network connections. public static IEnumerableList NetworkConnections => connIter ?? (connIter = new NetworkConnectionIterator()); /// Gets the active networks available. /// The networks. public static IEnumerableList Networks => netIter ?? (netIter = new NetworkIterator()); /// /// Gets the current cost of either a machine-wide internet connection, or the first-hop of routing to a specific destination on a /// connection. If destIPaddr is NULL, this method instead returns the cost of the network used for machine-wide Internet connectivity. /// /// /// The destination IPv4/IPv6 address. If , this method will instead return the cost associated with the /// preferred connection used for machine Internet connectivity. /// /// The cost of the connection. public static NLM_CONNECTION_COST GetConnectionCost(IPAddress destIPAddr = null) { var addr = NLM_SOCKADDR.FromIPAddress(destIPAddr); var cost = NLM_CONNECTION_COST.NLM_CONNECTION_COST_UNKNOWN; (costmgr ?? (costmgr = (INetworkCostManager)Manager))?.GetCost(out cost, addr); return cost; } /// /// Gets the data plan status for either a machine-wide internet connection , or the first-hop of routing to a specific destination /// on a connection. If an IPv4/IPv6 address is not specified, this method returns the data plan status of the connection used for /// machine-wide Internet connectivity. /// /// /// The destination IPv4/IPv6 address. If , this method will instead return the data plan status of the /// connection used for machine-wide Internet connectivity. /// /// /// An NLM_DATAPLAN_STATUS structure that describes the data plan status associated with a connection used to route to a destination. /// If destIPAddr specifies a tunnel address, the first available data plan status in the interface stack is returned. /// public static NLM_DATAPLAN_STATUS GetConnectionDataPlanStatus(IPAddress destIPAddr = null) { var addr = NLM_SOCKADDR.FromIPAddress(destIPAddr); var cost = new NLM_DATAPLAN_STATUS(); (costmgr ?? (costmgr = (INetworkCostManager)Manager))?.GetDataPlanStatus(out cost, addr); return cost; } /// Gets a value indicating whether the data plan status values are default values, or provided by the MNO. /// true if this instance is available; otherwise, false. public static bool IsDefined(this NLM_DATAPLAN_STATUS status) { const uint NLM_UNKNOWN_DATAPLAN_STATUS = 0xFFFFFFFF; // usage data is valid only if both planUsage and lastUpdatedTime are valid if (status.UsageData.UsageInMegabytes != NLM_UNKNOWN_DATAPLAN_STATUS && (status.UsageData.LastSyncTime.dwHighDateTime != 0 || status.UsageData.LastSyncTime.dwLowDateTime != 0)) return true; if (status.DataLimitInMegabytes != NLM_UNKNOWN_DATAPLAN_STATUS) return true; if (status.InboundBandwidthInKbps != NLM_UNKNOWN_DATAPLAN_STATUS) return true; if (status.OutboundBandwidthInKbps != NLM_UNKNOWN_DATAPLAN_STATUS) return true; if (status.NextBillingCycle.dwHighDateTime != 0 || status.NextBillingCycle.dwLowDateTime != 0) return true; if (status.MaxTransferSizeInMegabytes != NLM_UNKNOWN_DATAPLAN_STATUS) return true; return false; } internal static INetworkListManager Manager { get { if (manager != null) return manager; try { manager = new INetworkListManager(); } catch (UnauthorizedAccessException) { } catch (ExternalException) { } return manager; } } internal class NetworkConnectionIterator : IEnumerableList, IDisposable { private IEnumNetworkConnections conns; internal NetworkConnectionIterator(IEnumNetworkConnections conns = null) { this.conns = conns; } public int Length => Items.Count(); private IEnumerable Items => GetItems(conns); private static IEnumerable GetItems(IEnumNetworkConnections conns) { IEnumerable ie = null; try { ie = (conns ?? Manager?.GetNetworkConnections()).Cast().Select(i => new NetworkConnection(i)); } catch (UnauthorizedAccessException) { } catch (ExternalException) { } return ie; } public NetworkConnection this[Guid id] => new NetworkConnection(Manager?.GetNetworkConnection(id)); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public IEnumerator GetEnumerator() { var ie = Items; if (ie == null) yield break; foreach (var conn in ie) yield return conn; } void IDisposable.Dispose() { if (conns == null) return; Marshal.FinalReleaseComObject(conns); conns = null; } } private class NetworkIterator : IEnumerableList { internal NetworkIterator() { } public int Length => Items.Count(); private static IEnumerable Items { get { IEnumerable ie = null; try { ie = Manager?.GetNetworks(NLM_ENUM_NETWORK.NLM_ENUM_NETWORK_ALL).Cast().Select(i => new NetworkProfile(i)); } catch (UnauthorizedAccessException) { } catch (ExternalException) { } return ie; } } public NetworkProfile this[Guid id] => new NetworkProfile(Manager?.GetNetwork(id)); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public IEnumerator GetEnumerator() { var ie = Items; if (ie == null) yield break; foreach (var networkProfile in ie) yield return networkProfile; } } } }