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

External IP Windows Notification Service

4.87/5 (16 votes)
1 Nov 2014MIT4 min read 22.4K   878  
A Windows Service which sends an email notification when the external IP address has changed.

Introduction

Download ExternalIPChecker.zip

Download ExternalIPChecker-noexe.zip

What is external IP address?
An external IP address is the address assigned to you by your Internet Service Provider. IP address is what the other PCs can see from outside your LAN (Local Area Network). 

Image 1

It deepens by the ISP(Internet Service Provider) to set you a static external IP or in most cases like mine a dynamic one. 
    
In order to connect to a device inside your network, you will need to redirect the whole traffic (or just the traffic for the remote desktop connection or web server - the port you want) to the IP address of the device in the LAN. This is usually very easy setup in the ISP router.
    
You can see my setup of my SKY router. This should be very easy to configure and is not the main idea of the article.

Image 2

So what happens if the external IP has changed? - you can't access your local pc or device to which you have redirected the traffic, because you do not know the external IP address which you have to use. The article gives a solution of that problem by implementing a Windows Notification Service - a windows service which sends an email with the new IP address once it's changed.

Background

To get notified when the external IP is changed requires application that will run all the time, will check the external IP address and if there is a change will send an email notification. For that requirements, the best technology for Windows Based PC is the Windows Services. They can be configured to run on the start of the PC, they run on the background - so you will not notice any console app starting and stopping if we have chosen a console app which starts by schedule task alternative for example.

 

Using the code

To get the external IP address I am using a service. When you write in google "What's my IP" you will get a lot of results. You can switch to a different service, but this is what I am using:
    
http://checkip.dyndns.org/
    
I am using this code: 

public static string GetExternalIp()
{
    try
    {
       var 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; }

}

Which parses the response of the service.
    
I am calling that service on regular time intervals - every 30 min. This is a configuration in the .config file where the setting is in seconds.
    
To send an email, I am using my google account to login into their SMTP server with the SSL enabled feature. Some other SMTP doesn't support that so you can check and modify that option.
This is the code to send email:

public void SendResetEmail(string ipAddress)
{
   try
    {
           var email = new MailMessage
           {
               From = new MailAddress(ConfigurationManager.AppSettings["EmailAddressFrom"])
           };
    
           email.To.Add(new MailAddress(ConfigurationManager.AppSettings["EmailAddressTo"]));
           email.Subject = "External IP Changed!";
           email.IsBodyHtml = true;
           email.Body = "The IP Address is: " + ipAddress;
           var smtpClient = new SmtpClient
           {
                EnableSsl = true
           };
    
          smtpClient.Send(email);
     }
     catch (Exception ex)
     {
         Program.Logger.Log(ex, LoggerExt.LogExtType.Error);
     }
 }

The service is using a timer, which will fire an event on time intervals and do the check:
    

private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
      lock (_locker)
      {
         Program.Logger.Log("Elapsed", LoggerExt.LogExtType.Info);
         var externalIPAddress = IPHelper.GetExternalIp();
         Program.Logger.Log(externalIPAddress, LoggerExt.LogExtType.Debug);
         if (!string.IsNullOrEmpty(externalIPAddress) && externalIPAddress != IPHelper.ReadIPFromFile())
         {
               IPHelper.SaveIPToFile(externalIPAddress);
               SendResetEmail(externalIPAddress);
         }
    
     }
}


As you can see here we have a crytical section - only one use per time - not needed if the time interval between two checks is long enough. After getting the external IP address it compares with the one lastly we have stored in a file. If the IP addresses are different - then sends a notifications and saves the new IP address.
    

Points of interest

There are different ways to test a windows service. Some suggest to install the service to attach to the process and debug it. That of course is an option, but not the best one, because for every debug you will have to reinstall your service. Another option is to have special input parameters based on which you will start a thread with   while (true) Thread.Sleep(1000);

    
Example:
 

var hadler = new ExternalIPChecker();
    hadler.CallOnStart();
    
    while (true) Thread.Sleep(1000);//only while debug make the main thread to sleep infinitely

But the best option is to use the Debug directives:

#if DEBUG

                var hadler = new ExternalIPChecker();

                hadler.CallOnStart();

                while (true) Thread.Sleep(1000);//only while debug make the main thread to sleep infinitely

#else

           var servicesToRun = new ExternalIPChecker();

            ServiceBase.Run(servicesToRun);

#endif

 

When you switch from debug to release mode different sections of the code will be executed - no need for strange magic input parameters!

 

How To Install?

Build the service project in release mode. Copy the release folder in the bin folder to a place where will live an will not be moved (could create folder in Program Files). Then run the scrip in the command prompt:

>sc create "ServiceName" binpath= "the absolute path to the service exe"

Please note here one very annoying thing. binpath= "… should be exactly with that number of spaces. If you decided to write it binpath = "… will never work! That could take you quite some time to understand if you are just following the syntax without noticing this small details.
    
If you want to remove the service:
>sc delete "ServiceName"
    
If you want to do an update, just stop the service and copy and override the new files.
    
When you install the service change its configuration to auto start  - in the service preferences
    
    
If you want to notify more than one person - to send more email addresses - you can easyly specify all the IP addresses in the configuration using a special separator then parse them into an array and loop through them and send the email to all subscriber - all people that can access the service you provide from your local PC.
    
Hope this was helpful and easy to understand article!

 

 

License

This article, along with any associated source code and files, is licensed under The MIT License