Automating the world one-liner at a time…
In the previous example we learned how to create a colorized copy of console in HTML and RTF format. However, the output of these scripts cannot be readily used for pasting into web or word processing applications. To insert it into your article in MS Word format, you need several steps: generate RTF string, save it to an RTF file, then open the file in MS Word, copy its contents and, finally, paste it into your document. Can we reduce it to two steps: run the script, which copies console screen to system clipboard, and then paste the results to MS Word? As a matter of fact we can, but to do this we need to learn how to work with system clipboard from within Windows PowerShell.
Here are some basics for those who are not familiar with system clipboard mechanics. When you do a copy in windows application, the application creates data object, which contains a reference or a serialized copy of the selected data. The data can be stored in multiple format to increase the chance that a target application, whose format requirements you might not know, can retrieve the stored data. For example, Windows Mail application in Vista can paste data presented in Text or HTML format and won't recognize RTF. Microsoft Word, on the contrary, will be happy to accept RTF or Text when pasting, but won't deal with HTML. Notepad will take only text and will ignore HTML and RTF altogether. That is why when copying formatted text it is generally a good idea to put data in clipboard in at least three popular formats - Text, HTML, and RTF. The easiest way to do it is to use System.Windows.Forms.Clipboard class, which is part of the .NET framework.
To make long story short, here is an example:
# Load System.Windows.Forms assembly. $null = [Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") # Create a data object. $dataObject = New-Object windows.forms.dataobject # Add generated strings to the data object. $dataObject.SetData([Windows.Forms.DataFormats]::UnicodeText, $true, $text) $dataObject.SetData([Windows.Forms.DataFormats]::RTF, $true, $rtf) $dataObject.SetData([Windows.Forms.DataFormats]::HTML, $true, $html) # Place the data object in the system clipboard. [Windows.Forms.Clipboard]::SetDataObject($dataObject, $true)
Note that working with system clipboard has one important limitation. The Clipboard class can only be used from the threads which are set to single thread apartment (STA) mode. Windows Powershell ISE runs in STA by default, but Windows PowerShell console default mode is MTA. To work around this limitation in Windows PowerShell console you need to start Windows PowerShell console with -sta switch, which is available in CTP3 release of Windows PowerShell V2.
In the attached script we are reusing the code from Capture console screen and Colorized capture of console screen in HTML and RTF to capture console screen buffer and transform it to three core text formats (Unicode Text, HTML and RTF). Then, we place the results into system clipboard as shown in a code snippet above.
To use this script you need to install PowerShell V2 CTP3 on your machine. To run the script start Windows PowerShell console in STA mode or run the script using the powershell –sta –command <scriptpath> line.
Windows PowerShell V2 (Community Technology Preview - Features Subject to Change) Copyright (C) 2008 Microsoft Corporation. All rights reserved. PS C:\Users\Vladimir> cd E:\MyScripts PS E:\MyScripts> PS E:\MyScripts> .\Copy-Console.ps1 The script cannot be run in MTA mode. Start Windows Powershell with -STA switch, or rerun the script using powershell -sta -command <scriptpath>. Example: powershell -noprofile -sta -command d:\myscripts\Copy-Console.ps1 PS E:\MyScripts> powershell -noprofile -sta -command e:\myscripts\Copy-Console.ps1 The console screen has been copied to system clipboard. You can now paste it to any application that supports text, HTML or RTF pasting. PS E:\MyScripts>
The results of the script execution can be seen above. I’ve simply run the script and pasted the results in the blog post editor.
Note that you can run powershell –sta –command Copy-Console.ps1 not only from Windows PowerShell console, but also from conventional CMD console. That means you can use this script to capture colorized output from any Windows console application.
Microsoft Windows [Version 6.0.6001] Copyright (c) 2006 Microsoft Corporation. All rights reserved. C:\Windows\System32>cd WindowsPowerShell C:\Windows\System32\WindowsPowerShell>dir Volume in drive C has no label. Volume Serial Number is D67B-C7C5 Directory of C:\Windows\System32\WindowsPowerShell 09/08/2008 07:08 PM <DIR> . 09/08/2008 07:08 PM <DIR> .. 01/10/2009 05:24 PM <DIR> v1.0 0 File(s) 0 bytes 3 Dir(s) 55,533,215,744 bytes free C:\Windows\System32\WindowsPowerShell>powershell -noprofile -sta -command e:\myscripts\Copy-Console.ps1
Windows PowerShell team
The -STA switch was also available in CTP2. I can't remember if CTP1 had it also.
The ISE runs exclusively in STA mode.
It is the second time this weekend that I am seeing a requirement for the PowerShell session to be run in STA mode (the first one was with the PowerBoots module).
I find this a rather serious issue if specific products or sample code snippets start requiring PowerShell to run in a non-default mode. Is there any limitation with running PowerShell in STA mode as a default mode?
To reliably use the Clipboard, make sure that the PowerShell window is running in the STA mode. I am