{"id":107889,"date":"2023-03-02T07:00:00","date_gmt":"2023-03-02T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=107889"},"modified":"2023-03-06T08:27:25","modified_gmt":"2023-03-06T16:27:25","slug":"20230302-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230302-00\/?p=107889","title":{"rendered":"Enumerating Windows clipboard history in C++\/WinRT and C#"},"content":{"rendered":"<p>Here&#8217;s a console program that dumps all the text from the Windows clipboard history:<\/p>\n<pre>#include &lt;stdio.h&gt;\r\n#include &lt;winrt\/Windows.ApplicationModel.DataTransfer.h&gt;\r\n#include &lt;winrt\/Windows.Foundation.h&gt;\r\n#include &lt;winrt\/Windows.Foundation.Collections.h&gt;\r\n\r\nnamespace winrt\r\n{\r\n    using namespace winrt::Windows::Foundation;\r\n    using namespace winrt::Windows::Foundation::Collections;\r\n    using namespace winrt::Windows::ApplicationModel::DataTransfer;\r\n}\r\n\r\nwinrt::IAsyncAction DumpClipboardHistoryAsync()\r\n{\r\n    auto result = co_await Clipboard::GetHistoryItemsAsync();\r\n    auto items = result.Items();\r\n    for (auto item : items) {\r\n        auto content = item.Content();\r\n        if (content.Contains(StandardDataFormats::Text())) {\r\n            auto text = co_await content.GetTextAsync();\r\n            printf(\"%ls: %ls\\n\", item.Id().c_str(), text.c_str());\r\n        } else {\r\n            printf(\"%ls: (no text content)\\n\", item.Id().c_str());\r\n        }\r\n    }\r\n}\r\n\r\nint main()\r\n{\r\n    winrt::init_apartment(winrt::apartment_type::multi_threaded);\r\n\r\n    DumpClipboardHistoryAsync().get();\r\n\r\n    return 0;\r\n}\r\n<\/pre>\n<p>First, we ask for all of the clipboard history items. This call may fail and return no items; if we are interested in that case, we can check the <code>Clipboard\u00adHistory\u00adItem\u00adResult\u00adStatus<\/code> to see why we got nothing. (Maybe the user hasn&#8217;t enabled clipboard history.)<\/p>\n<p>Conveniently, if clipboard history is not available, the <code>Get\u00adHistory\u00adItems\u00adAsync<\/code> method produces an empty vector, so we can just go straight to the vector of results.\u00b9<\/p>\n<p>For each item in the results, we ask if its content contains text. If so, then we ask for the text and print it. (If not, then we just say &#8220;Sorry.&#8221;)<\/p>\n<p>The sample doesn&#8217;t demonstrate it, but you can also take a history item and pass it to <code>Clipboard::<wbr \/>Set\u00adHistory\u00adItem\u00adAs\u00adContent<\/code> to make it the current item on the clipboard.<\/p>\n<p>And here&#8217;s the C# version:<\/p>\n<pre>using System;\r\nusing System.Threading.Tasks;\r\nusing Windows.ApplicationModel.DataTransfer;\r\n\r\nclass Program\r\n{\r\n    public static async Task Main()\r\n    {\r\n        var result = await Clipboard.GetHistoryItemsAsync();\r\n        var items = result.Items;\r\n        foreach (var item in items) {\r\n            var content = item.Content;\r\n            if (content.Contains(StandardDataFormats.Text)) {\r\n                var text = await content.GetTextAsync();\r\n                System.Console.WriteLine($\"{item.Id}: {text}\");\r\n            } else {\r\n                System.Console.WriteLine($\"{item.Id}: (no text content)\");\r\n            }\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>It&#8217;s a straightforward translation of the C++\/WinRT version.<\/p>\n<p>Next time, we&#8217;ll translate this into PowerShell.<\/p>\n<p>Wait, what?<\/p>\n<p>Yup, PowerShell.<\/p>\n<p>\u00b9 This is a general principle in the Windows Runtime that methods which produce vectors return empty vectors rather than null pointers on failure.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Exploring the clipboard history API.<\/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-107889","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Exploring the clipboard history API.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/107889","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=107889"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/107889\/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=107889"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=107889"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=107889"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}