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.
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.
This is accomplished by temporarily setting the IP and host-address to bogus values, like so:
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.
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:
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
:
private void InitializeComponent()
{
...
TrayIcon = new NotifyIcon();
TrayIcon.BalloonTipIcon = ToolTipIcon.Info;
TrayIcon.Text = "Double-Click to Set Current Task";
this.sTaskDesc = "";
this.bInTask = false;
TrayIcon.Icon = Properties.Resources.TrayIcon;
TrayIcon.DoubleClick += TrayIcon_DoubleClick;
TrayIcon.BalloonTipClicked += TrayIcon_BalloonTipClick;
TrayIconContextMenu = new ContextMenuStrip();
toolstripRequestTime = new ToolStripMenuItem();
toolstripClose = new ToolStripMenuItem();
TrayIconContextMenu.SuspendLayout();
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);
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:
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"))
{
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);
}
if (!String.IsNullOrEmpty(gateway))
{
using (var newGateway = managementObject.GetMethodParameters("SetGateways"))
{
newGateway["DefaultIPGateway"] = new[] { gateway };
newGateway["GatewayCostMetric"] = new[] { 1 };
managementObject.InvokeMethod("SetGateways", newGateway, null);
}
}
}
}
}
}
}
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);
}
}
}
}
This is the first beta release for PC-use only. Again, .NET Framework 4.0 should be installed.