March 3rd, 2023

Enumerating Windows clipboard history in PowerShell

Last time, we enumerated the contents of the Windows clipboard history from C++/WinRT and C#. Today we’ll do it from PowerShell.

Because, hey, why not.

$null = [Windows.ApplicationModel.DataTransfer.Clipboard, Windows.ApplicationModel.DataTransfer, ContentType=WindowsRuntime]
$op = [Windows.ApplicationModel.DataTransfer.Clipboard]::GetHistoryItemsAsync()

$result = Await ($op) `
    ([Windows.ApplicationModel.DataTransfer.ClipboardHistoryItemsResult])

$textops = $result.Items.Content.GetTextAsync()
for ($i = 0; $i -lt $textops.Count; $i++){ Await($textops[$i]) ([String]) }

It’s basically the same thing we’ve been doing, just written in PowerShell. Note that I’m not a PowerShell expert, so some of the things I’m doing may be suboptimal.

First, we load the Clipboard class into memory, specifying that it is a Windows Runtime class.

Next, we call Get­History­Items­Async and Await it to get the history items result.

We take the Items from the result, get their Content, and ask each Content for its text.

The text query is another asynchronous operation, so we iterate through the operations and Await each one, sending the results back into the pipeline.

I didn’t add the code to check ahead of time whether the content contained text. I just let the exception flow out of the Get­Text­Async call. Fixing this is left as an exercise.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

10 comments

Discussion is closed. Login to edit/delete existing comments.

Newest
Newest
Popular
Oldest
  • Mystery Man · Edited

    Doesn’t work. The first line of the script returns the following error.

    InvalidOperation: Unable to find type [Windows.ApplicationModel.DataTransfer.Clipboard,Windows.ApplicationModel.DataTransfer, ContentType=WindowsRuntime].

    From that point onward, it’s all failures.

    • Andrew Timson · Edited

      Windows PowerShell can find the type, PowerShell 7 can’t. (I still get issues later on because $result.Items.Content is null, though.)

      • George Tokmaji · Edited

        Windows PowerShell (aka PowerShell 5) is based on .NET Framework, PowerShell 7 on .NET Core.

      • Kalle Niemitalo · Edited

        The file is “C:\WINDOWS\system32\WinMetadata\Windows.ApplicationModel.winmd” but neither Windows PowerShell 5.1 nor PowerShell 7.3.3 can load it by calling Add-Type -AssemblyName, [System.Reflection.Assembly]::LoadFile, or [System.Reflection.Assembly]::LoadFrom.

        WinRT interop was removed in .NET 5. PowerShell 7.0.13 uses .NET Core 3.1.30 and seems to be the last release in which WinRT types can be natively referenced.

      • Mystery Man · Edited

        Ironic. I remember a time when Microsoft had an undue focus on backward compatibility. Now its contemporary technologies aren’t compatible with each other. The “I” in “API” stands for “Interface” but whoever made Windows.ApplicationModel.DataTransfer.Clipboard didn’t get the memo.

      • Blubberich

        Well it’s supposed to be the cross-platform PowerShell and framework.
        So what do you do about platform-specific stuff?

        Throw it out as happened here?
        Keep it in and require runtime checks for the platform?

        I see no way Microsoft can win here.

      • Mystery Man

        PowerShell 7.0, which was also cross-platform, could do it. C#, which is also cross-platform, can do it right now.

        And most importantly, this Windows Runtime nonsense that nobody seems to understand is a trap of Microsoft’s making. It shows no teamwork spirit towards anything except Microsoft Store apps, which are hard to develop, impossible to optimize, slow as tar, and incredibly hideous. Microsoft had 11 years to dismantle this nonsense. Except, the company kept digging itself into a hole.

      • Paulo Pinto

        The way UWP, WinUI. .NET Native, C++/CX migration has been managed has been a joke on us, see the amount of issues on Github, Developer Connection and missing features.

        PowerShell being another victim of this mess is yet another symptom.

        It is quite hard to stay commited to Windows desktop nowadays, other than classical Win32 and .NET APIs, everything else is hit and miss.

      • Mystery Man

        And PowerShell’s inventor left Microsoft. He’s working for Google now.

Feedback