Q: Hey I have a fun question! I remember reading a while back about using VBScript to paste to the clipboard. Are we able to do that with PowerShell?
A: Why yes, yes we can! It is far often a much quicker solution if we start with PowerShell!
Pasting content to the clipboard, the old VBScript method
Before we show the quick and easy solution, let’s learn how we could adapt an older solution.
Now back in the day if I wanted to paste something on the clipboard I would go down to the store, get some glue and…
“DOH! Wrong Clipboard!” (Knew I should have splashed some water on my face before typing this up!)
What I should have said was back before PowerShell existed we actually had TWO methods to paste text data to the clipboard.
One was a nice simple solution if you were working in DOS or has simple text output from a VBScript. You would pipe the output to the clip
command as seen below
dir | clip
Once this was complete you could paste your captured text using a CTRL-V
in whichever Windows application.
Another method that presented itself was using some code such as this in VBScript
strCopy = "This text has been copied to the clipboard."
Set objIE = CreateObject("InternetExplorer.Application")
objIE.Navigate("about:blank")
objIE.document.parentwindow.clipboardData.SetData "text", strCopy
objIE.Quit
So I could re-use this solution in PowerShell quite easily. I do this in case you might ever see some older VBScript that you might want to reuse.
The first line in VBScript is assigning a string
strCopy = "This text has been copied to the clipboard."
In PowerShell I can do this in the following manner.
$strCopy = "This text has been copied to the clipboard."
The next line is where a Comobject is created.
Set objIE = CreateObject("InternetExplorer.Application")
The equivalent code in PowerShell to do the same thing and even use the same variable name for the object would be
$objIE = New-Object -comobject "InternetExplorer.Application"
Then from this point the final lines are just manipulating data in the Object.
objIE.Navigate("about:blank")
objIE.document.parentwindow.clipboardData.SetData "text", strCopy
objIE.Quit
Which in PowerShell would look like this.
$objIE.Navigate("about:blank")
$objIE.document.parentwindow.clipboardData.SetData("text", strCopy)
$objIE.Quit
However if you try this solution in a modern version of Windows, it will appear to just sit and hang in PowerShell.
We can one extra line to the original code and you see why.
$objIE.Navigate("about:blank")
# Show the hidden Internet Explorer background application
$objIE.Visible=$True
$objIE.document.parentwindow.clipboardData.SetData("text", strCopy)
$objIE.Quit
The following Window below demonstrates why the old solution, even when converted to PowerShell failed.
In fact, even if we just ran it in VBScript today, it would have failed in an equal manner.
The drawback to converting from VBScript
So that was pretty cool, you tried to re-use some VBScript to meet your task.
In this case because security has improved in past 17 years, Internet Explorer is not allowed to just paste things to the clipboard.
But although this is a nice way to learn how to convert over some older code from VBScript, it is actually not a good used of PowerShell for two reasons.
- It leverages Internet Explorer which, for this purpose, is a big resource to solve the problem at hand. We can also no longer automate in this manner.
- PowerShell has built in cmdlets to solve the problem which are far easier to use. They not only work well in Windows PowerShell, but also just as seamlessly across all supported Operating Systems when using PowerShell 7.x.
The clipboard cmdlets in PowerShell
You can verify they exist by just using Get-Command
like the sample below
Get-Command *clipboard*
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Get-Clipboard 7.0.0.0 Microsoft.PowerShell.Management
Cmdlet Set-Clipboard 7.0.0.0 Microsoft.PowerShell.Management
To populate the clipboard with a directory structure, as an example, I can execute the following line
PS> Get-Childitem | Set-Clipboard
There is no visual output because the data is now stored on the Clipboard.
To verify this in PowerShell you can use the Get-Clipboard
Cmdlet.
PS> Get-Clipboard
C:\Demo\AzureADBaseline
C:\Demo\AzureDSC
C:\Demo\AzureVM-Json
C:\Demo\DualStateMitigate
C:\Demo\testmoduleforme.ps1
C:\Demo\TheShellofBlueness.docx
So yes, I wasted a bit of time showing you how to convert some VBScript. Please have pity on me for my intent was good. Shame on me. 🙂
Summary
It is nice to know that you can convert over to PowerShell in a pretty simple manner from VBScript if you needed to. There are a lot of excellent examples of how to manage Windows environments with VBScript readily written.
It is equally important to understand why we would choose to start fresh with the solution in PowerShell.
It gives us a solution, in this case of manipulating the clipboard in an Operating System; which is consistent across the board whether you choose to use Windows, macOS, Linux or any supported Operating System for PowerShell 7.x.
The choice is yours my friends!
Tip of the Hat
This article was based on one written back on older post on “Can I Copy Script Output to the Clipboard”
I do not recall the author but it was a good way to learn how to programmatically set the clipboard back then. It was time to get it updated.
Cheers all!
Your friend in Automation
Sean Kearney – Customer Engineer/Microsoft – @PowerShellMan
“Remember with great PowerShell comes great responsibility…”
I tried using the set-clipboard and get-clipboard and it didn’t work. Are there other pre-reqs for it to work?
What a commandlet writes onto the pipe are objects and not strings. But the clipboard expects strings. It can’t continue with objects. So better to convert objects into strings before forwarding to the pipe.
dir | out-string -stream | set-clipboard
So far my experiences as a newcomer with powershell.
You don’t need to use Out-String. PowerShell automatically calls the ToString() method on each object in the pipeline before sending it to the clipboard.
One, admittedly small, benefit of using Out-String is that you can adjust the width of the output, like this:
Get-ChildItem -Path M:\GD | Select-object … | Out-Atring -WIdth 180
Should be at least Windows Management Framework 3.x (PowerShell 3 or higher) – Server 2012 / Windows 8 or higher would have this ability in PowerShell.