Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Internet Connection Sharing (ICS). Console Application to Share Internet Connection to Other Network Interface

5.00/5 (3 votes)
9 Mar 2022CPOL3 min read 8.6K   249  
Console app to share internet connection with other network interface
The purpose of this application is a quick way to share the internet connection from a certain network interface (for example, a VPN) to another interface (for example, a Remote NDIS interface to share the internet through the smartphone) in this case via console.

Introduction

Since internet sharing in Windows is quite annoying and Windows doesn't have an easier way for more advanced users, plus I need to execute a series of commands to connect my mobile device using it as a modem, this would be an easy way to get the whole job done. to share my internet connection using a single script.

Background

Although I had already found a way to do it using a Powershell script, it was still just as annoying, so I decided to port this script into a .NET application so it would just run and go. This was where I had to face the HNetCfg.HNetShare COM object, which is the one that allows operations of this type in Windows, so I realized that the use of Reflection was not so easy here, so doing a little more research, I found this article, Reflection with IDispatch-based COM objects, which made my task easier as the COMObject HNetCfg.HNetShare is of the IDispatch type and it was easier than having to implement the corresponding interfaces and types in the NetCon.h library.

Using the Code

Basically, I implemented a static class that will handle the objects and functions that I was going to use. The first thing is to register the hnetcfg.dll (it is a module associated with the Microsoft Corporation Home Networking Configuration Manager) and obtain the COMObject associated with HNetCfg.HNetShare, then you have to invoke the EnumEveryConnection property that returns a COMObject that actually represents an INetSharingEveryConnectionCollection with all the existing network connections, then for each connection the basic properties are obtained such as the name, the Guid, etc., invoking the NetConnectionProps property, and from the INetSharingConfigurationForINetConnection property, a COMObject of the type INetSharingConfiguration is obtained, which is the one that Allows you to enable or disable internet sharing for the associated network interface. So with the EnableSharing and DisableSharing methods, I can enable and disable internet sharing for a certain interface, as well as define who shares who.

Unregistering and reregistering the hnetcfg.dll ensured that the changes were applied correctly.

C#
/// <summary>
/// Manage ICS using COMObject HNetCfg.HNetShare
/// </summary>
static class NetConnectionDispatch {
    private static object _netShare;

    static NetConnectionDispatch() {
        Process.Start(new ProcessStartInfo("regsvr32.exe", "/s hnetcfg.dll"));
    }

    public static NetConnectionSharing[] GetAllNetConnections() {
        _netShare = ProgIdInstance("HNetCfg.HNetShare");

        List<NetConnectionSharing> nets = new List<NetConnectionSharing>();
        foreach (var i in EnumEveryConnection()) {
            nets.Add(GetNetConnectionSharingObject(i));
        }
        return nets.ToArray();
    }

    private static NetConnectionSharing GetNetConnectionSharingObject(object i) {
        var ncp = Invoke(_netShare, "NetConnectionProps", new[] { i });
        var inscfinc = Invoke(_netShare,
            "INetSharingConfigurationForINetConnection", new[] { i });

        NetConnectionSharing netConnection = new NetConnectionSharing() {
            Guid = (string)GetPropertyValue(ncp, "Guid"),
            Name = (string)GetPropertyValue(ncp, "Name"),
            DeviceName = (string)GetPropertyValue(ncp, "DeviceName"),
            Status = (NETCON_STATUS)GetPropertyValue(ncp, "Status"),
            MediaType = (NETCON_MEDIATYPE)GetPropertyValue(ncp, "MediaType"),
            Characteristics = (uint)GetPropertyValue(ncp, "Characteristics"),
            SharingEnabled = (bool)GetPropertyValue(inscfinc, "SharingEnabled"),
            SharingConnectionType =
               (SHARINGCONNECTIONTYPE)GetPropertyValue(inscfinc, "SharingConnectionType"),
            InternetFirewallEnabled =
                    (bool)GetPropertyValue(inscfinc, "InternetFirewallEnabled")
        };
        return netConnection;
    }

    private static IEnumerable<object> EnumEveryConnection() {
        List<object> result = new List<object>();
        var eec = Invoke(_netShare, "EnumEveryConnection", null);
        int count = (int)Invoke(eec, "Count", null);
        var @enum = Invoke(eec, "_NewEnum", null);
        while (count-- > 0) {
            @enum.GetType().InvokeMember("MoveNext",
                            BindingFlags.InvokeMethod, null, @enum, null);
            var current = @enum.GetType().GetProperties()[0].GetValue(@enum, null);
            result.Add(current);
        }
        return result;
    }

    private static object GetPropertyValue(object target, string propertyName) {
        return target.GetType().InvokeMember(propertyName,
        BindingFlags.InvokeMethod | BindingFlags.GetProperty, null, target, null, null);
    }

    private static object ProgIdInstance(string progId, params string[] memberNames) {
        Type standardType = Type.GetTypeFromProgID(progId);
        object obj = Activator.CreateInstance(standardType);

        // Make sure it implements IDispatch.
        if (!DispatchUtility.ImplementsIDispatch(obj)) {
            throw new ArgumentException("The object created for " + progId +
                                        " doesn't implement IDispatch.");
        }

        // See if we can get Type info and then do some reflection.
        //Type dispatchType = DispatchUtility.GetType(obj, false);

        return obj;
    }

    public static bool EnableSharing(NetConnectionSharing netConnection,
                                     int SHARINGCONNECTIONTYPE) {
        Process.Start(new ProcessStartInfo("regsvr32.exe", "/u /s hnetcfg.dll"));
        Process.Start(new ProcessStartInfo("regsvr32.exe", "/s hnetcfg.dll"));
        var INetConnection = EnumEveryConnection().Where
        (d => GetNetConnectionSharingObject(d).Guid == netConnection.Guid).FirstOrDefault();
        if (INetConnection == null) return false;
        var inscfinc = Invoke(_netShare, "INetSharingConfigurationForINetConnection",
                       new[] { INetConnection });
        var _result = inscfinc.GetType().InvokeMember
                      ("EnableSharing", BindingFlags.InvokeMethod, null,
                      inscfinc, new object[] { SHARINGCONNECTIONTYPE }, null);
        return false;
    }

    public static bool DisableSharing(NetConnectionSharing netConnection) {
        Process.Start(new ProcessStartInfo("regsvr32.exe", "/u /s hnetcfg.dll"));
        Process.Start(new ProcessStartInfo("regsvr32.exe", "/s hnetcfg.dll"));
        var INetConnection = EnumEveryConnection().Where
        (d => GetNetConnectionSharingObject(d).Guid == netConnection.Guid).FirstOrDefault();
        if (INetConnection == null) return false;
        var inscfinc = Invoke(_netShare, "INetSharingConfigurationForINetConnection",
                              new[] { INetConnection });
        var _result = inscfinc.GetType().InvokeMember
                      ("DisableSharing", BindingFlags.InvokeMethod, null, inscfinc, null);
        return true;
    }
}

Points of Interest

Help for usage

Commands:

  • -l: Get all information for network adapters
  • -from "<NetworkAdapterName>": Name of the source network adapter that will share the connection to the destination
  • -to "<NetworkAdapterName>": Name of the destination network adapter with which you want to share the source connection
  • 1: Allows you to enable the source connection to the destination
  • 0: Allows you to disable the source connection to the destination

Example:

  • This example enables connection to share internet from "Internet adapter" to "wlan adapter".
    simpleics -from "Internet adapter" -to "wlan adapter" 1
  • This example disables connection to share internet from "Internet adapter" to "wlan adapter".
    simpleics -from "Internet adapter" -to "wlan adapter" 0
  • This example disables SharingEnabled for this network adapter.
    simpleics "Internet adapter" 0
  • This example enables SharingEnabled for this network adapter by specifying that this is the origin.
    simpleics "Internet adapter" 1 0
  • This example enables SharingEnabled for this network adapter by specifying that this is the destination.
    simpleics "Internet adapter" 1 1

Hope my code is helpful.

History

  • 7th March, 2022: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)