Files
CommonLib/CommonLib/Library/Windows/Misc/NetworkManagement.cs
2025-03-13 18:15:01 -07:00

613 lines
25 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.NetworkInformation;
using System.Management;
using System.Runtime.InteropServices;
using System.IO;
using Microsoft.Win32;
using System.Text.RegularExpressions;
using System.Security.Principal;
using System.Security.AccessControl;
using CommonLib.IO;
using CommonLib.Misc;
using CommonLib.Diagnostics;
namespace CommonLib.Windows.Misc
{
public class NetworkManagement
{
//////==========================================================================
/// NetworkSharing.GetNetworkAdapterAndConfigurationBasedOnPciLocation
///==========================================================================
/// <summary>
/// Given PCI Location (bus,device,function), obtain references to objects of
/// type Win32_NetworkAdapter and Win32_NetworkAdapterConfiguration.
/// These two object provides us with a wide array of information about the
/// network adapter
/// </summary>
/// <param name="networkAdapter">
/// This object must be of type Win32_NetworkAdapter
/// </param>
/// <param name="networkAdapterConfiguration">
/// This object must be of type Win32_NetworkAdapterConfiguration
/// </param>
/// <param name="expectedPciLocation">
/// Must be in this format: #,#,# (bus,device,function)
/// i.e.: 61,7,2
/// Every PCI network adapter has a unique location.
/// </param>
/// <param name="errMsg">error message returned if error encountered</param>
/// <return>true/false</return>
///==========================================================================
/// Date Programmer Proj.ID SAR REVISION HISTORY:
/// --/--/-- ------------ -------- ---- -----------------------------
/// 12/07/16 D.Le
///==========================================================================
public static bool GetNetworkAdapterAndConfigurationBasedOnPciLocation(ref ManagementObject networkAdapter, ref ManagementObject networkAdapterConfiguration, string expectedPciLocation, ref string errMsg)
{
bool successful = true;
errMsg = "";
networkAdapter = null;
networkAdapterConfiguration = null;
ManagementObjectSearcher mos = null;
Match regExMatch;
string valueName = "LocationInformation";
string registryValueNameValue = "";
string actualPciLocationInfo = "";
try
{
if (expectedPciLocation.Length == 0)
{
throw new Exception("PCI Location cannot be empty. Provide PCI Location in the form: #,#,# representing bus,device,function");
}
else
{
expectedPciLocation = Regex.Replace(expectedPciLocation, @"\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*", "$1,$2,$3", RegexOptions.IgnoreCase);
}
mos = new ManagementObjectSearcher(@"SELECT *
FROM Win32_NetworkAdapter
WHERE Manufacturer != 'Microsoft'
AND NOT PNPDeviceID LIKE 'ROOT\\%'");
if (mos == null)
{
throw new Exception("No network adapter found in the system");
}
foreach (ManagementObject adapter in mos.Get())
{
// print out all the properties name/value for each adapter
//foreach (PropertyData pd in adapter.Properties)
// Console.WriteLine(pd.Name + ": " + (pd.Value ?? "N/A"));
//Console.WriteLine("Index: {0}, Name: {1}", adapter["DeviceID"],adapter["Name"]);
string pnpDeviceIdRegistryPath = @"SYSTEM\CurrentControlSet\Enum\" + adapter["PNPDeviceID"];
RegistryKey hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
RegistryKey rkSubKey = hklm.OpenSubKey(pnpDeviceIdRegistryPath, false);
List<string> list = new List<string>(rkSubKey.GetValueNames());
// if there's a name "LocationInformation" found in the registry key
if (list.FindIndex(x => x.Equals(valueName, StringComparison.OrdinalIgnoreCase)) != -1)
{
// get the value associated with LocationInformation
registryValueNameValue = rkSubKey.GetValue(valueName).ToString();
regExMatch = Regex.Match(registryValueNameValue, @".+\((\d+,\d+,\d+)\)$", RegexOptions.IgnoreCase);
if (regExMatch.Success)
{
// get actual pci location in this format #,#,# which corresponds to bus,device,function
actualPciLocationInfo = regExMatch.Groups[1].Value;
}
}
if (expectedPciLocation == actualPciLocationInfo)
{
networkAdapter = adapter;
foreach (ManagementObject configuration in
adapter.GetRelated("Win32_NetworkAdapterConfiguration"))
{
// print out all the properties name/value for each configuration
//foreach (PropertyData pd in configuration.Properties)
// Console.WriteLine(pd.Name + ": " + (pd.Value ?? "N/A"));
networkAdapterConfiguration = configuration;
}
break;
}
}
if (networkAdapterConfiguration == null)
{
throw new Exception("No network adapter found at PCI Location: " + expectedPciLocation);
}
}
catch (Exception ex)
{
errMsg = ex.Message;
successful = false;
}
return successful;
}
//////==========================================================================
/// NetworkSharing.SetNetworkAdapterForDhcp
///==========================================================================
/// <summary>
/// Set network adapter to use DHCP. This is the same thing as setting the adapter
/// to obtain IP and DNS automatically
/// </summary>
/// <param name="networkAdapter">
/// This object must be of type Win32_NetworkAdapter
/// </param>
/// <param name="networkAdapterConfiguration">
/// This object must be of type Win32_NetworkAdapterConfiguration
/// </param>
/// <param name="errMsg">error message returned if error encountered</param>
/// <return>true/false</return>
///==========================================================================
/// Date Programmer Proj.ID SAR REVISION HISTORY:
/// --/--/-- ------------ -------- ---- -----------------------------
/// 12/07/16 D.Le
///==========================================================================
public static bool SetNetworkAdapterForDhcp(ManagementObject networkAdapter, ManagementObject networkAdapterConfiguration, ref string errMsg)
{
bool successful = true;
errMsg = "";
try
{
if (networkAdapter == null)
{
throw new Exception("Object networkAdapter cannot be null");
}
else if (networkAdapterConfiguration == null)
{
throw new Exception("Object adapterNetworkConfiguration cannot be null");
}
ManagementBaseObject setDhcp;
setDhcp = networkAdapterConfiguration.InvokeMethod("EnableDHCP", null, null);
uint returnedVal = UInt32.Parse(setDhcp["returnValue"].ToString());
// failed because the adapter is disconnected
if (returnedVal == 84)
{
string adapterGuid = @"SYSTEM\CurrentControlSet\services\Tcpip\Parameters\Interfaces\" + networkAdapter["GUID"];
successful = WindowsRegistry.AddOrModifyRegistryKeySingleValue(adapterGuid, RegistryHive.LocalMachine, "EnableDHCP", RegistryValueKind.String, "1", ref errMsg);
if (!successful)
throw new Exception(errMsg);
// set dns server to be obtained automatically
successful = WindowsRegistry.AddOrModifyRegistryKeySingleValue(adapterGuid, RegistryHive.LocalMachine, "NameServer", RegistryValueKind.String, "", ref errMsg);
if (!successful)
throw new Exception(errMsg);
successful = WindowsRegistry.DeleteRegistryValueName(adapterGuid, RegistryHive.LocalMachine, "DisableDhcpOnConnect", ref errMsg);
if (!successful)
throw new Exception(errMsg);
successful = WindowsRegistry.DeleteRegistryValueName(adapterGuid, RegistryHive.LocalMachine, "DefaultGateway", ref errMsg);
if (!successful)
throw new Exception(errMsg);
successful = WindowsRegistry.DeleteRegistryValueName(adapterGuid, RegistryHive.LocalMachine, "DefaultGatewayMetric", ref errMsg);
if (!successful)
throw new Exception(errMsg);
successful = WindowsRegistry.DeleteRegistryValueName(adapterGuid, RegistryHive.LocalMachine, "IPAddress", ref errMsg);
if (!successful)
throw new Exception(errMsg);
successful = WindowsRegistry.DeleteRegistryValueName(adapterGuid, RegistryHive.LocalMachine, "SubnetMask", ref errMsg);
if (!successful)
throw new Exception(errMsg);
}
else if (returnedVal != 0)
{
throw new Exception("Unable to enable DHCP for this network adapter. Error code: " + setDhcp["returnValue"]);
}
}
catch (Exception ex)
{
errMsg = ex.Message;
successful = false;
}
return successful;
}
//////==========================================================================
/// NetworkSharing.SetNetworkAdapterIpAddress
///==========================================================================
/// <summary>
/// Set network adapter's IP address and subnet mask
/// </summary>
/// <param name="networkAdapterConfiguration">
/// This object must be of type Win32_NetworkAdapterConfiguration
/// </param>
/// <param name="ipAddress">i.e 192.168.0.1</param>
/// <param name="subnetMask">i.e 255.255.255.0</param>
/// <param name="errMsg">error message returned if error encountered</param>
/// <return>true/false</return>
///==========================================================================
/// Date Programmer Proj.ID SAR REVISION HISTORY:
/// --/--/-- ------------ -------- ---- -----------------------------
/// 12/07/16 D.Le
///==========================================================================
public static bool SetNetworkAdapterIpAddress(ManagementObject networkAdapterConfiguration, string ipAddress, string subnetMask, ref string errMsg)
{
bool successful = true;
errMsg = "";
try
{
if (!StringManip.IsValidIPv4(ipAddress))
{
throw new Exception(ipAddress + " is an invalid IPv4 Address");
}
else if (!StringManip.IsValidIPv4(subnetMask))
{
throw new Exception(subnetMask + " is an invalid IPv4 Address");
}
ManagementBaseObject setIP;
ManagementBaseObject newIP =
networkAdapterConfiguration.GetMethodParameters("EnableStatic");
newIP["IPAddress"] = new string[] { ipAddress };
newIP["SubnetMask"] = new string[] { subnetMask };
setIP = networkAdapterConfiguration.InvokeMethod("EnableStatic", newIP, null);
uint returnedVal = UInt32.Parse(setIP["returnValue"].ToString());
if (returnedVal != 0)
{
throw new Exception("Unable to change IP address/subnet mask for this network adapter. Error code: " + setIP["returnValue"]);
}
}
catch (Exception ex)
{
errMsg = ex.Message;
successful = false;
}
return successful;
}
//////==========================================================================
/// NetworkSharing.SetNetworkAdapterDefaultGateway
///==========================================================================
/// <summary>
/// Set default gateway for network adapter
/// </summary>
/// <param name="networkAdapterConfiguration">
/// This object must be of type Win32_NetworkAdapterConfiguration
/// </param>
/// <param name="defaultGateway">
/// IP address for the gateway
/// </param>
/// <param name="errMsg">error message returned if error encountered</param>
/// <return>true/false</return>
///==========================================================================
/// Date Programmer Proj.ID SAR REVISION HISTORY:
/// --/--/-- ------------ -------- ---- -----------------------------
/// 12/07/16 D.Le
///==========================================================================
public static bool SetNetworkAdapterDefaultGateway(ManagementObject networkAdapterConfiguration, string defaultGateway, ref string errMsg)
{
bool successful = true;
errMsg = "";
try
{
if (!StringManip.IsValidIPv4(defaultGateway))
{
throw new Exception(defaultGateway + " is an invalid IPv4 IP Address");
}
ManagementBaseObject setGateway;
ManagementBaseObject newGateway = networkAdapterConfiguration.GetMethodParameters("SetGateways");
newGateway["DefaultIPGateway"] = new string[] { defaultGateway };
newGateway["GatewayCostMetric"] = new int[] { 1 };
setGateway = networkAdapterConfiguration.InvokeMethod("SetGateways", newGateway, null);
uint returnedVal = UInt32.Parse(setGateway["returnValue"].ToString());
if (returnedVal != 0)
{
throw new Exception("Unable to change default gateway for this network adapter. Error code: " + setGateway["returnValue"]);
}
}
catch (Exception ex)
{
errMsg = ex.Message;
successful = false;
}
return successful;
}
//////==========================================================================
/// NetworkSharing.SetNetworkAdapterDnsServers
///==========================================================================
/// <summary>
/// Set DNS servers for the network adapter
/// </summary>
/// <param name="networkAdapter">
/// This object must be of type Win32_NetworkAdapter
/// </param>
/// <param name="networkAdapterConfiguration">
/// This object must be of type Win32_NetworkAdapterConfiguration
/// </param>
/// <param name="dnsServers">
/// Must provide at least one IP address for DNS server, maximum is 2 IP addresses
/// </param>
/// <param name="errMsg">error message returned if error encountered</param>
/// <return>true/false</return>
///==========================================================================
/// Date Programmer Proj.ID SAR REVISION HISTORY:
/// --/--/-- ------------ -------- ---- -----------------------------
/// 12/07/16 D.Le
///==========================================================================
public static bool SetNetworkAdapterDnsServers(ManagementObject networkAdapter, ManagementObject networkAdapterConfiguration, List<string> dnsServerList, ref string errMsg)
{
bool successful = true;
errMsg = "";
string nameServer = "";
try
{
if (networkAdapter == null)
{
throw new Exception("Object networkAdapter cannot be null");
}
else if (networkAdapterConfiguration == null)
{
throw new Exception("Object adapterNetworkConfiguration cannot be null");
}
else if (dnsServerList.Count == 0 || dnsServerList == null)
{
throw new Exception("DNS Server information not provided");
}
for (int i = 0; i < dnsServerList.Count; i++)
{
if (!StringManip.IsValidIPv4(dnsServerList[i].Trim()))
{
throw new Exception(dnsServerList[i].Trim() + " is an invalid IPv4 IP Address");
}
if (nameServer.Length == 0)
nameServer = dnsServerList[i].Trim();
else
nameServer += "," + dnsServerList[i].Trim(); ;
}
string[] dnsServers = dnsServerList.ToArray();
ManagementBaseObject newDNS =
networkAdapterConfiguration.GetMethodParameters("SetDNSServerSearchOrder");
newDNS["DNSServerSearchOrder"] = dnsServers;
ManagementBaseObject setDNS =
networkAdapterConfiguration.InvokeMethod("SetDNSServerSearchOrder", newDNS, null);
uint returnedVal = UInt32.Parse(setDNS["returnValue"].ToString());
// failed because the adapter is disconnected
if (returnedVal == 84)
{
string adapterGuid = @"SYSTEM\CurrentControlSet\services\Tcpip\Parameters\Interfaces\" + networkAdapter["GUID"];
successful = WindowsRegistry.AddOrModifyRegistryKeySingleValue(adapterGuid, RegistryHive.LocalMachine, "NameServer", RegistryValueKind.String, nameServer, ref errMsg);
if (!successful)
throw new Exception(errMsg);
}
else if (returnedVal != 0)
{
throw new Exception("Unable to change default gateway for this network adapter. Error code: " + setDNS["returnValue"]);
}
}
catch (Exception ex)
{
errMsg = ex.Message;
successful = false;
}
return successful;
}
//////==========================================================================
/// NetworkSharing.ChangeNetworkAdapterName
///==========================================================================
/// <summary>
/// Change the name of the network adapter
/// </summary>
/// <param name="networkAdapter">
/// This object must be of type Win32_NetworkAdapter
/// </param>
/// <param name="networkAdapterConfiguration">
/// This object must be of type Win32_NetworkAdapterConfiguration
/// </param>
/// <param name="adapterName">
/// Name to give the network adapter
/// </param>
/// <param name="errMsg">error message returned if error encountered</param>
/// <return>true/false</return>
///==========================================================================
/// Date Programmer Proj.ID SAR REVISION HISTORY:
/// --/--/-- ------------ -------- ---- -----------------------------
/// 12/07/16 D.Le
///==========================================================================
public static bool ChangeNetworkAdapterName(ManagementObject networkAdapter, ManagementObject networkAdapterConfiguration, string adapterName, ref string errMsg)
{
bool successful = true;
errMsg = "";
string uniqueID = "";
try
{
if (networkAdapter == null)
{
throw new Exception("Object networkAdapter cannot be null");
}
else if (networkAdapterConfiguration == null)
{
throw new Exception("Object adapterNetworkConfiguration cannot be null");
}
else if (adapterName.Length == 0)
{
throw new Exception("adapterName cannot be empty");
}
string adapterGuid = @"SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\" + networkAdapter["GUID"] + @"\Connection";
uniqueID = Guid.NewGuid().ToString();
successful = WindowsRegistry.AddOrModifyRegistryKeySingleValue(adapterGuid, RegistryHive.LocalMachine, "Name", RegistryValueKind.String, uniqueID, ref errMsg);
if (!successful)
throw new Exception(errMsg);
ProcessStarter proc = new ProcessStarter();
proc.fileName = @"C:\Windows\System32\netsh.exe";
proc.procArguments = "interface set interface name=\"" + uniqueID + "\" newname=\"" + adapterName + "\"";
proc.Run();
if (proc.procExitCode != 0)
{
throw new Exception("Process netsh.exe returned the following error\n" + proc.outputMsg);
}
}
catch (Exception ex)
{
errMsg = ex.Message;
successful = false;
}
return successful;
}
//////==========================================================================
/// NetworkSharing.SetNetworkAdapterLinkSpeed
///==========================================================================
/// <summary>
/// Set network adapter to use DHCP. This is the same thing as setting the adapter
/// to obtain IP and DNS automatically
/// </summary>
/// <param name="networkAdapter">
/// This object must be of type Win32_NetworkAdapter
/// </param>
/// <param name="networkAdapterConfiguration">
/// This object must be of type Win32_NetworkAdapterConfiguration
/// </param>
/// <param name="linkSpeedValue">
/// Value of the link speed
/// </param>
/// <param name="errMsg">error message returned if error encountered</param>
/// <return>true/false</return>
///==========================================================================
/// Date Programmer Proj.ID SAR REVISION HISTORY:
/// --/--/-- ------------ -------- ---- -----------------------------
/// 12/07/16 D.Le
///==========================================================================
public static bool SetNetworkAdapterLinkSpeed(ManagementObject networkAdapter, ManagementObject networkAdapterConfiguration, string linkSpeedValue, ref string errMsg)
{
bool successful = false;
errMsg = "";
try
{
uint linkSpeed = 0;
if (networkAdapter == null)
{
throw new Exception("Object networkAdapter cannot be null");
}
else if (networkAdapterConfiguration == null)
{
throw new Exception("Object adapterNetworkConfiguration cannot be null");
}
else if (linkSpeedValue.Length == 0)
{
throw new Exception("linkSpeedValue cannot be empty");
}
else if (!UInt32.TryParse(linkSpeedValue, out linkSpeed))
{
throw new Exception("linkSpeedValue must be a number");
}
var hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
RegistryKey regSubKey = null;
string registryPath = @"SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}";
regSubKey = hklm.OpenSubKey(registryPath, false);
// get a list of folder names under the registry path above
List<string> keyNameList = new List<string>(regSubKey.GetSubKeyNames());
regSubKey.Close();
// loop through each key name to find the entry for the adapter we are interested in
foreach (string keyName in keyNameList)
{
string vendorRegistryPath = registryPath + @"\" + keyName;
string adapterGuid = WindowsRegistry.GetRegistryValueInString(vendorRegistryPath, RegistryHive.LocalMachine, "NetCfgInstanceId");
// if this is the adapter we are interested in
if (String.Equals(adapterGuid, networkAdapter["GUID"].ToString(), StringComparison.OrdinalIgnoreCase))
{
successful = WindowsRegistry.AddOrModifyRegistryKeySingleValue(vendorRegistryPath, RegistryHive.LocalMachine, "*SpeedDuplex", RegistryValueKind.String, linkSpeedValue, ref errMsg);
if (!successful)
throw new Exception(errMsg);
break;
}
}
if (!successful && errMsg.Length == 0)
throw new Exception("Unable to find a registry entry for this network adapter under " + registryPath);
}
catch (Exception ex)
{
errMsg = ex.Message;
successful = false;
}
return successful;
}
}
}