{"id":105234,"date":"2021-05-21T07:00:00","date_gmt":"2021-05-21T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=105234"},"modified":"2021-05-21T05:55:42","modified_gmt":"2021-05-21T12:55:42","slug":"20210521-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20210521-00\/?p=105234","title":{"rendered":"Obtaining attributed network usage information from the Windows Runtime"},"content":{"rendered":"<p>The network usage information we obtained <a title=\"Obtaining network usage information from the Windows Runtime\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20210520-00\/?p=105232\"> last time<\/a> can also be attributed, so you can see who is consuming all of your bandwidth.<\/p>\n<p>Modify the C# application to gather data differently:<\/p>\n<pre>using System;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Threading.Tasks;\r\nusing Windows.Networking.Connectivity;\r\n\r\nclass Program\r\n{\r\n    static async Task DoIt()\r\n    {\r\n        var now = DateTime.Now;\r\n        var states = new NetworkUsageStates\r\n        { Roaming = TriStates.DoNotCare, Shared = TriStates.DoNotCare };\r\n\r\n        <span style=\"color: blue;\">var profile = NetworkInformation.GetInternetConnectionProfile();\r\n        Console.WriteLine($\"Profile: {profile.ProfileName}\");\r\n        Console.WriteLine($\"------------------\");\r\n\r\n        var usages = await profile.GetAttributedNetworkUsageAsync(\r\n            now.AddHours(-24), now, states);\r\n        for (var usage in usages.OrderByDescending(u =&gt; u.BytesReceived + u.BytesSent))\r\n        {\r\n            Console.WriteLine($\"Id = {usage.AttributionId}\");\r\n            Console.WriteLine($\"BytesReceived = {usage.BytesReceived}\");\r\n            Console.WriteLine($\"BytesSent = {usage.BytesSent}\");\r\n            Console.WriteLine($\"------------------\");\r\n        }<\/span>\r\n    }\r\n\r\n    static void Main()\r\n    {\r\n        DoIt().GetAwaiter().GetResult();\r\n    }\r\n}\r\n<\/pre>\n<p>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.<\/p>\n<p>We sort the results descending by total byte transmitted (sent plus received) and print each record. The <code>Attribution\u00adId<\/code> identifies the source of the network access. It&#8217;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.)<\/p>\n<p>Here&#8217;s the C++\/WinRT version:<\/p>\n<pre>#include &lt;winrt\/Windows.Foundation.h&gt;\r\n#include &lt;winrt\/Windows.Foundation.Collections.h&gt;\r\n#include &lt;winrt\/Windows.Networking.Connectivity.h&gt;\r\n#include &lt;stdio.h&gt;\r\n<span style=\"color: blue;\">#include &lt;algorithm&gt;<\/span>\r\n\r\nusing namespace std::literals::chrono_literals;\r\nusing namespace winrt;\r\nusing namespace winrt::Windows::Foundation;\r\nusing namespace winrt::Windows::Networking::Connectivity;\r\n\r\nIAsyncAction DoIt()\r\n{\r\n    auto now = clock::now();\r\n    NetworkUsageStates states{ TriStates::DoNotCare, TriStates::DoNotCare };\r\n\r\n    <span style=\"color: blue;\">auto profile = NetworkInformation::GetInternetConnectionProfile();\r\n    printf(\"%ls\\n\", profile.ProfileName().c_str());\r\n    printf(\"------------------\\n\");\r\n\r\n    auto usages = co_await profile.GetAttributedNetworkUsageAsync(\r\n        now - 24h, now, states);\r\n    std::vector&lt;AttributedNetworkUsage&gt; sorted{ begin(usages), end(usages) };\r\n    std::sort(begin(sorted), end(sorted), [](auto&amp;&amp; left, auto&amp;&amp; right)\r\n    {\r\n        return left.BytesReceived() + left.BytesSent() &gt;\r\n            right.BytesReceived() + right.BytesSent();\r\n    });\r\n    for (auto usage : sorted) {\r\n        printf(\"Id = %ls\\n\", usage.AttributionId().c_str());\r\n        printf(\"BytesReceived = %I64u\\n\", usage.BytesReceived());\r\n        printf(\"BytesSent = %I64u\\n\", usage.BytesSent());\r\n        printf(\"------------------\\n\");\r\n    }<\/span>\r\n}\r\n\r\nint main()\r\n{\r\n    init_apartment();\r\n    DoIt().get();\r\n}\r\n<\/pre>\n<p>The hardest part about translating the C# version to C++ was sorting the results descending by total bytes transferred!<\/p>\n<p>Now you can answer this question that came in via a customer&#8217;s liaison:<\/p>\n<blockquote class=\"q\"><p>My customer wants to use the data usage feature built into Windows 10 and export the data to a CSV. We couldn&#8217;t find a way to get this information from WMI, but it&#8217;s there in the Settings app. How can we get that information?<\/p><\/blockquote>\n<p>We pointed the customer to the <code>Network\u00adInformation<\/code> class and the <code>Attributed\u00adNetwork\u00adUsage<\/code> class in particular.<\/p>\n<blockquote class=\"q\"><p>Can we use that class to export the data to a CSV?<\/p><\/blockquote>\n<p>The customer doesn&#8217;t seem to want to do any actual programming. It looks they&#8217;re hoping somebody has already written the program for them. Your exercise is to write that program.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Breaking it down by application.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-105234","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Breaking it down by application.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/105234","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=105234"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/105234\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=105234"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=105234"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=105234"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}