VBScript Components
I've been using quite a lot of VBScript for my work, which we use for general admin tasks such as transferring or downloading files, logging, or interacting with databases. Basically, stuff we need a quick and dirty script for and where creating a program would be too much effort!
VBScript, which is actually a subset of VBA (Visual Basic for Applications), is actually quite handy for stuff like this, and whilst not the most flexible or powerful, it has its advantages.
For one, it's a scripting language, which means that code doesn't have to be compiled or recompiled every time it's run. This might not seem like a huge benefit, but usually when one of these scripts goes awry, we can track down the bug or problem and fix it in place, rather than having to go searching for the source code, modifying, and then creating the executable all over again. This is an important speed gain for us, as the processes which break are normally on a business schedule and have to be run as soon as possible for clients.
It also has the ability to interact with COM objects, which makes it far more powerful than it ever could be on its own, enabling us to interact with other installed applications and create other objects allowing us to delve into the murky depths of the windows operating system. In addition to creating and calling COM objects through your scripts though, you are also able to define your own COM object in VBScript.
It's a cool idea, and probably quicker/easier than creating it in another language such as C++ with the ATL. I recently decided we could use this idea where I work, in situations where sending out automated emails are required. We use a lightweight program called Blat to send emails at the moment - it's a command-line utility which requires knowledge of an SMTP server, but once it's hooked up you can pass some parameters to it and let it send all the emails you want! The problem we have with it, is that whenever you want to implement it in a script, you have to remember what command line arguments it wants and most of the time we end up going onto the Blat website to look them up! So my idea was to create an Email VBScript component that can be easily implemented in other scripts.
The documentation for creating components in VBScript can be found on Microsoft's site here but it turns out that they also have a handy wizard for creating them. Using the wizard creates a template for your component, asking you for any properties, methods, or events you want to implement as your interface, and then generating the XML file that you can use to implement your code and then register it.
This was how I created my Email component. The wizard very kindly handed me an xml document that read thus:
<?xml version="1.0"?>
<component>
<registration
description="Support.Email"
progid="Support.Email"
version="1.00"
>
</registration>
<public>
<method name="Send">
<PARAMETER name="Subject"/>
<PARAMETER name="Body"/>
</method>
<method name="SendWithAttach">
<PARAMETER name="Subject"/>
<PARAMETER name="Body"/>
<PARAMETER name="AttachPath"/>
</method>
<method name="SendToMobile">
<PARAMETER name="Subject"/>
<PARAMETER name="Body"/>
</method>
<method name="SendToMobileWithAttach">
<PARAMETER name="Subject"/>
<PARAMETER name="Body"/>
<PARAMETER name="AttachPath"/>
</method>
</public>
<script language="VBScript">
</script>
</component>
Currently, this document only defines the interface for your component, or in other words, the functions available to external processes that wish to use it. That doesn't mean that you can't implement more functions if you so wish, but these extra functions wouldn't be available to the external applications that use it. From here, all I had to do is implement the code for my declared functions within the script tags. Easy, right? Something like this would do nicely:
Const ProductionAddr = "production@theirdomain.co.uk"
Const FromAddr = "production@ourdomain.co.uk"
Const SupportAddr = "support@ourdomain.co.uk"
Const MobileAddr = "mobileAlerts@ourdomain.co.uk"
Const BlatPath = "D:\blat.exe"
function Send(Subject, Body)
On Error Resume Next
Dim Cmd: Cmd = BlatPath & " - -to " & ProductionAddr & " " & _
"-s """ & Replace(Subject, """", "'") & """ " & _
"-body """ & Replace(Body, """", "'") & """ " & _
"-from " & FromAddr & " " & _
"-replyto " & SupportAddr
With CreateObject("WScript.Shell")
.Run Cmd, 1, True
End With
If (Err) Then
Send = 1
Else
Send = 0
End If
end function
function SendWithAttach(Subject, Body, AttachPath)
On Error Resume Next
Dim Cmd: Cmd = BlatPath & " - -to " & ProductionAddr & " " & _
"-s """ & Replace(Subject, """", "'") & _
"-body """ & Replace(Body, """", "'") & _
"-attach """ & AttachPath & """ " & _
"-from " & FromAddr & " " & _
"-replyto " & SupportAddr
With CreateObject("WScript.Shell")
.Run Cmd, 1, True
End With
If (Err) Then
Send = 1
Else
Send = 0
End If
end function
function SendToMobile(Subject, Body)
On Error Resume Next
Dim Cmd: Cmd = BlatPath & " - -to " & ProductionAddr & "," & MobileAddr & " " & _
"-s """ & Replace(Subject, """", "'") & """ " & _
"-body """ & Replace(Body, """", "'") & """ " & _
"-from " & FromAddr & " " & _
"-replyto " & SupportAddr
With CreateObject("WScript.Shell")
.Run Cmd, 1, True
End With
If (Err) Then
Send = 1
Else
Send = 0
End If
end function
function SendToMobileWithAttach(Subject, Body, AttachPath)
On Error Resume Next
Dim Cmd: Cmd = BlatPath & " - -to " & ProductionAddr & "," & MobileAddr & " " & _
"-s """ & Replace(Subject, """", "'") & _
"-body """ & Replace(Body, """", "'") & _
"-attach """ & AttachPath & """ " & _
"-from " & FromAddr & " " & _
"-replyto " & SupportAddr
With CreateObject("WScript.Shell")
.Run Cmd, 1, True
End With
If (Err) Then
Send = 1
Else
Send = 0
End If
end function
Once that's saved, you can right click on the .wsc file that was generated and click 'Register'. This registers your component within the registry and allows other programs or scripts to locate and use your component, which is done by creating a Support.Email object. Here's an example of how this works in VBScript:
With CreateObject("Support.Email")
.SendToMobile "Server1 Reboot Alert!", _
"Alert Timestamp: " & Now & VBCrLf & _
"Server1 has rebooted."
End With
Easy peasy, huh?
