Lorenzo Santoro
Lorenzo Santoro

Reputation: 512

C# WMI : Adding/Removing multiple IP addresses to NIC

My application is C# .net Framework 3.5.

The main functionality of the application is:

  1. let the user choose a network interface card (NIC)
  2. assign to the user selected NIC an IP address (and subnet mask) - I use WMI - EnableStatic method of Win32_NetworkAdapterConfiguration class.
  3. start through a Process a 3rd party C++ exe component, behaving like a server, which will be listening to the given IP address - the binding functionality is implemented by the server, so on Process start up I just give pass the proper IP address and it starts listening on that one.

Operation 2 and 3 can be repeated an unlimited number of times, thus it's possible to assign to the very same NIC several IP addresses and have multiple servers, each one listening to the its own IP address.

To assign the IP address to the given NIC I use WMI, in particular this code, where adapterGUID is the GUID of the user selected NIC and newSettings it's a class holding a list of IPs and subnet masks:

public static bool ChangeNetworkInterfaceIPs(string adapterGUID, IpSettings newSettings)
    {
        try
        {
            if (String.IsNullOrEmpty(adapterGUID))
                    throw new ArgumentException("adapterGUID");

                ManagementBaseObject inPar = null;

                ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
                ManagementObjectCollection moc = mc.GetInstances();
                ManagementObject moTarget = null;

                //Look for the correct network interface
                foreach (ManagementObject mo in moc)
                {
                    //find the target management object
                    if ((string) mo["SettingID"] == adapterGUID)
                    {
                        moTarget = mo;
                        break;
                    }
                }
                if (moTarget == null)
                {
                    mc = null;
                    return false;
                }

                //we found the correct NIC. Save the current gateways, dns and wins
                object winsSecondary = moTarget.GetPropertyValue("WINSSecondaryServer");
                object gateways = moTarget.GetPropertyValue("DefaultIPGateway");
                object dnsDomain = moTarget.GetPropertyValue("DNSDomain");
                object dnsServers = moTarget.GetPropertyValue("DNSServerSearchOrder");
                object winsPrimary = moTarget.GetPropertyValue("WINSPrimaryServer");

                if (newSettings.DHCP)
                {
                    inPar = moTarget.GetMethodParameters("EnableDHCP");
                    moTarget.InvokeMethod("EnableDHCP", inPar, null);
                }
                else
                {
                    inPar = moTarget.GetMethodParameters("EnableStatic");
                    inPar["IPAddress"] = newSettings.Ips;
                    inPar["SubnetMask"] = newSettings.Netmasks;
                    moTarget.InvokeMethod("EnableStatic", inPar, null);
                }

                //restore the gateways, dns and wins
                if (gateways != null && !newSettings.DHCP)
                {
                    inPar = moTarget.GetMethodParameters("SetGateways");
                    inPar["DefaultIPGateway"] = gateways;
                    outPar = moTarget.InvokeMethod("SetGateways", inPar, null);
                }
                if (dnsDomain != null && !newSettings.DHCP)
                {
                    inPar = moTarget.GetMethodParameters("SetDNSDomain");
                    inPar["DNSDomain"] = dnsDomain;
                    outPar = moTarget.InvokeMethod("SetDNSDomain", inPar, null);
                }
                if (dnsServers != null && !newSettings.DHCP)
                {
                    //Do not restore DNS Servers in case of DHCP. Will be retrieved from DHCP Server
                    inPar = moTarget.GetMethodParameters("SetDNSServerSearchOrder");
                    inPar["DNSServerSearchOrder"] = dnsServers;
                    outPar = moTarget.InvokeMethod("SetDNSServerSearchOrder", inPar, null);
                }
                if (winsPrimary != null && !newSettings.DHCP)
                {
                    inPar = moTarget.GetMethodParameters("SetWINSServer");
                    inPar["WINSPrimaryServer"] = winsPrimary;
                    if (winsSecondary != null)
                    {
                        inPar["WINSSecondaryServer"] = winsSecondary;
                    }
                    outPar = moTarget.InvokeMethod("SetWINSServer", inPar, null);
                }

                return true;
        }
        catch
        {
            return false;
        }
    }

Now, my problem comes when the user wants to kill one the active servers. On server closure I have to remove from the NIC the IP address the server was listening to.

Killing the process it's not a problem, but when I call my ChangeNetworkInterfaceIPs to update the IP assigned to NIC (removing the one of the server no longer in use) using a new list of IP address (namely: the old list without the ip address of the killed server) something very strange happens: randomly some of other running servers get a SOCKET_ERROR and their connection it's closed.

Any idea on what's happening? Why the running servers are randomly getting SOCKET_ERRORs when I remove an unused IP address from the NIC ? Additionally, I know that probably setting a whole list of IP addresses just to remove one it's not really a best practice: is there a way to remove just a given IP address?

I hope the question is clear enough. Thank you for your time.

Upvotes: 0

Views: 4485

Answers (1)

Raj.A
Raj.A

Reputation: 51

I am not answering all the questions asked in the post, but posting this might be helpful for starters like me.

Question: Is there a way to remove just a given IP address?
Answer: run netsh command as a process in c#

Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "netsh";
p.StartInfo.Arguments = "netsh interface ipv4 delete address \"my NIC Name\" addr=192.168.1.1";
p.Start();
string response = p.StandardOutput.ReadToEnd();
p.Close();

Note: this command has to be ran in administrator.

Upvotes: 0

Related Questions