Click here to Skip to main content
15,890,043 members
Articles / Programming Languages / C#

TaskTimer, Reducing Your Exposure to the Internet

Rate me:
Please Sign up or sign in to vote.
2.95/5 (7 votes)
17 Oct 2016CPOL4 min read 12.6K   296   9   7
A novel standalone tool to help limit computer-related distractions such as the internet, while promoting more healthy goal-driven behavior(s).

Introduction

Internet is a great tool, but it often distracts us. The same could be said of computer clutter in general -- all the icons and files in close proximity make it too easy for us to dart off into an unexpected adventure. TaskTimer is a tool to limit our exposure to the distractions by tempering our access to the internet and periodically reminding us to focus on a chosen task. It appears as a tray icon and is completely configured in one step by setting a desired nag message, the approximate frequency with which you'd like to see the nag message, and, finally, the target internet adapter (e.g. Wi-Fi) you'd like for the program to turn on and off, based on your needs.

Turning on TaskTimer will block all access to your immediate network, including your internet connection. Then, until you close the application, you will only be able to access the internet for the limited amount of time that you request for your internet goal. Likewise, there is additional functionality to encourage you to stay focused on non-internet goals as well. Exiting TaskTimer will re-enable your internet access.

Background

It is well known that webpages and advertisements are designed to maximize our exposure to marketing material. Users may not even notice how much time they engage with content they never planned to consume. The result is hours upon hours of wasted time every day--hours that could have been spent productively enhancing one's skill set or one's social connections. The first step in making changes for the better is to understand and accept this potential challenge.

Currently, there is no stand-alone solution to the problem of internet overindulgence. There are multiple websites that offer to keep track of your time online--even services that store a log of tasks you worked on--but these are still services, interested in keeping you online and not offline. TaskTimer takes the alternative approach that only freeware could take in that it asks for no contribution at all from the user. It respects the users decision about being offline, and enforces the user's intended goal of being online for only a limited amount of time, after which the internet gets shut off, prompting a re-examination of whether it's worth it for the user to continue browsing.

TaskTimer relies on two basic principles: having a plan and staying focused often increases productivity and nagging increases the likelihood we'll move forward with our goals. TaskTimer uses the less explored functionality of taskbar popup notifications--they are clickable--to create a more focused computer environment, gently reminding us to stick to one goal at a time or to stop browsing the internet when it's no longer necessary.

Image 1

Using the Code

Written in C# .NET Framework 4.0, the code for TaskTimer is attached as a Visual Studio project. Although currently fully-functional, it's highly likely that one may desire some additional feature(s), in which case they should feel free to change / enhance TaskTimer.

The core functionality uses System.Timers.Timer to monitor for changes every 15 seconds. Upon launching the application, ApplicationContext.cs stores the user's current internet configuration (IP address, etc.) into container class InternetDetails.cs. The user interface, Form.cs, displays the list of internet adapters in your computer that could be controlled by the program. The user is encouraged to store their settings before closing the initial popup window, although it is possible to close the UI and the program by selecting "Close Program" from the icon created in the task-bar. Pressing the "Save and Turn Off Internet" button will, indeed, turn off internet access.

Image 2

This is accomplished by temporarily setting the IP and host-address to bogus values, like so:

C#
Process cmd1 = new Process();
cmd1.StartInfo.FileName = "cmd.exe";
cmd1.StartInfo.RedirectStandardInput = true;
cmd1.StartInfo.RedirectStandardOutput = true;
cmd1.StartInfo.CreateNoWindow = true;
cmd1.StartInfo.UseShellExecute = false;

String sCmd = "netsh interface ip set address \"" + context.sActiveAdapter + 
              "\" static 192.168.1.100 255.255.255.0 192.168.0.254";
cmd1.StartInfo.Arguments = "/C " + sCmd;
cmd1.Start();
cmd1.WaitForExit();

Upon exiting the program or shutdown, previous internet settings are restored so that everything works again.

Adapting the Framework

As a typical tray application, TaskTimer lives in the system tray, relying on a hidden form to interact with the user when necessary. This is accomplished by starting the program with an intermediary application context class, called ApplicationContext.cs.

C#
 namespace TaskTimer
{
    static class Program
    {
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new ApplicationContext());
        }
    }
}

The main user-form is then launched from within ApplicationContext.cs:

C#
public ApplicationContext()
{
    Application.ApplicationExit += new EventHandler(this.OnApplicationExit);
    InitializeComponent();
    TrayIcon.Visible = true;
    bSettingsConfigured = false;
}

private void InitializeComponent()
{
    ...

    frm = new Form(this, iDetails);
    frm.Show();
}

Also of interest within InitializeComponent() is the general structure for creating Tray Icon applications, along with a way to remove the tray icon OnApplicationExit:

C#
 private void InitializeComponent()
 {

    ...
    TrayIcon = new NotifyIcon();

    TrayIcon.BalloonTipIcon = ToolTipIcon.Info;
    TrayIcon.Text = "Double-Click to Set Current Task";

    this.sTaskDesc = "";
    this.bInTask = false;
    //The icon is added to the project resources.
    TrayIcon.Icon = Properties.Resources.TrayIcon;

    //Optional - handle doubleclicks on the icon:
    TrayIcon.DoubleClick += TrayIcon_DoubleClick;
    TrayIcon.BalloonTipClicked += TrayIcon_BalloonTipClick;

    //////////////////
    // Context Menu //
    //////////////////
    TrayIconContextMenu = new ContextMenuStrip();
    toolstripRequestTime = new ToolStripMenuItem();
    toolstripClose = new ToolStripMenuItem();
    TrayIconContextMenu.SuspendLayout();

    // 
    // TrayIconContextMenu
    // 
    this.TrayIconContextMenu.Items.AddRange(new ToolStripItem[] {this.toolstripRequestTime});
    this.TrayIconContextMenu.Items.AddRange(new ToolStripItem[] {this.toolstripClose});
    this.TrayIconContextMenu.Name = "TrayIconContextMenu";
    this.TrayIconContextMenu.Size = new Size(153, 70);
    // 
    // toolstripRequestTime
    // 
    this.toolstripRequestTime.Name = "reqTime";
    this.toolstripRequestTime.Size = new Size(152, 22);
    this.toolstripRequestTime.Text = "Request Time";
    this.toolstripRequestTime.Click += new EventHandler(this.RequestTime_Click);

    this.toolstripClose.Name = "closProg";
    this.toolstripClose.Size = new Size(152, 22);
    this.toolstripClose.Text = "Close Program";
    this.toolstripClose.Click += new EventHandler(this.CloseProgram_Click);

    TrayIconContextMenu.ResumeLayout(false);
    TrayIcon.ContextMenuStrip = TrayIconContextMenu;

    ...
}

private void OnApplicationExit(object sender, EventArgs e)
{
    TrayIcon.Visible = false;
}

Points of Interest

Ideally, it would be much easier to accomplish this same purpose by simply enabling a proxy server and setting the address of that server. However, the following Chrome bug was discovered, making this approach impractical:

It was also discovered that Windows 7's shutdown process is not compatible with any kind of Process.* calls. To accommodate this popular operating system, WMI objects were used instead:

C#
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 new 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);
                        }
                    }
                }
            }
        }
    }
} // end SetIP

public void SetDHCP()
{
    using (var networkConfigMng = new ManagementClass("Win32_NetworkAdapterConfiguration"))
    {
        using (var networkConfigs = networkConfigMng.GetInstances())
        {
            foreach (var managementObject in networkConfigs.Cast<ManagementObject>().Where
                    (managementObject => (bool)managementObject["IPEnabled"]))
            {
                var ndns = managementObject.GetMethodParameters("SetDNSServerSearchOrder");
                ndns["DNSServerSearchOrder"] = null;

                managementObject.InvokeMethod("EnableDHCP", null, null);
                managementObject.InvokeMethod("SetDNSServerSearchOrder", ndns, null);
            }
        }
    }
} // end SetDHCP

This is the first beta release for PC-use only. Again, .NET Framework 4.0 should be installed.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
B.S. in Chemistry, minor in Math / Computer Science, background in UI principles.

Comments and Discussions

 
QuestionMinor improvement Pin
Nelek18-Oct-16 1:46
protectorNelek18-Oct-16 1:46 
AnswerRe: Minor improvement Pin
Moshe Morris18-Oct-16 8:38
Moshe Morris18-Oct-16 8:38 
GeneralRe: Minor improvement Pin
Nelek18-Oct-16 10:41
protectorNelek18-Oct-16 10:41 
GeneralMy vote of 5 Pin
Franc Morales14-Oct-16 19:21
Franc Morales14-Oct-16 19:21 
GeneralRe: My vote of 5 Pin
Moshe Morris15-Oct-16 6:08
Moshe Morris15-Oct-16 6:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.