Set Machine IP on Windows 7 - c#

I am working on a bit of code that uses a custom DHCP protocol to get an ip. The code then needs to set one of the machines NICs to that ip.
The code i have for that is below.
private void SetIp(IPAddress ipAddress, IPAddress subnetMask, IPAddress gatewayAddress)
{
try
{
ManagementBaseObject objNewIP = null;
ManagementBaseObject objSetIP = null;
ManagementBaseObject objNewGate = null;
objNewIP = networkInterface.GetMethodParameters("EnableStatic");
objNewGate = networkInterface.GetMethodParameters("SetGateways");
//Set DefaultGateway
objNewGate["DefaultIPGateway"] = new string[] { gatewayAddress.ToString() };
objNewGate["GatewayCostMetric"] = new int[] { 1 };
//Set IPAddress and Subnet Mask
objNewIP["IPAddress"] = new string[] { ipAddress.ToString() };
objNewIP["SubnetMask"] = new string[] { subnetMask.ToString() };
objSetIP = networkInterface.InvokeMethod("EnableStatic", objNewIP, null);
objSetIP = networkInterface.InvokeMethod("SetGateways", objNewGate, null);
Console.WriteLine(
"Updated IPAddress, SubnetMask and Default Gateway!");
}
catch (Exception ex)
{
}
// throw new System.NotImplementedException();
}
I keep on getting 2147749891 on the EnableStatic call. This post Machine IP reset does nothing suggests i need admin priviledges on the machine which I do.
The microsoft page https://msdn.microsoft.com/en-us/library/aa390383(v=vs.85).aspx suggests i need to acquire a write lock which requires com code which i would rather avoid.
Is there a better way to achieve this, perhaps using netsh and maybe in a way that doesn't require admin priviledges? All i have the mac address of the NIC to set and the details to set for it
Thanks

I got the same error when calling EnableStatic.
Elevating the running user to an admin (run as admin) solved my problem, which seems normal: only admin can change the NIC parameters.
I have yet to determine why a user with admin access cannot run the same code, possibly an UAC problem, investigation is on-going.
As for the microsoft page (https://msdn.microsoft.com/en-us/library/aa390383(v=vs.85).aspx), the "Write lock not enabled" is 2147786788.
Not 2147749891.

Related

How to keep common name of SSL while changing port wss

I have a problem here. I created a windows app that requires interaction between browser and desktop apps. In the desktop app, I include WebSocket Secure made by [Dave](WebSocket Server in C#).
I have a valid pfx file. While using the default port (443), everything runs smoothly. The URL shows the CN of the SSL. My window app then has to use other port other than default ones (443), when I change in setting it runs not as per CN of the SSL but instead localhost:portnum. how to make it run using CN in ports other than 443? Please help.
I will try to answer this.
I have checked the link that you have pasted and came across the following code snippet:
private static void Main(string[] args){
IWebSocketLogger logger = new WebSocketLogger();
try
{
string webRoot = Settings.Default.WebRoot;
int port = Settings.Default.Port;
// used to decide what to do with incoming connections
ServiceFactory serviceFactory = new ServiceFactory(webRoot, logger);
using (WebServer server = new WebServer(serviceFactory, logger))
{
server.Listen(port);
Thread clientThread = new Thread(new ParameterizedThreadStart(TestClient));
clientThread.IsBackground = false;
clientThread.Start(logger);
Console.ReadKey();
}
}
catch (Exception ex)
{
logger.Error(null, ex);
Console.ReadKey();
}
}
Within the try block there is this code line:
int port = Settings.Default.Port;
Maybe trying setting that to an auto assign port fix your problem.

C# create firewall rule to allow system to respond to pings?

I inherited a C# application and working on it. It creates some firewall rules programmatically. By default it disables everything on a specific interface, then allows a few specified TCP ports access, which is fine. I can't figure out how to modify the code to allow that port to respond to ping commands. However, and couldn't find any code online in other searches that would do that.
Does anyone know how to use C# to create a firewall rule to allow a port to respond to ping commands? The app will be deployed in Windows 7 embedded, 64 bit.
Here is some existing code which creates a rule to open a TCP port, which works OK:
private void SetupFirewallAllowIncomingRule(int port)
{
try
{
_log.Debug("Creating instance of Windows Firewall policy (HNetCfg.FwPolicy2)...");
INetFwPolicy2 firewallPolicy = Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2")) as INetFwPolicy2;
if (null == firewallPolicy)
{
_log.Error("HNetCfg.FwPolicy2 instance could not be created!");
return;
}
string name = "Rule Port " + port.ToString();
foreach (INetFwRule2 rule in firewallPolicy.Rules)
{
if (name.Equals(rule.Name))
{
_log.WarnFormat("Windows Firewall Rule ({0}) already exists. It will not be created again.", rule.Name);
return;
}
}
_log.Debug("Creating new Windows Firewall Rule (HNetCfg.FWRule)...");
INetFwRule firewallRule = Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FWRule")) as INetFwRule;
if (null == firewallRule)
{
_log.Error("HNetCfg.FWRule instance could not be created!");
return;
}
firewallRule.Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW;
firewallRule.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN;
firewallRule.Enabled = true;
firewallRule.InterfaceTypes = "All";
firewallRule.Name = name;
firewallRule.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP;
//NOTE: Must do this after setting the Protocol!
firewallRule.LocalPorts = port.ToString();
_log.DebugFormat("Adding Windows Firewall Rule {0}...", firewallRule.Name);
firewallPolicy.Rules.Add(firewallRule);
_log.InfoFormat("Windows Firewall Rule {0} added.", firewallRule.Name);
}
catch (Exception ex)
{
_log.Error("Windows Firewall Rule could not be added for port " + port.ToString() + "!", ex);
}
}

Client IP address returns the same internal network address

I'm trying to get the user's IP address from ASP.NET MVC 5. I've looked up various examples, such as these:
https://stackoverflow.com/a/740431/177416
https://stackoverflow.com/a/20194511/177416
https://stackoverflow.com/a/3003254/177416
They've all produced the same result: the user is considered internal to the network. I've had friends try their phones (which are not on the network). Here's my latest attempt:
private static Logger _logger = LogManager.GetCurrentClassLogger();
public static bool IsIpInternal()
{
var ipAddress = HttpContext.Current.Request.UserHostAddress;
var logEvent = new LogEventInfo(LogLevel.Info, _logger.Name, ipAddress);
_logger.Log(logEvent);
try
{
if (ipAddress != null)
{
var ipParts = ipAddress.Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries)
.Select(int.Parse).ToArray();
var isDebug = System.Diagnostics.Debugger.IsAttached;
if (ipParts[0] == 10)
{
return true;
}
}
}
catch (Exception e)
{
logEvent = new LogEventInfo(LogLevel.Error, _logger.Name, e.Message);
_logger.Log(logEvent);
return false;
}
return false;
}
The log is showing 10.xxx.xx.xxx for all requests (based on the log). This is an internal address rather than the IP of the client connecting to the web app. The IsIpInternal() returns true always. What am I doing wrong?
Note that I'm ignoring 192.168.x.x and 172.16.xxx.xxx addresses as being internal.
If your web site is behind a load balancer, it is a common problem for the load balancer's IP address to appear when you are expecting the client's IP address. That is because in reality the load balancer is the only client that the web application knows is talking to it.
There are two ways to deal with this:
You can configure the load balancer to add an additional HTTP header (x-forwarded-for) that specifies the original IP address. You will need to modify your web site to look at this header instead of the UserHostAddress, like this:
//var clientIP = HttpContext.Current.Request.UserHostAddress;
var clientIP = HttpContext.Current.Request.Headers["x-forwarded-for"];
Note: The x-forwarded-for header can actually return a comma-delimited list of IP addresses in some cases. So to be compatible with such an occurence, you might write this instead:
var clientIP = HttpContext.Current.Request.Headers["x-forwarded-for"].Split(',')[0];
You can configure certain LBs to pass through the client IP by copying the IP header packet. For Citrix Netscaler, see this article for more information.

Polling for IP address change in C# using WMI/Win32_NetworkAdapterConfiguration

I'm making a program that needs to set a static IP to a computer's wired NIC, and the program can't perform the next part (querying an SNMP string from another IP on the same network) until it's positively set and usable, which experience has taught me isn't always instant. This program is written in C# on VS2013 as a WinForms application, and the function is below. The actual setting of the IP address works perfectly, the problem is trying to poll for when the change completes. I can run the program, have it set an IP address (never more than a single IP/Subnet/Gateway), and while it's still polling for the change, pop open a command prompt, run ipconfig, and see that the change has already gone through. The program will continue to hang until it times out. I have tried several different methods of querying and checking the IP addresses, including reassigning NICConfig every time through the loop and checking to see if any IP addresses in either string[] match, nothing works. I have not yet piped currentIPs[0] into a file or command line to see what it contains, but I strongly suspect it will contain the previous IP address. I also tried setting the IP address in the registry, per this post: Why does applying a static IP address via WMI work just once? but all that did for me was give me a second IP address on that interface in ipconfig with the program still hanging.
Actually, on further examination, it looks like the behavior is to add the IP address/subnet/gateway to the list (string array), instead of replacing the old info, but the program isn't even getting an updated version of the list with the intended IP on it. This may not have started until after messing with the registry values using code from the above link, I can't be sure. I also can't seem to remove the extra IPs from my PC's configuration, they don't show up in the windows ipv4 configuration page (but I do get a warning when closing it about multiple gateways), and removing them from the registry seems to do nothing - so any help fixing my computer's NIC configuration would also be appreciated.
private bool set_staticIP(string Index, string[] IP, string[] Subnet, string[] Gateway, string[] DNS)
{
string WMIQuery = String.Format("Win32_NetworkAdapterConfiguration.Index='{0}'", Index);
ManagementObject NICConfig = new ManagementObject(#"root\CIMV2", WMIQuery, null);
ManagementBaseObject inParams = null;
ManagementBaseObject outParams = null;
string[] OldIP = (string[])NICConfig["IPAddress"];
try
{
/* Set IP/Subnet mask */
inParams = NICConfig.GetMethodParameters("EnableStatic");
inParams["IPAddress"] = IP;
inParams["SubnetMask"] = Subnet;
outParams = NICConfig.InvokeMethod("EnableStatic", inParams, null);
if (outParams["ReturnValue"].ToString() != "0")
{
MessageBox.Show("Error setting IP, returned " + outParams["ReturnValue"]);
}
/* Set Gateway(s) */
inParams = NICConfig.GetMethodParameters("SetGateways");
inParams["DefaultIPGateway"] = Gateway;
inParams["GatewayCostMetric"] = new int[] {1};
outParams = NICConfig.InvokeMethod("SetGateways", inParams, null);
if (outParams["ReturnValue"].ToString() != "0")
{
MessageBox.Show("Error setting Gateway, returned " + outParams["ReturnValue"]);
}
/* Set DNS Servers */
inParams = NICConfig.GetMethodParameters("SetDNSServerSearchOrder");
inParams["DNSServerSearchOrder"] = DNS;
outParams = NICConfig.InvokeMethod("SetDNSServerSearchOrder", inParams, null);
if (outParams["ReturnValue"].ToString() != "0")
{
MessageBox.Show("Error setting DNS, returned " + outParams["ReturnValue"]);
}
bool IPMatches = false;
string[] currentIPs = null;
int timeout = 2000;
int i;
for (i = 0; i < timeout && !IPMatches; i++)
{
currentIPs = (string[])NICConfig["IPAddress"];
if (currentIPs == IP || currentIPs != OldIP)
{
IPMatches = true;
break;
}
Task.Delay(100);
}
if (i >= timeout)
{
MessageBox.Show("Timeout while setting static IP address");
}
}
catch(ManagementException e)
{
MessageBox.Show("set_static() threw exception " + e.Message);
}
return IPMatches;
}
The machines I've tested this on are a laptop running Windows 7 x64, I get the same behavior with the internal NIC and a USB NIC, and a tablet running Windows 8.1 x64 with the same USB NIC.
You can use:
// Callback für Netzwerk-Änderungen erzeugen
NetworkChange.NetworkAddressChanged += new NetworkAddressChangedEventHandler(AddressChangedCallback);
// Callback für Netzwerk-Änderungen
void AddressChangedCallback(object sender, EventArgs e)
{
// IP is changed;
}
You will get the callback whenever a network adress is changed. Now you can check if it is the adress you are waiting for.

Changing the IP address on an .NET 2.0 Remoting service breaks new clients from connecting

I have a C++ Windows service exposing a .Net Remoting interface for a local client to use and everything works great until the IP address changes.
Since I have to support .Net 2.0, switching to WCF isn't an option.
Any ideas on what I can do?
Here's how I set up the channel:
Hashtable^ dict = gcnew Hashtable();
dict["port"] = 9085;
dict["authenticationMode"] = "IdentifyCallers";
dict["impersonate"] = nullptr;
dict["secure"] = true;
dict["typeFilterLevel"] = "Full";
TcpServerChannel^ tcpChannel;
try
{
tcpChannel = gcnew TcpServerChannel( dict, nullptr);
}
catch (Exception^ e)
{
}
try
{
ChannelServices::RegisterChannel(tcpChannel, true);
}
catch (RemotingException^ RemoteException)
{
return FALSE;
}
catch (Exception^ e) { }
MyServiceProxy^ proxy = gcnew MyServiceProxy(m_pService);
RemotingServices::Marshal(proxy,"ServiceProxy");
Here's how I'm connecting to that service via C#
IDictionary dict = new Hashtable();
dict["port"] = 9085;
dict["name"] = "127.0.0.1";
dict["secure"] = true;
dict["tokenImpersonationLevel"] = "Impersonation";
dict["typeFilterLevel"] = "Full";
dict["connectionTimeout"] = 10000; // 10 seconds timeout
workChannel = new TcpClientChannel(dict, null);
try
{
ChannelServices.RegisterChannel(workChannel, true);
}
catch (System.Exception /*e*/)
{
}
string objectPath = "tcp://127.0.0.1:9085/ServiceProxy";
obj = (IMyService)Activator.GetObject(typeof(IMyService), objectPath);
I mean when the computers IP address changes. So here's the flow.
Start the service which sets up the channel, then close the laptop lid, go home, open it back up again, get assigned a new IP address, now when I try to start the client and it can't connect the the service.
After a good bit of research, I ran across the 'bindTo' parameter...and all I needed to do was to add the parameter to the TCPServerChannel dictionary.
dict["bindTo"]= "127.0.0.1";
If this didn't work, I was going to try to using the IPCServerChannel, but thankfully this one line was all I needed.
And to think, this one line has caused so much grief.
Thank you Alexei for helping.

Categories