Obtaining attributed network usage information from the Windows Runtime

Raymond Chen

Raymond

The network usage information we obtained last time can also be attributed, so you can see who is consuming all of your bandwidth.

Modify the C# application to gather data differently:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Windows.Networking.Connectivity;

class Program
{
    static async Task DoIt()
    {
        var now = DateTime.Now;
        var states = new NetworkUsageStates
        { Roaming = TriStates.DoNotCare, Shared = TriStates.DoNotCare };

        var profile = NetworkInformation.GetInternetConnectionProfile();
        Console.WriteLine($"Profile: {profile.ProfileName}");
        Console.WriteLine($"------------------");

        var usages = await profile.GetAttributedNetworkUsageAsync(
            now.AddHours(-24), now, states);
        for (var usage in usages.OrderByDescending(u => u.BytesReceived + u.BytesSent))
        {
            Console.WriteLine($"Id = {usage.AttributionId}");
            Console.WriteLine($"BytesReceived = {usage.BytesReceived}");
            Console.WriteLine($"BytesSent = {usage.BytesSent}");
            Console.WriteLine($"------------------");
        }
    }

    static void Main()
    {
        DoIt().GetAwaiter().GetResult();
    }
}

This time, we get the current connection that is being used to access the Internet and ask for attributed network usage for the past 24 hours.

We sort the results descending by total byte transmitted (sent plus received) and print each record. The Attribution­Id identifies the source of the network access. It’s kind of ugly, but you can usually eyeball it to see what the application is. (Converting this to something prettier is out of scope for this exercise.)

Here’s the C++/WinRT version:

#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Networking.Connectivity.h>
#include <stdio.h>
#include <algorithm>

using namespace std::literals::chrono_literals;
using namespace winrt;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Networking::Connectivity;

IAsyncAction DoIt()
{
    auto now = clock::now();
    NetworkUsageStates states{ TriStates::DoNotCare, TriStates::DoNotCare };

    auto profile = NetworkInformation::GetInternetConnectionProfile();
    printf("%ls\n", profile.ProfileName().c_str());
    printf("------------------\n");

    auto usages = co_await profile.GetAttributedNetworkUsageAsync(
        now - 24h, now, states);
    std::vector<AttributedNetworkUsage> sorted{ begin(usages), end(usages) };
    std::sort(begin(sorted), end(sorted), [](auto&& left, auto&& right)
    {
        return left.BytesReceived() + left.BytesSent() >
            right.BytesReceived() + right.BytesSent();
    });
    for (auto usage : sorted) {
        printf("Id = %ls\n", usage.AttributionId().c_str());
        printf("BytesReceived = %I64u\n", usage.BytesReceived());
        printf("BytesSent = %I64u\n", usage.BytesSent());
        printf("------------------\n");
    }
}

int main()
{
    init_apartment();
    DoIt().get();
}

The hardest part about translating the C# version to C++ was sorting the results descending by total bytes transferred!

Now you can answer this question that came in via a customer’s liaison:

My customer wants to use the data usage feature built into Windows 10 and export the data to a CSV. We couldn’t find a way to get this information from WMI, but it’s there in the Settings app. How can we get that information?

We pointed the customer to the Network­Information class and the Attributed­Network­Usage class in particular.

Can we use that class to export the data to a CSV?

The customer doesn’t seem to want to do any actual programming. It looks they’re hoping somebody has already written the program for them. Your exercise is to write that program.

5 comments

Comments are closed. Login to edit/delete your existing comments

  • Avatar
    Brian Boorman

    To be fair, maybe the customer submitting this request isn’t a programmer but rather an IT-type person.

    Either way, the exercise would be to open a file handle, fprintf() the csv header right before the for loop, and then change the printf’s in the loop to an fprintf with the proper format string.

    • Ivan K
      Ivan K

      If it involves an IT Dept and available .NET classes then a challenge (to me) would be to do the whole thing in PowerShell so it can be easily modded by whoever uses it… I guess I stereotype IT coders with scripters. I think I’ve written maybe 20 lines of PowerShell in my life, so I don’t know if it’s possible, but I suspect it is. Anyways, quick searches for PowerShell + CSV, and PowerShell + NetworkInformation yield a character called Dr. Scripto.

      • Avatar
        cheong00

        I thought the ability of doing basic scripting with PowerShell is standard ability for admins since like 10 years ago.

        And for people who don’t know how to sort with Sort-Object, they can always write data as CSV first then use Excel to sort.

  • Avatar
    Brett Thwaites Jr.

    “Converting this to something prettier is out of scope for this exercise”

    Isn’t this what AttributionName is for?