Many people asked how to access clipboard from WSH and how to print from WSH scripts. Well, during updating my German title Inside Windows Script Host, 2nd edition (Microsoft Press), I covered this issue. Due to postings in distinct newsgroups I was inspired to investigate Internet Explorer, and I found some tricks how to print simple documents or exchange data with the clipboard. I also wrote some ActiveX controls that provides the requested methods. In newsletter #6 I already introduced a way how to create your own power scripts that uses Imaging as a helper to access graphics, print them, copy and paste to/from clipboard or to convert files. But Imaging is a bit an overkill, if you intend to print just simple text or html files or if you intend to copy a simple string to/from clipboard. So let's talk about the details.
(c) Günter Born, http://www.borncity.de
Warning: The material submitted as a newsletter comes AS-IS without any warranty of any kind. In no event shall the author be liable for damages and losses of any kind. The material discussed herein is copyrighted by the author. You get a free right to use it. This newsletter may be distribute freely as long as: a) the text remains intact and unmodified, b) a reference to the WSH Bazaar www.borncity.de is given and c) the newsletter is not shipped with other commercial material. If you like to ship the newsletter with CD-ROMs etc. please ask. Permission will be granted in normal cases, but I like to know where my material goes into.
The most simple way to print text files (and other files containing text) is offered by the program Notepad. This little editor is available in all Windows versions, and you may invoke the editor using the following command:
Notepad.exe /p c:\test\mytext.txt
The command above invokes Notepad and load the file submitted in the 2nd argument. The switch /p forces Notepad to print the file (using the default printer). After printing, Notepad terminates automatically. Using this know how it is only a short way to print from WSH scripts:
'************************************************ ' File: PrintTxt.vbs (WSH-sample in VBScript) ' Author: G. Born www.borncity.com ' ' Demonstrates how to print a text file using Notepad. ' The sample prints the script's source code. ' ' See also the Microsoft Press title: ' Microsoft Windows Script Host 2.0 Developer's Guide '************************************************ Option Explicit Dim oWSHShell ' create Shell object instance for Run method Set oWSHShell = WScript.CreateObject("WScript.Shell") ' shell out a command to print with Notepad oWSHShell.Run "Notepad /p " _ & """" & WScript.ScriptFullName & """" ,_ 7, true WScript.Echo "Printing" ' inform user '*** End |
The script show above just prints its own source code using notepad. The parameters submitted to Run forces Windows to show the window minimized (2nd parameter set to 7). The third parameter set to True causes the script to wait until Notepad terminates.
Internet Explorer installs also a library MSHTML.dll that provides some functions to print documents. The advantages, compared to Notepad, are: The program show the Print dialog box, so a user may select the printer and some print options. Also MSHTML.dll supports beside text files also HTML documents and RTF files. Unfortunately there is a small problem: MSHTML.dll is a system library and WSH scripts can't access library functions (if these functions are not exported as methods of COM objects). Fortunately there is Rundll32.exe, a small program that allows calling API functions in system libraries. So you can use the following command to invoke the MSHTML.dll print function:
Rundll32.exe MSHTML.dll,PrintHTML filename
Note that the command is case-sensitive, and also there is no blank following the comma separating the library name from the function name. The function PrintHTML accepts one argument containing the document's file name. The next listing uses MSHTML.dll to print distinct files:
'************************************************ ' File: PrintDocs.vbs (WSH-sample in VBScript) ' Author: G. Born www.borncity.com ' ' Demonstrates how to print several document files ' using MSHTML.dll. '************************************************ Option Explicit ' Define some files. 'Const file = "C:\Text.txt" Const file = "C:\Text.htm" 'Const file = "C:\Text.rtf" Dim oWSHShell ' create Shell object instance for Run method Set oWSHShell = WScript.CreateObject("WScript.Shell") ' shell out a command to print source with MSHTML oWSHShell.Run "Rundll32.exe MSHTML.dll,PrintHTML " & _ file, 1, true WScript.Echo "I guess we are printing " & file '*** End |
If the script displays the Print dialog box, just select the print options and click OK. Take care to prepare a document file and set the right file and path name in the file constant. The parameters submitted to Run forces Windows to show the dialog box in normal mode.
If you right-click a document file, Windows Shell shows you a context menu, and in most cases you'll find the Print command. If you select Print, Windows forces the registered application to load the document, print it and terminate. Why not use a similar feature from WSH? Unfortunately WSH can't access the Shell API (there are only a few methods offered by Shell.Application). Therefore I wrote a small ActiveX control that provides access to some Shell API. The control WSHShellExtend.ocx may be dowloaded from the ActiveX page of the WSH Bazaar. After installing this control (see also newsletter #3), you can use the methods provided by this control. The next listing uses this control to print document files:
'************************************************ ' File: PrintExtender.vbs (WSH-sample in VBScript) ' Author: G. Born www.borncity.de ' ' Demonstrate how to print document files using an ' ActiveX control. Need WSHShellExtend.ocx. '************************************************ Option Explicit Dim oShExt, code, tmp ' create object reference Set oShExt = WScript.CreateObject("ShellExtension.ShellObjects") If MsgBox ("Print bmp file?", vbYesNo + vbQuestion, _ "Print Extender") = vbYes Then ' print a BMP file code = oShExt.WSHShellExecute ( _ "print", GetPath() & "TestImg.bmp", "", "", 1) If code > 32 Then MsgBox "We are printing ... " Else MsgBox "Error, code is " & code End if End if If MsgBox ("Print pdf-file", vbYesNo + vbQuestion, _ "Print Extender") = vbYes Then ' print a PDF file (requires Acrobat reader installed) code = oShExt.WSHShellExecute ( _ "print", GetPath() & "TestDoc.pdf", "", "", 1) If code > 32 Then MsgBox "We are printing ... " Else MsgBox "Error, code is " & code End if End if '########################## Function GetPath ' Retrieve path to the script file DIM path path = WScript.ScriptFullName ' script file name GetPath = Left(path, InstrRev(path, "\")) End Function '*** End |
The script instantiate the object ShellExtension.ShellObjects and accesses then the WSHShellExecute method. This method requires 6 parameters. The first parameter contains a verb ("print", "open" for instance), the 2nd parameter contains the path and the file name. The other parameters (for working directories etc.) are set to "" or to 1 as shown above. Further details about using this methods along with the source code of the ActiveX control is provided in my German Microsoft Press title Inside Windows Script Host, 2. Ausgabe. Also my upcoming English MS Press title Advanced Development with Microsoft Windows Script Host 2.0 will cover this topic.
Many scripters wish to interact with the clipboard. Although WSH doesn't provide methods to do that, you can use a few tricks. Let's go step by step.
The most efficient way will be to write an ActiveX control that provides you with methods allowing you to access Windows clipboard. I wrote such a control and shipped it with the MS Press title Inside Windows Script Host, 2. Ausgabe (and there are also plans that my upcoming English MS Press title Advanced Development with Microsoft Windows Script Host 2.0 will contain this control). But till now I'm not ready to release this stuff in the WSH Bazaar (because the description is still in German). That's odd, but fortunately there are a few way to overcome this situation.
Well, maybe you intend to control two applications using WSH, and your script need to force one program to transfer data to the other. In this case you can force the application to copy data to clipboard and paste it into the document area of the other program. This will be used. The script launches Notepad and Calc, forces Calc to evaluate an expression and transfer the result to Notepad.
'************************************************ ' File: AppActivateWSH2.vbs (WSH 2.0 VBScript sample) ' Author: (c) G. Born www.borncity.de ' ' Launch Calc and Notepad, use AppActivate to ' switch between applications. Transfers data ' between Calc and Notepad using Clipboard (controlled ' by SendKeys. ' Attention: The script requires WSH 2.0 !!! '************************************************ Option Explicit ' Define the title strings of the application windows ' Use the title's begin or end, if a file name changes ' Important: strings depend on the localized Windows version Const Edit_Title = "Notepad" ' window title Const Calc_Title = "Calculator" ' window title DIM Wsh ' Create the Shell object, required for Run and AppActivate Set Wsh = WScript.CreateObject("WScript.Shell") ' we try to launch two applications - to assure that the ' last application receives the focus, we delay the script Wsh.Run "Calc.exe",1 ' launch Windows calculator WScript.Sleep 300 ' delay, till calc gets the focus Wsh.Run "Notepad.exe",1 ' launch Windows editor Notepad WScript.Sleep 300 ' delay, till notepad gets the focus ' set the focus back to the calculator window & calulate If Wsh.AppActivate (Calc_Title) Then Wsh.SendKeys "10" ' send 10 Wsh.SendKeys "{+}" ' send + Wsh.SendKeys "2" ' send 2 Wsh.SendKeys "=" ' send = Wsh.SendKeys "^{c}" ' send Ctrl+C, copy to clipboard End if ' set the focus to the editor window MsgBox "Paste result into editor window?", vbOkOnly + vbSystemModal If Wsh.AppActivate (Edit_Title) Then Wsh.SendKeys "Result of 10 {+} 2 =" Wsh.SendKeys "^{v}" ' send Ctrl+v, paste from clipboard End if '* End |
You can use similar techniques also with other application programs. Then you need to send keystrokes to select portions of the document area (which can be a problem).
If you need to access some clipboard text within your script, the trick shown above won't fit. But I found another way to exchange text data between script variable and clipboard without using an ActiveX control. Let's go into details. You can use Internet Explorer to show a form that contains a text field. And you can use the methods execCommand('Paste') and execCommand('Copy') to transfer data to and from a selected area. The following form demonstrates how to do this: Enter a text into the Send text box and click Copy. The content of the text box will be transfered to clipboard. If you click the Paste button, the clipboard's contend will be pasted into the Read text box. You can use another applications to copy text to the clipboard and paste it into the Read text box. Or you can paste the text obtained from Send in other document windows (using for instance the SendKeys trick shows above).
The HTML source code of the form shown above is rather simple:
Send: <input type=text id="input" size="40" value="John Brown's body ..."> <input type="button" id="x1" value="Copy " onClick={input.select();execCommand('Copy')}> <br> Read: <input type=text id="result" size="40" value=""> <input type="button" id="x2" value="Paste" onClick={result.select();execCommand('Paste')}> |
Well, that's the beef. You can use a simple HTML form to exchange clipboard text data with a WSH script. The script can use the Internet Explorer object model to access the necessary document elements and functions. This will be shown in the following VBScript sample. The sample creates an Internet Explorer instance and writes a small form on the fly in the document area. Then the script can read or write data to the text box located in the form, and the script can access the execCommand method to echange data with clipboard. Details may be found in the following listing.
'************************************************ ' File: HTMLClipboard.vbs (WSH sample in VBScript) ' Author: (c) Günter Born www.borncity.de ' ' Demonstrates how to access the clipboard using ' VBscript and Internet Explorer. ' Details may be found in the MS Press Titel: ' Microsoft Windows Script Host 2.0 Developer's Guide '************************************************ Option Explicit Dim oIE ' global object for IE Dim txt ' handles clipboard text ' Create Internet Explorer instance for clipboard access MakeIEDoc ' Ask user for a text txt = InputBox ("Enter a text", "Paste text to clipboard", "") ' write a text into text box oIE.Document.All.exch.Value = txt ' Write text into IE document's text box ... oIE.Document.All.exch.select() ' ... and transfer it to clipboard oIE.Document.execCommand("Copy") ' Allow user to check the clipboard content WScript.Echo "Written to clipboard: " & vbCRLF & txt & vbCRLF & _ vbCRLF & "Please check and alter the clipboard" ' read data from clipboard into text box ... oIE.Document.execCommand("Paste") ' and show data obtained from this text box WScript.Echo "Clipboard text:" & vbCRLF & oIE.Document.All.exch.Value oIE.Quit ' close Internet Explorer instance ' Ready '################### ' Helper procedures '################### Sub MakeIEDoc () ' Launch Internet Explorer & prepare a page with a text box Dim html ' define HTML code with a text area html = "<html><head><title>Clipboard Exchange Helper</title></head>" & _ "<body bgcolor='silver'>" & _ "<textarea name='exch' rows='8' cols='80'></textarea>" & _ "</body></html>" ' *** launch Internet Explorer *** Set oIE = WScript.CreateObject("InternetExplorer.Application") oIE.left=50 ' window position oIE.top = 100 ' and other properties oIE.height = 200 oIE.width = 580 oIE.menubar = 0 ' no menu oIE.toolbar = 0 oIE.statusbar = 0 oIE.navigate "about:" & html ' Helper window ' we keep the browser window invisible! Uncomment the ' next line, if you like to view the browser window for tests ' oIE.visible = 1 ' keep visible Do While (oIE.Busy):Loop ' Important: wait till MSIE is ready End Sub '* End |
Launch the script with a double-click to its file icon. The script shows an input dialog asking for a text. After closing the dialog, the input is pasted to the clipboard. You can use Notepad to check the clipboard's content. Then you may copy some text from Notepad to the clipboard. After closing the script's dialog box, the clipboard contend is shown in a second dialog box. BTW: uncomment the oIE.visible=1 statement in MakeIEDoc procedure will show Internet Explorer's window (the window is hidden by default).
Michael Turenne, one of my readers, has noticed me that the script to access the clipboard shown above fails, if more than one instance of Internet Explorer is running. In this case, WSH causes a runtime error
Error: Object doesn't support this property or
method: 'Document.All.exch'
Code: 800a01b6
Source: Microsoft VBScript runtime error
Don't know why that happens - maybe a bad implementation within IE. But there is a solution to overcome this problem. We can use the clipboardData-object and its methods setData ("Text", txt) and getData("Text") to access the clipboard from WSH scripts. Here is the sample code of a VBScript program.
'************************************************ ' File: HTMLClipboard.vbs (WSH sample in VBScript) ' Author: (c) Günter Born ' ' Demonstrates how to access clipboard from a ' WSH script using Internet Explorer. ' Depending on IE security settings, a warning dialog ' will occur during inserting and reading clipboard data. '************************************************ Option Explicit Dim oIE ' global object IE Dim txt ' clipboard text ' create IE instance - used for clipboard access Set oIE = WScript.CreateObject("InternetExplorer.Application") oIE.navigate "about:blank" ' empty document oIE.visible = 0 ' hidden Do While (oIE.Busy) ' wait till IE ready WScript.Sleep 50 Loop ' query text from user txt = InputBox ("Please enter a text", _ "Copy text to clipboard", "") ' copy text to clipboard oIE.Document.parentWindow.clipboardData.setData "Text", txt ' allow user to check clipboard WScript.Echo "Text copied to clipboard: " & vbCRLF & txt & vbCRLF & _ vbCRLF & "You may check the clipboard now" ' Read text back from clipboard ... txt = oIE.document.parentWindow.clipboarddata.getData("text") ' show result WScript.Echo "Text aus Zwischenablage:" & vbCRLF & txt oIE.Quit ' close IE '* End |
Launch the script with a double-click to its file icon. The script shows an input dialog asking for a text. After closing the dialog, the input is pasted to the clipboard. You can use Notepad to check the clipboard's content. Then you may copy some text from Notepad to the clipboard. After closing the script's dialog box, the clipboard contend is shown in a second dialog box.
Further details and other tricks may be found in my German Microsoft Press title Inside Windows Script Host, 3. Ausgabe and in my English Microsoft Press title Microsoft Windows Script Host 2.0 Developer's Guide.
Planned topics for newsletter #8 and future newsletters:
Enyoy scripting, till the next newsletter arrives...
... but currently (since 2 years) I'm terrible busy with a lot of other projects (from Linux to data base acces in StarOffice/OpenOffice, from Windows inside tricks to .NET-programming). So my spare time is rare at the moment. But don't give up hope - maybe there will be some spare time to transform the material located on my hard disc to further newsletters.
(c) G. Born, 7 - May 2004 - www.borncity.de