| Excerpt | ||
|---|---|---|
| ||
allows you to script any ActiveX or COM Windows component from within your Groovy scripts |
| Warning |
|---|
This is the page of the old version of Scriptom. As the new version, Scriptom 2.0, brings with it a couple breaking changes, you may still want to use this version. However, we highly encourage you to switch to the newer version which solves a certain number of bugs and provide a much better integration to COM / ActiveX components. |
Introduction
Scriptom is an optional Groovy module developed by Guillaume Laforge leveraging the Jacob library (JAva COm Bridge). Once installed in your Groovy installation, it allows you to script any ActiveX or COM Windows component from within your Groovy script. Of course, this module can be used on Windows only.
Scriptom is especially interesting if you are developing Groovy shell scripts under Windows. You can combine both Groovy code and any Java library with the platform-specific features available to Windows Scripting Host or OLE COM automation from Office.
Installation
Zip bundle
The easiest way for installing Scriptom is to unzip the Zip bundle in your %GROOVY_HOME% directory.
The distribution contains the jacob.jar and jacob.dll, and the scriptom.jar. The DLL needs to be in the bin directory, or in your java.library.path to be loaded by jacob.jar.
Building from sources
If you are brave enough and prefer using the very latest fresh version from CVS Head, you can build Scriptom from sources. Checkout modules/scriptom, and use Maven to do the installation automatically. If your %GROOVY_HOME% points at the target/install directory of your groovy-core source tree, just type:
| Code Block |
|---|
maven |
Otherwise, if you have installed Groovy in a different directory, you have two possibilities, either you change the property groovy.install.staging.dest to your %GROOVY_HOME% directory in the project.properties file, and run maven, or you can type:
| Code Block |
|---|
maven -Dgroovy.install.staging.dest=%GROOVY_HOME% |
Usage
Let's say we want to script Internet Explorer. First, we're going to import the ActiveX proxy class.
Then, we're going to create a GroovyObjectSupport wrapper around the ActiveXComponent class of Jacob. And now, we're ready to use properties or methods from the component:
| Code Block |
|---|
import org.codehaus.groovy.scriptom.ActiveXProxy
// instantiate Internet Explorer
def explorer = new ActiveXProxy("InternetExplorer.Application")
// set its properties
explorer.Visible = true
explorer.AddressBar = true
// navigate to a site by calling the Navigate() method
explorer.Navigate("http://glaforge.free.fr/weblog")
|
Note however that explorer.Visible returns a proxy, if you want to get the real value of that property, you will have to use the expression explorer.Visible.value or explorer.Visible.getValue().
Limitations
For the moment, Scriptom is in a beta stage, so you may encounter some bugs or limitations with certain ActiveX or COM component, so don't hesitate to post bugs either in JIRA or on the mailing lists. There may be some issues with the mappings of certain objects returned by the component and the Java/Groovy counterpart.
An important limitation for the first release is that it is not yet possible to subscribe to events generated by the components you are scripting. In the next releases, I hope I will be able to let you define your own event handlers with closures, with something like:
| Code Block |
|---|
import org.codehaus.groovy.scriptom.ActiveXProxy
def explorer = new ActiveXProxy("InternetExplorer.Application")
explorer.events.OnQuit = { println "Quit" }
explorer.events.listen()
|
But for the moment, event callbacks are not supported.
There is an experimental implementation currently in CVS Head,it does not work with the groovy command, but it does work when launching a script from a Java program with the GroovyShell object. There is perhaps a problem with Classworlds or Jacob, and the different classloaders. If anyone has a clue, I'm game!
Samples
If you checkout the Scriptom sources, you will find a few samples in the src/script directory.
I will show you some samples in the following sub-sections.
Scripting Internet Explorer
| Code Block |
|---|
import org.codehaus.groovy.scriptom.ActiveXProxy
// instantiate Internet Explorer
def explorer = new ActiveXProxy("InternetExplorer.Application")
// set its properties
explorer.Visible = true
explorer.AddressBar = true
// navigate to a site
explorer.Navigate("http://glaforge.free.fr/weblog")
Thread.sleep(1000)
explorer.StatusText = "Guillaume Laforge's weblog"
Thread.sleep(2000)
// quit Internet Explorer
explorer.Quit()
|
Scripting Excel
| Code Block |
|---|
import org.codehaus.groovy.scriptom.ActiveXProxy
// create a proxy for Excel
def xls = new ActiveXProxy("Excel.Application")
xls.Visible = true
Thread.sleep(1000)
// get the workbooks object
def workbooks = xls.Workbooks
// add a new workbook
def workbook = workbooks.Add()
// select the active sheet
def sheet = workbook.ActiveSheet
// get a handle on two cells
a1 = sheet.Range('A1')
a2 = sheet.Range('A2')
// sets a value for A1
a1.Value = 123.456
// defines a formula in A2
a2.Formula = '=A1*2'
println "a1: ${a1.Value.value}"
println "a2: ${a2.Value.getValue()}"
// close the workbook without asking for saving the file
workbook.Close(false, null, false)
// quits excel
xls.Quit()
|
Warning: on my machine (WinXP Home), there is still an Excel.exe process running. I have no clue why Excel is still running.
Mixing VBScript or JScript with Groovy
| Code Block |
|---|
import org.codehaus.groovy.scriptom.ActiveXProxy
// invoke some VBScript from Groovy and get the results!
def sc = new ActiveXProxy("ScriptControl")
sc.Language = "VBScript"
println sc.Eval("1 + 1").value
|
Scripting the Windows Shell object
| Code Block |
|---|
import org.codehaus.groovy.scriptom.ActiveXProxy
// showing the current directory
def cmd = new ActiveXProxy("Scripting.FileSystemObject")
println cmd.GetAbsolutePathName(".").value
sh = new ActiveXProxy("Shell.Application")
// minimizing all opened windows
sh.MinimizeAll()
// opens an Explorer at the current location
sh.Explore(cmd.GetAbsolutePathName(".").value)
// choosing a folder from a native windows directory chooser
def folder = sh.BrowseForFolder(0, "Choose a folder", 0)
println folder.Items().Item().Path.value
def wshell = new ActiveXProxy("WScript.Shell")
// create a popup
wshell.popup("Groovy popup")
// show some key from the registry
def key = "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\User Agent"
println wshell.RegRead(key).value
def net = new ActiveXProxy("WScript.Network")
// prints the computer name
println net.ComputerName.value
|
Scripting Windows Media Player
| Code Block |
|---|
import org.codehaus.groovy.scriptom.ActiveXProxy
import java.io.File
// create a proxy for the Shell object
def sh = new ActiveXProxy("Shell.Application")
// use a Windows standard folder chooser
def folder = sh.BrowseForFolder(0, "Choose a folder with wav files", 0)
// get the folder chosen
def folderName = folder.Items().Item().Path.value
println "Playing Wav files from: ${folderName}"
// create a Windows Media Player (from its Class ID)
def player = new ActiveXProxy("clsid:{6BF52A52-394A-11D3-B153-00C04F79FAA6}")
// for each file in the folder
new File(folderName).eachFile{ file ->
if (file.name.endsWith("wav")) {
println file
player.URL = file.absolutePath
// play the wav for one second
control = player.controls.play()
Thread.sleep(1000)
}
}
// close the player
player.close()
|
When event callbacks are supported, you will be able to subscribe to the player.statusChange event, so that you can play the wav entirely, before loading a new sample (instead of listening only to the first second of each sample).
Converting a Word document into HTML
This program takes a Word document as first parameter, and generate an HTML file with the same name, but with the .html extension.
| Code Block |
|---|
import org.codehaus.groovy.scriptom.ActiveXProxy
import java.io.File
def word = new ActiveXProxy("Word.Application")
word.Documents.Open(new File(args[0]).canonicalPath)
word.ActiveDocument.SaveAs(new File(args[0] - ".doc" + ".html").canonicalPath, 8)
word.Quit()
|
Printing the contents of your Outlook Inbox
| Code Block |
|---|
import org.codehaus.groovy.scriptom.ActiveXProxy
def outlook = new ActiveXProxy("Outlook.Application")
def namespace = outlook.GetNamespace("MAPI") // There is only "MAPI"
// 6 == Inbox; other values in Outlook's VBA documentation
def inbox = namespace.GetDefaultFolder(6)
def mails = inbox.Items
println "Elements in your Inbox: " + mails.Count.value
for (i in 1..mails.Count.value) {
def mail = mails.Item(i)
println i + ": " + mail.Subject.value + " (" + mail.Size.value + " bytes)"
}
|