9

How do you determine or examine the connection profile of the current network connection (if any)?

Specifically, I need to determine if the current connection is to a private or public network, and from there determine whether network discovery is turned on or off.

It seems like this information is readily available in a Windows Store app via the Windows.Networking.Connectivity.NetworkInformation.GetConnectionProfiles() or NetworkInformation.GetInternetConnectionProfile() functions, but this is a standard desktop app that must run on Win 7 and Server 2008 as well as Win 8 and Server 2012.

Enumerating the NICs on a machine is not a problem, but this doesn't solve my issue - I need to get the properties of the connection, not the physical device.

Is there an inbuilt way to do this with the .Net framework? Alternatively can it be done with WMI? Or as a crude alternative, can it be done by invoking the netsh command (although this seems to depend on the dot3svc and/or wlansvc services to be running)?

slugster
  • 49,403
  • 14
  • 95
  • 145
  • Does this help at all? http://stackoverflow.com/questions/6578480/unable-to-obtain-profile-of-connected-network-in-vista-7 – Jun Wei Lee Oct 07 '13 at 23:43
  • @JunWeiLee Thanks, it doesn't directly help. That is a code snippet that users the [Managed Wifi API](http://managedwifi.codeplex.com/) which wraps the [Native Wifi API](http://msdn.microsoft.com/en-us/library/ms705969.aspx). – slugster Oct 08 '13 at 00:00

2 Answers2

14

You can use Network List Manager API for that purpose, to use it from C# import Network List Manager Type Library.

Then you must enumerate all connected networks, because there can be more than one, for example right now I am connected to internet and VPN. Then for all connected networks call GetCategory() API, it returns NLM_NETWORK_CATEGORY (private, public or domain).

Here is the sample code (add using NETWORKLIST in use clauses) :

  var manager = new NetworkListManager();
  var connectedNetworks = manager.GetNetworks(NLM_ENUM_NETWORK.NLM_ENUM_NETWORK_CONNECTED).Cast<INetwork>();
  foreach (var network in connectedNetworks)
  {
    Console.Write(network.GetName() + " ");
    var cat = network.GetCategory();
    if (cat == NLM_NETWORK_CATEGORY.NLM_NETWORK_CATEGORY_PRIVATE)
      Console.WriteLine("[PRIVATE]");
    else if (cat == NLM_NETWORK_CATEGORY.NLM_NETWORK_CATEGORY_PUBLIC)
      Console.WriteLine("[PUBLIC]");
    else if (cat == NLM_NETWORK_CATEGORY.NLM_NETWORK_CATEGORY_DOMAIN_AUTHENTICATED)
      Console.WriteLine("[DOMAIN]");
  }      
  Console.ReadKey();

For this to work one must add reference to COM Network List 1.0 Type Library, like this:

adding COM Network List 1.0 Type library

For Network Discovery you have to use Firewall API and reference COM library NetFwTypeLib and get INetFwProfile for active profile, then in services there are File sharing, Network Discovery and Remote Desktop services, and there is a bool flag if these are Enabled. Here is the example code : (just to warn you I didn't use below code in production I was just exploring this API)

  Type objectType = Type.GetTypeFromCLSID(new Guid("{304CE942-6E39-40D8-943A-B913C40C9CD4}"));
  var man = Activator.CreateInstance(objectType) as INetFwMgr;
  /// get current profile 
  INetFwProfile prof = man.LocalPolicy.CurrentProfile;
  Console.WriteLine("Current profile ");
  ShowProfileServices(prof);

And the method that shows profile services.

private static void ShowProfileServices(INetFwProfile prof)
{
  var services = prof.Services.Cast<INetFwService>();
  var sharing = services.FirstOrDefault(sc => sc.Name == "File and Printer Sharing");
  if (sharing != null)
    Console.WriteLine(sharing.Name + " Enabled : " + sharing.Enabled.ToString());
  else
    Console.WriteLine("No sharing service !");

  var discovery = services.FirstOrDefault(sc => sc.Name == "Network Discovery");

  if (discovery != null)
    Console.WriteLine(discovery.Name + " Enabled : " + discovery.Enabled.ToString());
  else
    Console.WriteLine("No network discovery service !");

  var remoteDesktop = services.FirstOrDefault(sc => sc.Name == "Remote Desktop");
  if (remoteDesktop != null)
    Console.WriteLine(remoteDesktop.Name + " Enabled : " + remoteDesktop.Enabled.ToString());
  else
    Console.WriteLine("No remote desktop service !");
}
Antonio Bakula
  • 20,445
  • 6
  • 75
  • 102
  • Thanks for the answer, it solves part of my problem (I'm not sure the "network discovery" setting is easily obtainable). – slugster Oct 09 '13 at 03:47
  • oh, didn't see this, I played somewhat with firewall API's and there is a way trough that, I will update my answer – Antonio Bakula Oct 09 '13 at 12:03
  • Great answer, it was everything I needed :) – slugster Oct 10 '13 at 01:41
  • 1
    I would recommend keeping `Embed Interop Types` set to true though. You can avoid needing to change it by simply removing "Class" from `var manager = new NetworkListManagerClass();`... so that line should instead be `var manager = new NetworkListManager();`. Then you can minimize the dependency introduced by this COM reference. – u8it Feb 06 '17 at 21:45
  • Thanks for the answer. My Windows language is Turkish and sc.Name is "Dosya ve Yazıcı paylaşımı" :) So prefer sc.Type == NET_FW_SERVICE_TYPE_.NET_FW_SERVICE_FILE_AND_PRINT – Ercument Eskar Mar 29 '17 at 22:06
  • sharing is not null and sharing.Name returned properly. But when i try to access sharing.Enabled throw "An exception of type 'System.Runtime.InteropServices.COMException'" E_UNEXPECTED i cant find any resolve. Why i get this exception? Application and VS have Administration Privileges – Ercument Eskar Mar 30 '17 at 20:30
  • sorry don't have clue why this is happening, for me it worked properly – Antonio Bakula Mar 31 '17 at 08:55
  • `'NetworkListManagerClass' is inaccessible due to its protection level` How do I fix this? – Henry Davis Sep 18 '22 at 18:07
  • 1
    @Dan hmm, it's been almost 10 years from my answer, I tried to run this code and you must add reference to COM Network List Manager 1.0 Type library and change NetworkListManagerClass to NetworkListManager. I updated my answer – Antonio Bakula Sep 26 '22 at 08:47
  • @u8it updated my answer, thanks for your insight :) – Antonio Bakula Sep 26 '22 at 09:37
1

I know this question is super old, but I faced this problem recently - how to get Network Category (private or public) in C# using Windows.Network.Connectivity from Windows Runtime API.

There is almost everything related to networking but I could not find the Network Category.

The solution is NetworkTypes enum.

https://learn.microsoft.com/en-us/uwp/api/windows.networking.connectivity.networktypes?view=winrt-22000

Simply check if returned types has flag PrivateNetwork. If yes - then is't private, if not - it's public.

Example code below:

var adapters = NetworkInterface.GetAllNetworkInterfaces();
var upNetworkInterfaces = adapters.Where(x =>
    x.Supports(NetworkInterfaceComponent.IPv4) &&
    x.NetworkInterfaceType is NetworkInterfaceType.Ethernet or NetworkInterfaceType.Wireless80211);
foreach (var adapter in upNetworkInterfaces)
{
    var hostname = NetworkInformation.GetHostNames()
        .FirstOrDefault(x =>
            x.IPInformation != null &&
            string.Equals(x.IPInformation.NetworkAdapter.NetworkAdapterId.ToString(),
                adapter.Id.Replace("{", string.Empty).Replace("}", string.Empty),
                StringComparison.InvariantCultureIgnoreCase));

    if (hostname is not null)
    {
        var networkTypes = hostname.IPInformation.NetworkAdapter.NetworkItem.GetNetworkTypes();
        var privateNetwork = networkTypes.HasFlag(NetworkTypes.PrivateNetwork)
            ? NetworkAccessibilityLevel.Private
            : NetworkAccessibilityLevel.Public;
    }
}
beribazoo
  • 351
  • 5
  • 18