Below is simple code for creating a user in AD. The code is DC un-specific. It doesn't care which DC it creates it on, it'll use the windows default that the server is connected to.
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, Domain, path, ContextOptions.Negotiate, ManagementUsername, ManagementPassword))
{
try
{
using (UserPrincipal up = new UserPrincipal(pc, username, password, true))
{
up.GivenName = firstName; up.Surname = lastName; up.DisplayName = firstName + " " + lastName; up.UserPrincipalName = username + "#" + Domain; up.Save();
}
}
catch (PasswordException) { return null; }
}
The issue is that there is a replication time (usually domains have 15 minutes) of new accounts. This does not work when trying to implement an on-demand account creation when the account is requested by somebody wanting to use it on a workstation connected to a different DC than the server. They end up having to sit in front of the work station for up to 15 minutes being unable to log in.
Question:
Is there a way to connect to a DC based on client IP address to create it on that one? OR is there a way to make the account on all DC's and have the replication be ok with this? OR force the account to replicate programmatically (based on searching through SO, I'm guessing no).
Forest adForest = Forest.GetCurrentForest();
ActiveDirectorySite[] sites = new ActiveDirectorySite[adForest.Sites.Count];
adForest.Sites.CopyTo(sites, 0);
List<ActiveDirectorySubnet> subnets = new List<ActiveDirectorySubnet>();
sites.ToList().ForEach(x =>
{
ActiveDirectorySubnet[] subnetTemp = new ActiveDirectorySubnet[x.Subnets.Count];
x.Subnets.CopyTo(subnetTemp, 0);
subnets.AddRange(subnetTemp);
});
IPAddress address = IPAddress.Parse("IPAddress to look up closest DC");
var currentSubnet = subnets.Where(x => address.IsInRange(x.Name));
var location = currentSubnet.First().Site.Name;
DomainController dc = DomainController.FindOne(new DirectoryContext(DirectoryContextType.Domain, Domain), location);
This gets you the DC associated with that site and domain that is nearest the specified IP address within the topology.
Then you pass the DC IP address to the Principal Context.
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, dc.IPAddress, path, ContextOptions.Negotiate, ManagementUsername, ManagementPassword))
{
try
{
using (UserPrincipal up = new UserPrincipal(pc, username, password, true))
{
up.GivenName = firstName; up.Surname = lastName; up.DisplayName = firstName + " " + lastName; up.UserPrincipalName = username + "#" + Domain; up.Save();
}
}
catch (PasswordException) { return null; }
}
And create a user.
Note: IPAddress functions were done via NetTools IPAddressRange class on github and the following custom extensions of it.
/// <summary>
/// All extensions for IPAddress type
/// </summary>
public static class IPAddressExtension
{
/// <summary>
/// Determine whether this IP address is part of the range/subnet
/// </summary>
/// <param name="range">A range of IPAddresses</param>
/// <returns></returns>
public static bool IsInRange(this IPAddress thisIP, IPAddressRange range)
{
return range.Contains(thisIP);
}
/// <summary>
/// Determine whether this IP address is part of the range/subnet
/// </summary>
/// <param name="range">Can be specified in CIDR/UNI (ex: 192.168.10.0/24) </param>
/// <returns></returns>
public static bool IsInRange(this IPAddress thisIP, string rangeIP)
{
IPAddressRange range = IPAddressRange.Parse(rangeIP);
return range.Contains(thisIP);
}
/// <summary>
/// Determine whether this IP address is part of the range/subnet
/// </summary>
/// <param name="ipBegin">Beginning IP address of range</param>
/// <param name="ipEnd">Ending IP address of range</param>
/// <returns></returns>
public static bool IsInRange(this IPAddress thisIP, IPAddress ipBegin, IPAddress ipEnd)
{
IPAddressRange range = new IPAddressRange(ipBegin, ipEnd);
return range.Contains(thisIP);
}
}
Related
I developed site. I need to get IP of site visitors.
I try to use Request, but it have only internal IP:
Response.Write(Request.ServerVariables["REMOTE_ADDR"]);
I looked all keys in Server Variables collection - the same result:
foreach (string var in Request.ServerVariables)
{
Response.Write(Request[var]);
}
How can I get external IP address?
You can use it to get External (public) IP Address..
public static string getExternalIp()
{
try
{
string externalIP;
externalIP = (new WebClient()).DownloadString("http://checkip.dyndns.org/");
externalIP = (new Regex(#"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"))
.Matches(externalIP)[0].ToString();
return externalIP;
}
catch { return null; }
}
This it part of my implementation for WebTracking. So here you go a snippet for IpAddress retrieval. You can read more about the Server Variables at Wikipedia.
/// <summary>
/// Get ip address from request
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
private string GetIpAddress(HttpRequest request)
{
if (request.ServerVariables.IsNull()) return null;
var _realAddress = request.ServerVariables[#"HTTP_X_FORWARDED_FOR"];
if (_realAddress.IsNullOrEmpty())
{
_realAddress = request.ServerVariables[#"HTTP_FORWARDED"];
}
if (_realAddress.IsNullOrEmpty())
{
_realAddress = request.ServerVariables[#"REMOTE_ADDR"];
}
return _realAddress;
}
Are you behind a load-balancer/proxy? If so, inspect the headers collection of the request for headers similar to X-FORWARDED-FOR.
You can use like this
String lstrIpAddress;
if (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null || Request.ServerVariables["HTTP_CLIENT_IP"] != null)
lstrIpAddress = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
else
lstrIpAddress = Request.ServerVariables["REMOTE_ADDR"];
you can simply use this nuget package.
https://www.nuget.org/packages/IpPublicKnowledge/
easy and simple. here is an example :
// Get Public IP
var ip = IPK.GetMyPublicIp();
//Get all IP infos
var IPinfo = IPK.GetIpInfo(ip);
//print some info
Console.WriteLine("*--------------------------- IPK -----------------------------*");
Console.WriteLine("My public IP : " + IPinfo.IP);
Console.WriteLine();
Console.WriteLine("My ISP : " + IPinfo.isp);
Console.WriteLine();
Console.WriteLine("My Country : " + IPinfo.country);
Console.WriteLine();
Console.WriteLine("My Languages : ");
foreach (var lang in IPinfo.languages)
{
Console.WriteLine(" " + lang.Key + " : " + lang.Value);
}
Console.WriteLine("*-------------------------------------------------------------*");
Console.Read();
Here's what's going on. I have an ASP.NET MVC 4 Web API web application. I can call API resources via URL. One of these functions get performance monitoring data for a specified amount of time and returns it in JSON once it has completed. However, what I want to do is return
It is IMPORTANT to note that I am working with a the browser and API resources in the model, not with a View. Please don't casually tell me to use Javascript in a View, because there is no view, or tell me to look at the SignalR wiki because the information for ".NET" sections is meant for desktop applications, not web apps. For example, you can't "Console.WriteLine()" to a browser.
To reiterate, I am using ASP.NET MVC 4 Web API to develop an API, and am calling the API via URL in the browser and it is returning JSON. I am attempting to use SignalR to have the app send JSON to the browser, but it is not doing anything at all. Rather, the application simply returns the completed JSON from the controller action with all of the performance data values once the process has completed. In other words, SignalR is not working.
So what I'm trying to do is while the API resource is gathering all the information, SignalR sends JSON to the browser every second so that the client can see what's going on in real time.
What I need to find out is why SignalR isn't sending it, and how I can send information to be displayed in the browser without Javascript, since I'm working from a model class, not from a view.
As you can see, I subscribe to the event using On, and then use Invoke to call the server-side hub method SendToClient.
Please let me know if I'm trying to do is impossible. I have never heard of a "real-time", dynamic API call via URL.
Here is my hub class. It is located in ~/signalr/hubs and is in a file called LiveHub.cs. The method Send is what I am trying to invoke in the method seen in the next code block.
namespace PerfMon2.signalr.hubs
{
public class LiveHub : Hub
{
public void SendToClient(List<DataValueInfo> json)
{
Clients.showValue(json);
}
}
}
Here is the method from LogDBRepository.cs that includes the SignalR calls.
public List<LogInfo> LogTimedPerfData(string macName, string categoryName, string counterName,
string instanceName, string logName, string live, long? seconds)
{
iModsDBRepository modsDB = new iModsDBRepository();
List<MachineInfo> theMac = modsDB.GetMachineByName(macName);
if (theMac.Count == 0)
return new List<LogInfo>();
else if (instanceName == null)
{
if (!PerformanceCounterCategory.Exists(categoryName, macName) ||
!PerformanceCounterCategory.CounterExists(counterName, categoryName, macName) )
{
return new List<LogInfo>();
}
}
else if (instanceName != null)
{
if (!PerformanceCounterCategory.Exists(categoryName, macName) ||
!PerformanceCounterCategory.CounterExists(counterName, categoryName, macName) ||
!PerformanceCounterCategory.InstanceExists(instanceName, categoryName, macName))
{
return new List<LogInfo>();
}
}
else if (logName == null)
{
return new List<LogInfo>();
}
// Check if entered log name is a duplicate for the authenticated user
List<LogInfo> checkDuplicateLog = this.GetSingleLog(logName);
if (checkDuplicateLog.Count > 0)
{
return new List<LogInfo>();
}
PerformanceCounterCategory category = new PerformanceCounterCategory(categoryName, theMac[0].MachineName);
if (category.CategoryName == null || category.MachineName == null)
{
return new List<LogInfo>();
}
List<LogInfo> logIt = new List<LogInfo>();
if (category.CategoryType != PerformanceCounterCategoryType.SingleInstance)
{
List<InstanceInfo> instances = modsDB.GetInstancesFromCatMacName(theMac[0].MachineName, category.CategoryName);
foreach (InstanceInfo inst in instances)
{
if (!category.InstanceExists(inst.InstanceName))
{
continue;
}
else if (inst.InstanceName.Equals(instanceName, StringComparison.OrdinalIgnoreCase))
{
PerformanceCounter perfCounter = new PerformanceCounter(categoryName, counterName,
inst.InstanceName, theMac[0].MachineName);
//CounterSample data = perfCounter.NextSample();
//double value = CounterSample.Calculate(data, perfCounter.NextSample());
string data = "";
List<UserInfo> currUser = this.GetUserByName(WindowsIdentity.GetCurrent().Name);
string timeStarted = DateTime.Now.ToString("MM/dd/yyyy - h:mm:ss tt");
//string[] dataValues = new string[(int)seconds];
List<string> dataValues = new List<string>();
var hubConnection = new HubConnection("http://localhost/PerfMon2/");
hubConnection.Credentials = CredentialCache.DefaultNetworkCredentials;
var perfMon = hubConnection.CreateProxy("LiveHub");
// perfMon.On("sendValue", message => Console.WriteLine(message));
perfMon.On("showValue", json => Console.WriteLine(json));
hubConnection.Start().Wait();
List<DataValueInfo> lol = new List<DataValueInfo>();
for (int i = 0; i < seconds; i++)
{
data = "Value " + i + ": " + perfCounter.NextValue().ToString();
//dataValues[i] = data;
dataValues.Add(data);
lol.Add(new DataValueInfo
{
Value = perfCounter.NextValue().ToString()
});
// perfMon.Invoke<List<DataValueInfo>>("Send", lol);
perfMon.Invoke("SendToClient", lol);
Thread.Sleep(1000);
}
string timeFinished = DateTime.Now.ToString("MM/dd/yyyy - h:mm:ss tt");
Log log = new Log
{
LogName = logName,
CounterName = perfCounter.CounterName,
InstanceName = perfCounter.InstanceName,
CategoryName = perfCounter.CategoryName,
MachineName = perfCounter.MachineName,
TimeStarted = timeStarted,
TimeFinished = timeFinished,
PerformanceData = string.Join(",", dataValues),
UserID = currUser[0].UserID
};
this.CreateLog(log);
logIt.Add(new LogInfo
{
LogName = logName,
CounterName = perfCounter.CounterName,
InstanceName = perfCounter.InstanceName,
CategoryName = perfCounter.CategoryName,
MachineName = perfCounter.MachineName,
TimeStarted = timeStarted,
TimeFinished = timeFinished,
PerformanceData = dataValues.ToList<string>()
});
break;
}
}
}
else
{
PerformanceCounter perfCounter = new PerformanceCounter(categoryName, counterName,
"", theMac[0].MachineName);
string data = "";
List<UserInfo> currUser = this.GetUserByName(WindowsIdentity.GetCurrent().Name);
string timeStarted = DateTime.Now.ToString("MM/dd/yyyy - h:mm:ss tt");
//string[] dataValues = new string[(int)seconds];
List<string> dataValues = new List<string>();
var hubConnection = new HubConnection("http://localhost/PerfMon2/");
hubConnection.Credentials = CredentialCache.DefaultNetworkCredentials;
var perfMon = hubConnection.CreateProxy("LiveHub");
// perfMon.On("sendValue", message => Console.WriteLine(message));
perfMon.On("showValue", json => Console.WriteLine(json));
hubConnection.Start().Wait();
List<DataValueInfo> lol = new List<DataValueInfo>();
for (int i = 0; i < seconds; i++)
{
data = "Value " + i + ": " + perfCounter.NextValue().ToString();
//dataValues[i] = data;
dataValues.Add(data);
lol.Add(new DataValueInfo
{
Value = perfCounter.NextValue().ToString()
});
// perfMon.Invoke<List<DataValueInfo>>("Send", lol);
perfMon.Invoke("SendToClient", lol);
Thread.Sleep(1000);
}
string timeFinished = DateTime.Now.ToString("MM/dd/yyyy - h:mm:ss tt");
Log log = new Log
{
LogName = logName,
CounterName = perfCounter.CounterName,
InstanceName = perfCounter.InstanceName,
CategoryName = perfCounter.CategoryName,
MachineName = perfCounter.MachineName,
TimeStarted = timeStarted,
TimeFinished = timeFinished,
PerformanceData = string.Join(",", dataValues),
UserID = currUser[0].UserID
};
this.CreateLog(log);
logIt.Add(new LogInfo
{
LogName = logName,
CounterName = perfCounter.CounterName,
InstanceName = perfCounter.InstanceName,
CategoryName = perfCounter.CategoryName,
MachineName = perfCounter.MachineName,
TimeStarted = timeStarted,
TimeFinished = timeFinished,
PerformanceData = dataValues.ToList<string>()
});
}
return logIt;
}
Here is the controller for the method in LogController.cs :
[AcceptVerbs("GET", "POST")]
public List<LogInfo> Log_Perf_Data(string machine_name, string category_name, string counter_name, string instance_name,
string log_name, long? seconds, string live, string enforceQuery)
{
LogController.CheckUser();
// POST api/log/post_data?machine_name=&category_name=&counter_name=&instance_name=&log_name=&seconds=
if (machine_name != null && category_name != null && counter_name != null && log_name != null && seconds.HasValue && enforceQuery == null)
{
List<LogInfo> dataVal = logDB.LogTimedPerfData(machine_name, category_name, counter_name, instance_name,
log_name, live, seconds);
logDB.SaveChanges();
return dataVal;
}
return new List<LogInfo>();
}
Maybe you can implement it in push technique. Here is how I do it:
Class with message
public class Message
{
/// <summary>
/// The name who will receive this message.
/// </summary>
public string RecipientName { get; set; }
/// <summary>
/// The message content.
/// </summary>
public string MessageContent { get; set; }
}
Class that will represent client:
public class Client
{
private ManualResetEvent messageEvent = new ManualResetEvent(false);
private Queue<Message> messageQueue = new Queue<Message>();
/// <summary>
/// This method is called by a sender to send a message to this client.
/// </summary>
/// <param name="message">the new message</param>
public void EnqueueMessage(Message message)
{
lock (messageQueue)
{
messageQueue.Enqueue(message);
// Set a new message event.
messageEvent.Set();
}
}
/// <summary>
/// This method is called by the client to receive messages from the message queue.
/// If no message, it will wait until a new message is inserted.
/// </summary>
/// <returns>the unread message</returns>
public Message DequeueMessage()
{
// Wait until a new message.
messageEvent.WaitOne();
lock (messageQueue)
{
if (messageQueue.Count == 1)
{
messageEvent.Reset();
}
return messageQueue.Dequeue();
}
}
}
Class to send messages to clients:
public class ClientAdapter
{
/// <summary>
/// The recipient list.
/// </summary>
private Dictionary<string, Client> recipients = new Dictionary<string,Client>();
/// <summary>
/// Send a message to a particular recipient.
/// </summary>
public void SendMessage(Message message)
{
if (recipients.ContainsKey(message.RecipientName))
{
Client client = recipients[message.RecipientName];
client.EnqueueMessage(message);
}
}
/// <summary>
/// Called by a individual recipient to wait and receive a message.
/// </summary>
/// <returns>The message content</returns>
public string GetMessage(string userName)
{
string messageContent = string.Empty;
if (recipients.ContainsKey(userName))
{
Client client = recipients[userName];
messageContent = client.DequeueMessage().MessageContent;
}
return messageContent;
}
/// <summary>
/// Join a user to the recipient list.
/// </summary>
public void Join(string userName)
{
recipients[userName] = new Client();
}
/// <summary>
/// Singleton pattern.
/// This pattern will ensure there is only one instance of this class in the system.
/// </summary>
public static ClientAdapter Instance = new ClientAdapter();
private ClientAdapter() { }
}
Sending messages:
Message message = new Message
{
RecipientName = tbRecipientName.Text.Trim(),
MessageContent = tbMessageContent.Text.Trim()
};
if (!string.IsNullOrWhiteSpace(message.RecipientName) && !string.IsNullOrEmpty(message.MessageContent))
{
// Call the client adapter to send the message to the particular recipient instantly.
ClientAdapter.Instance.SendMessage(message);
}
Receive messages (this is JavaScript functions written in test page. They render content of the message on ASPX page. Here you should implement your logic):
// This method will persist a http request and wait for messages.
function waitEvent() {
CSASPNETReverseAJAX.Dispatcher.WaitMessage("<%= Session["userName"] %>",
function (result) {
displayMessage(result);
// Keep looping.
setTimeout(waitEvent, 0);
}, function () {
// Keep looping.
setTimeout(waitEvent, 0);
});
}
// Append a message content to the result panel.
function displayMessage(message) {
var panel = document.getElementById("<%= lbMessages.ClientID %>");
panel.innerHTML += currentTime() + ": " + message + "<br />";
}
// Return a current time string.
function currentTime() {
var currentDate = new Date();
return currentDate.getHours() + ":" + currentDate.getMinutes() + ":" + currentDate.getSeconds();
}
I want to track users who have read my mails.I am doing this but it's not working
I am sending mails to myself in outlook.
Here is my code which sends mails
try
{
string emailTemplateBody = "Hy this is test mail";
emailTemplateBody += "<tr><img src=''http://localhost:52583/HttpModule_using_beacon_images/images/<keyvalue>.aspx'' style=''opacity:0.0; filter:alpha(opacity=0);'' /></tr>";
string templateName = txtTemplateName.Text;
string toEmail = mymailaddress
//// Get unique Key after registring mail to be sent
string key = bl_email_calls.RegisterSystemEmailAudit("1", templateName, DateTime.Now);
emailTemplateBody = emailTemplateBody.Replace("<keyvalue>", key);
//// sending e-mail
bl_email_calls.SendMailMessage(toEmail, templateName, emailTemplateBody, key);
using (var cn = new SqlConnection(ConfigurationManager.ConnectionStrings["webConnectionString"].ToString()))
{
//code to insert record in database; }
Response.Write("Mail sent");
// return false;
}
catch (Exception ex)
{
throw;
}
Here is my HTTP module i have used from http://www.aspnetemail.com/samples/emailtracker/default.aspx[^]
public class HttpModuleClass : IHttpModule
{
//public event EventHandler BeginRequest;
public void Dispose()
{
}
/// <summary>
/// public varibles
/// </summary>
string footerFile = "~/images/footer.png";
//string footerFile = "~/images/ajax-loader.gif";
Email_Calls bl_email_calls = new Email_Calls();
/// <summary>
/// Init methoed
/// </summary>
/// <param name="context"></param>
public void Init(HttpApplication context)
{
context.BeginRequest += new System.EventHandler(GetImage_BeginRequest);
}
/// <summary>
/// handles requests made to server and call update email read time
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
public void GetImage_BeginRequest(object sender, System.EventArgs args)
{
//cast the sender to a HttpApplication object
System.Web.HttpApplication application = (System.Web.HttpApplication)sender;
string url = application.Request.Path; //get the url path
//string pattern = #"/HttpModule/images/(?<key>.*)\.aspx";
//string pattern = #"/HttpModule_using_beacon_images/images/(?<key>.*)\.aspx";
string pattern = #"/HttpModule_using_beacon_images/images/(?<key>.*)\.aspx";
//string pattern = #"~/images/(?<key>.*)\.aspx";
//create the regex to match for beacon images
Regex r = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
if (r.IsMatch(url))
{
MatchCollection mc = r.Matches(url);
if ((mc != null) && (mc.Count > 0))
{
string key = (mc[0].Groups["key"].Value);
bl_email_calls.UpdateSystemEmailAuditReadDate(key);
}
//now send the REAL image to the client
//application.Response.ContentType = "image/gif";
application.Response.ContentType = "image/png";
application.Response.WriteFile(application.Request.MapPath(footerFile));
//end the response
application.Response.End();
}
}
}
To request a read receipt, we need add a custom header named 'Disposition-Notification-To'
in this example, read receipts will go back to 'someaddress#mydomain.com'
it's important to note that read receipts will only be sent by those mail clients that
a) support them
and
b)have them enabled.
//Add "Disposition-Notification-To" for Read receipt
mail.Headers.Add("Disposition-Notification-To", "<mail#yahoo.com>");
I got it. I was making some little mistakes.
Actually I was saving the email body into the database so I had to use '' instead of ' and that was making all the trouble. When is removed '' it worked fine.
I am having issue with cache-control. I have one IIS website with multiple host headers. When you browse site number 1 then cache will be set for this site, when you open browser again and go to 2nd site you will see content from first site. How can I determine cache content based on the site user visits? Everything working fine when you have 1 site and host header related to SAME site.
//Set Cacheability
if (!Context.User.Identity.IsAuthenticated && _activeNode.CacheDuration > 0)
{
var eTag = GetETag(_activeNode);
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.Public);
if (IsClientCached(_activeNode.UpdateTimestamp))
{
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.StatusCode = (int)HttpStatusCode.NotModified;
HttpContext.Current.Response.SuppressContent = true;
HttpContext.Current.Response.End();
return;
}
var incomingEtag = HttpContext.Current.Request.Headers["If-None-Match"];
if (String.Compare(incomingEtag, eTag) == 0)
{
HttpContext.Current.Response.StatusCode = (int)HttpStatusCode.NotModified;
HttpContext.Current.Response.SuppressContent = true;
HttpContext.Current.Response.End();
return;
}
HttpContext.Current.Response.Cache.SetExpires(DateTime.Now.ToUniversalTime().AddMinutes(_activeNode.CacheDuration));
HttpContext.Current.Response.Cache.SetMaxAge(new TimeSpan(0, _activeNode.CacheDuration, 0));
HttpContext.Current.Response.Cache.SetLastModified(_activeNode.UpdateTimestamp);
HttpContext.Current.Response.Cache.SetETag(eTag);
}
/// <summary>
/// Gets the ETag.
/// </summary>
/// <param name="node">The node.</param>
/// <returns></returns>
private static string GetETag(Node node)
{
var etag = String.Format("{0}_{1}", node.Site.Id, node.Id);
return "\"" + Encryption.StringToMD5Hash(etag).Replace("-", null) + "\"";
}
/// <summary>
/// Determines whether [is client cached] [the specified content modified].
/// </summary>
/// <param name="contentModified">The content modified.</param>
/// <returns>
/// <c>true</c> if [is client cached] [the specified content modified]; otherwise, <c>false</c>.
/// </returns>
private bool IsClientCached(DateTime contentModified)
{
var header = Request.Headers["If-Modified-Since"];
if (header != null)
{
DateTime isModifiedSince;
if (DateTime.TryParse(header, out isModifiedSince))
{
return isModifiedSince > contentModified;
}
}
return false;
}
Sounds like you should add the host header value to your IsClientCached algorithm
I am developing a wizard for a machine that is to be used as a backup of other machines. When it replaces an existing machine, it needs to set its IP address, DNS, WINS, and host name to match the machine being replaced.
Is there a library in .net (C#) which allows me to do this programatically?
There are multiple NICs, each which need to be set individually.
EDIT
Thank you TimothyP for your example. It got me moving on the right track and the quick reply was awesome.
Thanks balexandre. Your code is perfect. I was in a rush and had already adapted the example TimothyP linked to, but I would have loved to have had your code sooner.
I've also developed a routine using similar techniques for changing the computer name. I'll post it in the future so subscribe to this questions RSS feed if you want to be informed of the update. I may get it up later today or on Monday after a bit of cleanup.
Just made this in a few minutes:
using System;
using System.Management;
namespace WindowsFormsApplication_CS
{
class NetworkManagement
{
public void setIP(string ip_address, string subnet_mask)
{
ManagementClass objMC =
new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection objMOC = objMC.GetInstances();
foreach (ManagementObject objMO in objMOC)
{
if ((bool)objMO["IPEnabled"])
{
ManagementBaseObject setIP;
ManagementBaseObject newIP =
objMO.GetMethodParameters("EnableStatic");
newIP["IPAddress"] = new string[] { ip_address };
newIP["SubnetMask"] = new string[] { subnet_mask };
setIP = objMO.InvokeMethod("EnableStatic", newIP, null);
}
}
}
public void setGateway(string gateway)
{
ManagementClass objMC = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection objMOC = objMC.GetInstances();
foreach (ManagementObject objMO in objMOC)
{
if ((bool)objMO["IPEnabled"])
{
ManagementBaseObject setGateway;
ManagementBaseObject newGateway =
objMO.GetMethodParameters("SetGateways");
newGateway["DefaultIPGateway"] = new string[] { gateway };
newGateway["GatewayCostMetric"] = new int[] { 1 };
setGateway = objMO.InvokeMethod("SetGateways", newGateway, null);
}
}
}
public void setDNS(string NIC, string DNS)
{
ManagementClass objMC = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection objMOC = objMC.GetInstances();
foreach (ManagementObject objMO in objMOC)
{
if ((bool)objMO["IPEnabled"])
{
// if you are using the System.Net.NetworkInformation.NetworkInterface
// you'll need to change this line to
// if (objMO["Caption"].ToString().Contains(NIC))
// and pass in the Description property instead of the name
if (objMO["Caption"].Equals(NIC))
{
ManagementBaseObject newDNS =
objMO.GetMethodParameters("SetDNSServerSearchOrder");
newDNS["DNSServerSearchOrder"] = DNS.Split(',');
ManagementBaseObject setDNS =
objMO.InvokeMethod("SetDNSServerSearchOrder", newDNS, null);
}
}
}
}
public void setWINS(string NIC, string priWINS, string secWINS)
{
ManagementClass objMC = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection objMOC = objMC.GetInstances();
foreach (ManagementObject objMO in objMOC)
{
if ((bool)objMO["IPEnabled"])
{
if (objMO["Caption"].Equals(NIC))
{
ManagementBaseObject setWINS;
ManagementBaseObject wins =
objMO.GetMethodParameters("SetWINSServer");
wins.SetPropertyValue("WINSPrimaryServer", priWINS);
wins.SetPropertyValue("WINSSecondaryServer", secWINS);
setWINS = objMO.InvokeMethod("SetWINSServer", wins, null);
}
}
}
}
}
}
Refactored the code from balexandre a little so objects gets disposed and the new language features of C# 3.5+ are used (Linq, var, etc). Also renamed the variables to more meaningful names. I also merged some of the functions to be able to do more configuration with less WMI interaction. I removed the WINS code as I don't need to configure WINS anymore. Feel free to add the WINS code if you need it.
For the case anybody likes to use the refactored/modernized code I put it back into the community here.
/// <summary>
/// Helper class to set networking configuration like IP address, DNS servers, etc.
/// </summary>
public class NetworkConfigurator
{
/// <summary>
/// Set's a new IP Address and it's Submask of the local machine
/// </summary>
/// <param name="ipAddress">The IP Address</param>
/// <param name="subnetMask">The Submask IP Address</param>
/// <param name="gateway">The gateway.</param>
/// <remarks>Requires a reference to the System.Management namespace</remarks>
public void SetIP(string ipAddress, string subnetMask, string gateway)
{
using (var networkConfigMng = new ManagementClass("Win32_NetworkAdapterConfiguration"))
{
using (var networkConfigs = networkConfigMng.GetInstances())
{
foreach (var managementObject in networkConfigs.Cast<ManagementObject>().Where(managementObject => (bool)managementObject["IPEnabled"]))
{
using (var newIP = managementObject.GetMethodParameters("EnableStatic"))
{
// Set new IP address and subnet if needed
if ((!String.IsNullOrEmpty(ipAddress)) || (!String.IsNullOrEmpty(subnetMask)))
{
if (!String.IsNullOrEmpty(ipAddress))
{
newIP["IPAddress"] = new[] { ipAddress };
}
if (!String.IsNullOrEmpty(subnetMask))
{
newIP["SubnetMask"] = new[] { subnetMask };
}
managementObject.InvokeMethod("EnableStatic", newIP, null);
}
// Set mew gateway if needed
if (!String.IsNullOrEmpty(gateway))
{
using (var newGateway = managementObject.GetMethodParameters("SetGateways"))
{
newGateway["DefaultIPGateway"] = new[] { gateway };
newGateway["GatewayCostMetric"] = new[] { 1 };
managementObject.InvokeMethod("SetGateways", newGateway, null);
}
}
}
}
}
}
}
/// <summary>
/// Set's the DNS Server of the local machine
/// </summary>
/// <param name="nic">NIC address</param>
/// <param name="dnsServers">Comma seperated list of DNS server addresses</param>
/// <remarks>Requires a reference to the System.Management namespace</remarks>
public void SetNameservers(string nic, string dnsServers)
{
using (var networkConfigMng = new ManagementClass("Win32_NetworkAdapterConfiguration"))
{
using (var networkConfigs = networkConfigMng.GetInstances())
{
foreach (var managementObject in networkConfigs.Cast<ManagementObject>().Where(objMO => (bool)objMO["IPEnabled"] && objMO["Caption"].Equals(nic)))
{
using (var newDNS = managementObject.GetMethodParameters("SetDNSServerSearchOrder"))
{
newDNS["DNSServerSearchOrder"] = dnsServers.Split(',');
managementObject.InvokeMethod("SetDNSServerSearchOrder", newDNS, null);
}
}
}
}
}
}
I like the WMILinq solution. While not exactly the solution to your problem, find below a taste of it :
using (WmiContext context = new WmiContext(#"\\.")) {
context.ManagementScope.Options.Impersonation = ImpersonationLevel.Impersonate;
context.Log = Console.Out;
var dnss = from nic in context.Source<Win32_NetworkAdapterConfiguration>()
where nic.IPEnabled
select nic;
var ips = from s in dnss.SelectMany(dns => dns.DNSServerSearchOrder)
select IPAddress.Parse(s);
}
http://www.codeplex.com/linq2wmi
A far more clear solution is to use the command netsh to change the IP (or setting it back to DHCP)
netsh interface ip set address "Local Area Connection" static 192.168.0.10 255.255.255.0
Where "Local Area Connection" is the name of the network adapter. You could find it in the windows Network Connections, sometimes it is simply named "Ethernet".
Here are two methods to set the IP and also to set the IP back to DHCP "Obtain an IP address automatically"
public bool SetIP(string networkInterfaceName, string ipAddress, string subnetMask, string gateway = null)
{
var networkInterface = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(nw => nw.Name == networkInterfaceName);
var ipProperties = networkInterface.GetIPProperties();
var ipInfo = ipProperties.UnicastAddresses.FirstOrDefault(ip => ip.Address.AddressFamily == AddressFamily.InterNetwork);
var currentIPaddress = ipInfo.Address.ToString();
var currentSubnetMask = ipInfo.IPv4Mask.ToString();
var isDHCPenabled = ipProperties.GetIPv4Properties().IsDhcpEnabled;
if (!isDHCPenabled && currentIPaddress == ipAddress && currentSubnetMask == subnetMask)
return true; // no change necessary
var process = new Process
{
StartInfo = new ProcessStartInfo("netsh", $"interface ip set address \"{networkInterfaceName}\" static {ipAddress} {subnetMask}" + (string.IsNullOrWhiteSpace(gateway) ? "" : $"{gateway} 1")) { Verb = "runas" }
};
process.Start();
var successful = process.ExitCode == 0;
process.Dispose();
return successful;
}
public bool SetDHCP(string networkInterfaceName)
{
var networkInterface = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(nw => nw.Name == networkInterfaceName);
var ipProperties = networkInterface.GetIPProperties();
var isDHCPenabled = ipProperties.GetIPv4Properties().IsDhcpEnabled;
if (isDHCPenabled)
return true; // no change necessary
var process = new Process
{
StartInfo = new ProcessStartInfo("netsh", $"interface ip set address \"{networkInterfaceName}\" dhcp") { Verb = "runas" }
};
process.Start();
var successful = process.ExitCode == 0;
process.Dispose();
return successful;
}
A slightly more concise example that builds on top of the other answers here. I leveraged the code generation that is shipped with Visual Studio to remove most of the extra invocation code and replaced it with typed objects instead.
using System;
using System.Management;
namespace Utils
{
class NetworkManagement
{
/// <summary>
/// Returns a list of all the network interface class names that are currently enabled in the system
/// </summary>
/// <returns>list of nic names</returns>
public static string[] GetAllNicDescriptions()
{
List<string> nics = new List<string>();
using (var networkConfigMng = new ManagementClass("Win32_NetworkAdapterConfiguration"))
{
using (var networkConfigs = networkConfigMng.GetInstances())
{
foreach (var config in networkConfigs.Cast<ManagementObject>()
.Where(mo => (bool)mo["IPEnabled"])
.Select(x=> new NetworkAdapterConfiguration(x)))
{
nics.Add(config.Description);
}
}
}
return nics.ToArray();
}
/// <summary>
/// Set's the DNS Server of the local machine
/// </summary>
/// <param name="nicDescription">The full description of the network interface class</param>
/// <param name="dnsServers">Comma seperated list of DNS server addresses</param>
/// <remarks>Requires a reference to the System.Management namespace</remarks>
public static bool SetNameservers(string nicDescription, string[] dnsServers, bool restart = false)
{
using (ManagementClass networkConfigMng = new ManagementClass("Win32_NetworkAdapterConfiguration"))
{
using (ManagementObjectCollection networkConfigs = networkConfigMng.GetInstances())
{
foreach (ManagementObject mboDNS in networkConfigs.Cast<ManagementObject>().Where(mo => (bool)mo["IPEnabled"] && (string)mo["Description"] == nicDescription))
{
// NAC class was generated by opening a developer console and entering:
// mgmtclassgen Win32_NetworkAdapterConfiguration -p NetworkAdapterConfiguration.cs
// See: http://blog.opennetcf.com/2008/06/24/disableenable-network-connections-under-vista/
using (NetworkAdapterConfiguration config = new NetworkAdapterConfiguration(mboDNS))
{
if (config.SetDNSServerSearchOrder(dnsServers) == 0)
{
RestartNetworkAdapter(nicDescription);
}
}
}
}
}
return false;
}
/// <summary>
/// Restarts a given Network adapter
/// </summary>
/// <param name="nicDescription">The full description of the network interface class</param>
public static void RestartNetworkAdapter(string nicDescription)
{
using (ManagementClass networkConfigMng = new ManagementClass("Win32_NetworkAdapter"))
{
using (ManagementObjectCollection networkConfigs = networkConfigMng.GetInstances())
{
foreach (ManagementObject mboDNS in networkConfigs.Cast<ManagementObject>().Where(mo=> (string)mo["Description"] == nicDescription))
{
// NA class was generated by opening dev console and entering
// mgmtclassgen Win32_NetworkAdapter -p NetworkAdapter.cs
using (NetworkAdapter adapter = new NetworkAdapter(mboDNS))
{
adapter.Disable();
adapter.Enable();
Thread.Sleep(4000); // Wait a few secs until exiting, this will give the NIC enough time to re-connect
return;
}
}
}
}
}
/// <summary>
/// Get's the DNS Server of the local machine
/// </summary>
/// <param name="nicDescription">The full description of the network interface class</param>
public static string[] GetNameservers(string nicDescription)
{
using (var networkConfigMng = new ManagementClass("Win32_NetworkAdapterConfiguration"))
{
using (var networkConfigs = networkConfigMng.GetInstances())
{
foreach (var config in networkConfigs.Cast<ManagementObject>()
.Where(mo => (bool)mo["IPEnabled"] && (string)mo["Description"] == nicDescription)
.Select( x => new NetworkAdapterConfiguration(x)))
{
return config.DNSServerSearchOrder;
}
}
}
return null;
}
/// <summary>
/// Set's a new IP Address and it's Submask of the local machine
/// </summary>
/// <param name="nicDescription">The full description of the network interface class</param>
/// <param name="ipAddresses">The IP Address</param>
/// <param name="subnetMask">The Submask IP Address</param>
/// <param name="gateway">The gateway.</param>
/// <remarks>Requires a reference to the System.Management namespace</remarks>
public static void SetIP(string nicDescription, string[] ipAddresses, string subnetMask, string gateway)
{
using (var networkConfigMng = new ManagementClass("Win32_NetworkAdapterConfiguration"))
{
using (var networkConfigs = networkConfigMng.GetInstances())
{
foreach (var config in networkConfigs.Cast<ManagementObject>()
.Where(mo => (bool)mo["IPEnabled"] && (string)mo["Description"] == nicDescription)
.Select( x=> new NetworkAdapterConfiguration(x)))
{
// Set the new IP and subnet masks if needed
config.EnableStatic(ipAddresses, Array.ConvertAll(ipAddresses, _ => subnetMask));
// Set mew gateway if needed
if (!String.IsNullOrEmpty(gateway))
{
config.SetGateways(new[] {gateway}, new ushort[] {1});
}
}
}
}
}
}
}
Full source:
https://github.com/sverrirs/DnsHelper/blob/master/src/DnsHelperUI/NetworkManagement.cs
The existing answers have quite broken code. The DNS method does not work at all. Here is code that I used to configure my NIC:
public static class NetworkConfigurator
{
/// <summary>
/// Set's a new IP Address and it's Submask of the local machine
/// </summary>
/// <param name="ipAddress">The IP Address</param>
/// <param name="subnetMask">The Submask IP Address</param>
/// <param name="gateway">The gateway.</param>
/// <param name="nicDescription"></param>
/// <remarks>Requires a reference to the System.Management namespace</remarks>
public static void SetIP(string nicDescription, string[] ipAddresses, string subnetMask, string gateway)
{
using (var networkConfigMng = new ManagementClass("Win32_NetworkAdapterConfiguration"))
{
using (var networkConfigs = networkConfigMng.GetInstances())
{
foreach (var managementObject in networkConfigs.Cast<ManagementObject>().Where(mo => (bool)mo["IPEnabled"] && (string)mo["Description"] == nicDescription))
{
using (var newIP = managementObject.GetMethodParameters("EnableStatic"))
{
// Set new IP address and subnet if needed
if (ipAddresses != null || !String.IsNullOrEmpty(subnetMask))
{
if (ipAddresses != null)
{
newIP["IPAddress"] = ipAddresses;
}
if (!String.IsNullOrEmpty(subnetMask))
{
newIP["SubnetMask"] = Array.ConvertAll(ipAddresses, _ => subnetMask);
}
managementObject.InvokeMethod("EnableStatic", newIP, null);
}
// Set mew gateway if needed
if (!String.IsNullOrEmpty(gateway))
{
using (var newGateway = managementObject.GetMethodParameters("SetGateways"))
{
newGateway["DefaultIPGateway"] = new[] { gateway };
newGateway["GatewayCostMetric"] = new[] { 1 };
managementObject.InvokeMethod("SetGateways", newGateway, null);
}
}
}
}
}
}
}
/// <summary>
/// Set's the DNS Server of the local machine
/// </summary>
/// <param name="nic">NIC address</param>
/// <param name="dnsServers">Comma seperated list of DNS server addresses</param>
/// <remarks>Requires a reference to the System.Management namespace</remarks>
public static void SetNameservers(string nicDescription, string[] dnsServers)
{
using (var networkConfigMng = new ManagementClass("Win32_NetworkAdapterConfiguration"))
{
using (var networkConfigs = networkConfigMng.GetInstances())
{
foreach (var managementObject in networkConfigs.Cast<ManagementObject>().Where(mo => (bool)mo["IPEnabled"] && (string)mo["Description"] == nicDescription))
{
using (var newDNS = managementObject.GetMethodParameters("SetDNSServerSearchOrder"))
{
newDNS["DNSServerSearchOrder"] = dnsServers;
managementObject.InvokeMethod("SetDNSServerSearchOrder", newDNS, null);
}
}
}
}
}
}
This maybe more clear:
static NetworkInterface GetNetworkInterface(string macAddress)
{
foreach(NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
if (macAddress == ni.GetPhysicalAddress().ToString())
return ni;
}
return null;
}
static ManagementObject GetNetworkInterfaceManagementObject(string macAddress)
{
NetworkInterface ni = GetNetworkInterface(macAddress);
if (ni == null)
return null;
ManagementClass managementClass = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = managementClass.GetInstances();
foreach(ManagementObject mo in moc)
{
if (mo["settingID"].ToString() == ni.Id)
return mo;
}
return null;
}
static bool SetupNIC(string macAddress, string ip, string subnet, string gateway, string dns)
{
try
{
ManagementObject mo = GetNetworkInterfaceManagementObject(macAddress);
//Set IP
ManagementBaseObject mboIP = mo.GetMethodParameters("EnableStatic");
mboIP["IPAddress"] = new string[] { ip };
mboIP["SubnetMask"] = new string[] { subnet };
mo.InvokeMethod("EnableStatic", mboIP, null);
//Set Gateway
ManagementBaseObject mboGateway = mo.GetMethodParameters("SetGateways");
mboGateway["DefaultIPGateway"] = new string[] { gateway };
mboGateway["GatewayCostMetric"] = new int[] { 1 };
mo.InvokeMethod("SetGateways", mboGateway, null);
//Set DNS
ManagementBaseObject mboDNS = mo.GetMethodParameters("SetDNSServerSearchOrder");
mboDNS["DNSServerSearchOrder"] = new string[] { dns };
mo.InvokeMethod("SetDNSServerSearchOrder", mboDNS, null);
return true;
}
catch (Exception e)
{
return false;
}
}