Click here to Skip to main content
12,552,431 members (27,868 online)
Click here to Skip to main content
Add your own
alternative version


54 bookmarked

Internet Download Limiter

, 6 Jul 2010 CDDL
Rate this:
Please Sign up or sign in to vote.
How to set a download limit and disable a user's network connection.


For those who have a capped download broadband package and have children, this article may be a Godsend by showing a way to limit users' download ability by setting a daily download allowance.


So there I was, lecturing my children on the excess download charges our ISP had made again, when it occured to me that what I need is someway of limiting their download capacity. After searching the Web and asking in the CP forums, I came up with the idea for this little program.


The actual program, when running, creates a permanent, very small window on the user's desktop informing them of how much download capacity they have remaining.


Once the limit has been reached, the program informs the user that their limit has been reached and that their Internet access is now disabled.


Using the Code

I've tried to keep the program as simple as possible, and therefore the code itself has a relatively simple mode of operation. We use a performance counter (see for more information) to gather information on the number of bytes a network adapter has received.

' Instantiate our performance counter that will get the information we need.
downloadCounter = New PerformanceCounter("Network Interface", "Bytes Received/sec", nicName)

We then keep a running total, and if the running total exceeds a predetermined limit, we disable the user's network connection until the following day. It's as simple as that!

So, how do we implement all of this? How do we disable the user's internet connection I can hear you asking. Easy! We stop the DHCP service on the user's computer. Now, here's the rub: if you don't use dynamically allocated IP addresses from a DHCP server, stopping the client's DHCP service isn't going to make any difference; it won't disable their connection :-(

Private Sub StopService(ByVal service As String)

    Dim sc As ServiceController = New ServiceController(service)

    If sc.CanStop And sc.Status <> ServiceControllerStatus.Stopped Then
    End If
End Sub

To be able to gather the downloaded bytes and keep a running total, we create an event that is triggered every second and updates the latest download total. To create the trigger, we create a one second timer:

' Set the time interval for collecting the download data (milliseconds).
Dim myTimer As System.Timers.Timer = New System.Timers.Timer(1000)

We then create an Event Handler and point this to our Delegated collection Sub:

AddHandler myTimer.Elapsed, New ElapsedEventHandler(AddressOf timer_Elapsed)

This is where we get the update from:

Private Sub timer_Elapsed(ByVal sender As Object, ByVal e As ElapsedEventArgs)

    downloadBytes = downloadCounter.NextSample().RawValue
    regKey.SetValue("PreviouslyDownloadedBytes", downloadBytes, RegistryValueKind.DWord)

End Sub

Note: we also save a running total to the Registry. This is explained later.

We also use the timer.tick event to see if we have reached our download limit:

Private Sub TimerCounter_Tick(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles TimerCounter.Tick
    If Not disabled Then
        lblDownloadBytes.Text = ((tempDownloadLimit - downloadBytes) / 
             (1024 ^ 2)).ToString("###0.###") & " MBytes remaining"

        If downloadBytes > tempDownloadLimit Then

            ' We've reached our download limit.
            regKey.SetValue("Expired", True, RegistryValueKind.DWord)
            regKey.SetValue("PreviouslyDownloadedBytes", 0, RegistryValueKind.DWord)

            disabled = True

            lblDownloadBytes.Text = "Download Limit Reached, Internet Access Disabled."
        End If

        ' If we've reached the download limit, we stop the timer and remove the event handler
        ' that monitors the downloaded bytes.
        ' No point in monitoring anymore something that isn't happening! 
        ' We then rely on the AddressChanged sub to continue disabling the network should the
        ' user restart the dhcp service.
        RemoveHandler myTimer.Elapsed, AddressOf timer_Elapsed

    End If
End Sub

As the program stands, as described, it would be pretty trivial to circumvent and regain network access. So, we put in a few checks to help thwart circumvention. One of the first checks we perform is to see if the computer has been restarted thus resetting our performance counter.

As can be seen from the previous code block, we set a couple of Registry entries. One of these entries is 'Expired'. This is a boolean value that, if true, indicates that the download limit has been reached. We check to see if we have 'expired' on startup, and if we have, we disable the DHCP service straight away.

Another Registry setting we save, is the 'PreviouslyDownloadedBytes'. This is used in the event that the user restarts their computer and hasn't exhausted their download limit for that day. We subtract the PreviouslyDownloadedBytes figure from the limit we set, and this becomes the new download limit for the remainder of the day.

Case DateComparisonResult.TheSame
' We're running again on the same day. Check to make sure we've not expired.

If downloadLimitReached Then
    lblDownloadBytes.Text = "Download Limit Reached, Internet Access Disabled."
    disabled = True
    ' Adjust the download limit in case the computer has been restarted.
    tempDownloadLimit = maxDownloadLimit - previouslyDownloadedBytes
End If

Another check performed is to see if the user has moved the system clock forward thus resetting the download counter. One of our Registry entries saves the date on which we last ran, we then compare this date to the system's current date on startup to determine if we should give the user internet access. So that we can accurately determine if the system's clock is in fact correct, we query an NTP time server. DaveyM69 created a very detailed and useful CP article on querying time servers; see: for more information. I have modified Dave's original SNTPClient code to suit my own needs, and used this code to query a time server.

' First check to see if the dhcp service is running, if not, start it.
' We need network access to communicate with an NTP server to check that 
' the system clock hasn't been changed.
If Not IsServiceRunning(service) Then
End If

' Make sure the nic is connected to the network before querying
' the NTP server.
If My.Computer.Network.IsAvailable Then
    ntpServerDate = SntpClient.GetNow().ToShortDateString
End If

' Check whether the system clock has been changed.
If currentDate <> ntpServerDate Then
    ' System clock has been changed! Reset it.
    SntpClient.UpdateLocalDateTime = True
End If

The last check we make is to monitor the state of the IP address assigned to the NIC. If we have disabled the DHCP service and thus disabled the connection, and the NIC's IP address will be non-existent. We set up an event handler which notifies us if the NIC's IP address changes.

AddHandler NetworkChange.NetworkAddressChanged, AddressOf AddressChanged

We then use our delegated sub to disable the DHCP service again if the user re-enabled it.

Private Sub AddressChanged(ByVal sender As Object, ByVal e As EventArgs)

    ' We're notified here of an IP address change. If the network should have been
    ' disabled and we reach here, it means the user has restarted the dhcp service. 
    ' So we stop it again.
    If disabled Then
    End If

End Sub

So, there you have it ladies and gentlemen; how to simply disable a network connection after a predetermined number of bytes have been downloaded.

Points of Interest

Because the instantiation of the performance counter requires the name of the NIC, we use a WMI routine to get the NIC's name.

Private Function GetNetworkAdaptorName() As String

        ' Get the name of the nic that has an IP address associated with it.

        Dim nicName As String = ""

        Dim query As ManagementObjectSearcher = New ManagementObjectSearcher _
                            ("SELECT * FROM Win32_NetworkAdapterConfiguration " + 
                             "WHERE IPEnabled = TRUE")

        Dim queryCollection As ManagementObjectCollection = query.Get()
        Dim dhcpAddress() As String

        For Each mo As ManagementObject In queryCollection
            nicName = mo("Description").ToString.Trim
            dhcpAddress = CType(mo("IPAddress"), String())

            If dhcpAddress(0) <> "" Or dhcpAddress(0) <> "" Then
                ' Replace any forward slashes to underscores.
                ' Nvidia adaptors often have forward slashes
                ' in their NIC names which totally screws things up.
                If nicName.Contains("/"c) Then
                    nicName = nicName.Replace("/"c, "_"c)
                End If
                Exit For
            End If
        Return nicName
End Function

Although we try and filter the number of NICs returned by our WMI query by using the:


clause, we can sometimes get back more than one NIC. In this case, we check to see if the returned NIC has a DHCP server address associated with it.

We also use in the program a routine to start the DHCP service. One of the problems I found was that if you start the DHCP service and then try and use any network function immediately, the function would fail even though we wait explicitly for the service to start by using:


This is because, even though the service is running, it takes time for the DHCP server to allocate an IP address to the NIC. To keep things simple, I just added a 5 second delay before we use any network function.

Private Sub StartService(ByVal service As String)

    Dim sc As ServiceController = New ServiceController(service)

    If sc.Status <> ServiceControllerStatus.Running Then

            ' Even though we wait for the status of the dhcp service to change to
            ' Running, we have to pause to give the dhcp server time to allocate 
            ' an IP address to our Nic. 

        Catch ex As Exception
            lblDownloadBytes.Text = "Could Not Start DHCP Service"
        End Try
    End If

End Sub

Running the Program

To run the program on the user's system, put the executable out of the way somewhere, say 'Windows\system32', and then create a Registry entry in the HKLM\Software\Microsoft\Windows\CurrentVersion\Run Registry key to start the program.


Although the program works well on Windows XP and Windows 7, the user must be a member of the Administrators group. Additionally, on Vista, even if UAC is not disabled, UAC prompts will appear when starting and stopping the DHCP service and trying to change the system time.

To Do

I think, to overcome the running as admin and UAC problems, everything that doesn't display information to the user should become a Windows service with a separate GUI app that communicates with the service to display to the user their current download usage.

One other thing: if the user stops our app in the Task Manager, obviously we can't monitor download usage. I've been thinking about adding to the form closing event a routine that shuts down the user's computer if they stop our app. Also, it might be an idea integrating our app in such a way that if it's not running at startup, the NIC itself can't start; possibly by relying on our app to, say, start the NIC's driver.


  • 4th July 2010 - Initial version.
  • 5th July 2010 - Bug fix.


This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)


About the Author

United Kingdom United Kingdom
No Biography provided

You may also be interested in...


Comments and Discussions

GeneralMy vote of 2 Pin
i0021-May-13 17:22
member i0021-May-13 17:22 
GeneralMy vote of 5 Pin
GregoryW7-Feb-13 9:30
memberGregoryW7-Feb-13 9:30 
GeneralMy vote of 5 Pin
VitorHugoGarcia18-Jan-13 4:00
memberVitorHugoGarcia18-Jan-13 4:00 
QuestionMy Vote 5 Pin
Manoj K Bhoir27-Jun-12 21:27
memberManoj K Bhoir27-Jun-12 21:27 
GeneralMy vote of 5 Pin
manoj kumar choubey24-Feb-12 2:08
membermanoj kumar choubey24-Feb-12 2:08 
GeneralMy vote of 5 Pin
Sergio Andrés Gutiérrez Rojas10-Jan-12 20:31
memberSergio Andrés Gutiérrez Rojas10-Jan-12 20:31 
QuestionWiFi Pin
Member 816088716-Aug-11 19:48
memberMember 816088716-Aug-11 19:48 
AnswerRe: WiFi Pin
wamu6-Nov-12 21:52
memberwamu6-Nov-12 21:52 
QuestionHow to use Pin
Member 816088714-Aug-11 20:55
memberMember 816088714-Aug-11 20:55 
QuestionAny ideas to make it work with Win 7? Pin
atownsend18-Apr-11 7:04
memberatownsend18-Apr-11 7:04 
GeneralMy vote of 5 Pin
thatraja13-Feb-11 16:04
mvpthatraja13-Feb-11 16:04 
GeneralCould you please extend to... Pin
Kochise24-Nov-10 7:12
memberKochise24-Nov-10 7:12 
QuestionHow to limit the speed? Pin
Tigerrr28-Sep-10 0:44
memberTigerrr28-Sep-10 0:44 
AnswerRe: How to limit the speed? Pin
Euhemerus28-Sep-10 4:10
memberEuhemerus28-Sep-10 4:10 
GeneralMy vote of 5 Pin
burak2996-Sep-10 0:29
memberburak2996-Sep-10 0:29 
GeneralSuperb Article... Pin
burak2996-Sep-10 0:28
memberburak2996-Sep-10 0:28 
GeneralRe: Superb Article... Pin
Euhemerus7-Sep-10 4:12
memberEuhemerus7-Sep-10 4:12 
GeneralMy vote of 5 Pin
Bigdeak15-Aug-10 23:31
memberBigdeak15-Aug-10 23:31 
GeneralRe: My vote of 5 Pin
Digital Thunder16-Aug-10 5:21
memberDigital Thunder16-Aug-10 5:21 
GeneralRe: My vote of 5 Pin
kburman619-Apr-13 8:06
professionalkburman619-Apr-13 8:06 
GeneralMy vote of 5 Pin
Md. Marufuzzaman10-Aug-10 21:35
mvpMd. Marufuzzaman10-Aug-10 21:35 
GeneralRe: My vote of 5 Pin
Digital Thunder11-Aug-10 4:16
memberDigital Thunder11-Aug-10 4:16 
GeneralRe: My vote of 5 Pin
Md. Marufuzzaman11-Aug-10 6:15
mvpMd. Marufuzzaman11-Aug-10 6:15 
GeneralNice Work!!! Pin
rspercy6010-Jul-10 0:52
memberrspercy6010-Jul-10 0:52 
GeneralRe: Nice Work!!! [modified] Pin
Digital Thunder10-Jul-10 4:54
memberDigital Thunder10-Jul-10 4:54 

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.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.161021.1 | Last Updated 6 Jul 2010
Article Copyright 2010 by Euhemerus
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid