Developers‎ > ‎Creating AddOns‎ > ‎

Scripted Extensions Reference


Not limited to what they can do.

Snarl handles registration; extension just provides info.


Setting Up

Each script extension must be in its own folder.  There is no set naming convention but, in order to avoid naming clashes, the recommendation is to use a folder name that follows this template:


For example:


Within the folder, there must be a script file called script.vbs which contains the extension's code.  Other files (for example, icons) may also be included in this folder, and can be retrieved by the script using the ScriptExtension object's Path property.

The extension script must supply a series of procedures - known as "hooks" - which Snarl can call when it needs the extension to do something.  Only one hook - ext_Init() - is mandatory.


Every extension must support an ext_Init() hook.  This is called by the extension loader while Snarl starts up.  The return value is not important here at present, although for compatibility with future releases of Snarl, the extension should return zero.

Prior to the call to ext_Init(), Snarl will create a ScriptExtension object and make it visible to the script with the object name of sx.  In order to be loaded successfully, the extension must populate the ScriptExtensionInfo object referenced by sx.Info.  The extension should complete all fields, however only the Name and Vendor fields are mandatory.

Function ext_Init()

  sx.Info.Name = "Current Time"
  sx.Info.Vendor = "Acme Software Corp"

End Function

An extension can indicate it has a problem which prevents it from starting by setting the Error field to a non-zero value and entering a description of the problem in the Reason field, as follows:

Function ext_Init()

  sx.Info.Error = 201
  sx.Info.Reason = "Requires Windows 7 or later"

End Function

Starting and Stopping

Extension can provide either ext_Start(), ext_Stop() or both hooks.  If provided, ext_Start() is called when the extension is enabled; ext_Stop() is called when the extension is disabled.

Currently, Snarl only ever calls these two functions as part of its startup and shutdown code, however a future release may allow the end user to selectively stop individual extensions under circumstances (when they are away or busy for example).

Adding Classes

Classes are added and removed using AddClass() and RemoveClass() respectively.

Creating Notifications

An extension can use either Show() or ShowEx() to create notifications.  ShowEx() allows a completely free-form notify command to be sent to Snarl and is therefore more powerful, but slightly more complex to use than Show() which requires a series of optional parameters.

Responding to Events

text here

Regular Pulses

Extensions can receive a pulse at a regular interval.  An extension indicates it wishes to receive a pulse by including an ext_Pulse() hook.  The default frequency is 250 milliseconds; this can be changed through a call to SetPulseRate().

Tidying Up

When an extension is unloaded, Snarl calls its ext_TidyUp() hook, if it exists.  An extension would typically free any resources it has allocated during its lifetime here.

Object Reference


Hooks are procedures which are called in response to various asynchronous events.  A script only needs to define hooks for which events it wants to know about, however all scripts must define an ext_Init() hook.  Some functions rely on certain hooks begin defined - for example, SetPulseRate() will ignore any value passed to it if the script does not define an ext_Pulse() hook.


Sub ext_AsyncWebRequestDone(Success As String, Content As String)

Called whenever a request initiated by DoAsyncWebRequest() completes. Success will be "1" if the request was successful; "0" if it wasn't.  If the request was successful, Content will contain the data retrieved from the URL.

Note that no sanity checking of the returned content is performed, so if the URL used points (for example) to a missing web page, it's more than likely that Content will contain the HTML code of a 404 error.


Sub ext_Init()

Called when the extension is first loaded by Snarl.  The extension should complete the required elements of sx.Info or indicate a failure by setting sx.Info->Error and sx.Info->Reason accordingly.  All extensions must provide this hook - see Initialising for more information.


Sub ext_NotificationAction(UID As String, Identifier As String)

Called when the user selects an item from the Actions Menu of a notification created by either Show() or ShowEx(). UID will contain the unique identifier assigned to the notification when it was created; Identifier will be the identifier assigned to the action selected.

Note that Snarl does not automatically remove a notification when an action is selected; your application should use Hide() if it wants to remove the notification after a particular action has been performed.


Sub ext_NotificationClosed(UID As String)

Called when a notification created by either Show() or ShowEx() is closed in response to the user clicking the notification's Close gadget. UID will contain the unique identifier assigned to the notification when it was created.


Sub ext_NotificationInvoked(UID As String)

Called when a notification created by either Show() or ShowEx() was invoked by the user (invoking constitutes the user pressing and releasing the mouse button on any part of the notification not obscured by a gadget) . UID will contain the unique identifier assigned to the notification when it was created.


Sub ext_NotificationTimedOut(UID As String)

Called when a notification created by either Show() or ShowEx() disappears due to its duration expiring.  UID will contain the unique identifier assigned to the notification when it was created.


Sub ext_Pulse()

If defined by an extension, this hook will be called at regular intervals.  The default interval is 250 milliseconds and can be changed by calling SetPulseRate().


Sub ext_Start()

Called when the extension is started.  This occurs whenever the extension is first loaded (assuming it responded positively to ext_Init()) and subsequently when it is restarted.


Sub ext_Stop()

Called when the extension is stopped.  This occurs just before the extension is unloaded (and before ext_TidyUp()) and subsequently when it is stopped.


Sub ext_TidyUp()

Called immediately before the extension is unloaded.  An extension should take hook as an opportunity to release any resources it may have acquired.



Sub AddClass(Identifier As String, Name As String, [Enabled As Boolean = True], [DefaultTitle As String], [DefaultText As String], [DefaultIcon As String], [DefaultSound As String][DefaultCallback As String])

Adds a notification class. Identifier is the internal name used in subsequent calls to Show() and ShowEx(); Name is displayed in the application list in Snarl's preferences panel.  If Enabled is set to FALSE, the class will be disabled by default, otherwise it will be enabled.

DefaultTitle, DefaultText, DefaultIcon, DefaultSound and DefaultCallback are all optional and, if provided, will be used in subsequent notifications where no corresponding item is provided.


Sub CancelAsyncWebRequest()

Cancels any asynchronous web request initiated by DoAsyncWebRequest().

This function does nothing if no web request is currently in progress.


Function DoAsyncWebRequest(URL As String, [TimeoutInSeconds As Long = 5], [Username As String], [Password As String]

Initiates an asynchronous download of content from URL.  TimeoutInSeconds can be used to adjust the amount of time that may elapse before the request is cancelled.  Username and Password may be provided if authentication to the site hosting the URL is required.

The script must provide an ext_AsyncWebRequestDone() hook which receives the retrieved content when the request completes.

This function fails if an existing web request is currently in progress - call CancelAsyncWebRequest() to immediately terminate any existing request.


Sub Hide(UID As String)

Hides the notification identified by UID.

Care should be taken when programmatically removing notifications from the screen.  See Notification Guidelines in the Developer Guide for more information.


Function PulseRate() As Long

Returns the current pulse rate for the extension.  The default is 250 milliseconds.


Sub RemoveClass(Identifier As String)

Removes the notification class referenced by Identifier which was previously added using AddClass().


Sub SetPulseRate(Milliseconds As Long)

Sets the pulse rate for the notification.  Milliseconds indicates the frequency of the pulse and must be at least 100.  The extension must provide an ext_Pulse() hook for this function to have any effect.


Sub Show(Class As String, UID As String, [Title As String], [Text As String], [Icon As String], [Callback As String], [Duration As Long = -1], [Priority As Long = 0], [Sensitivity As Long = 0], [Actions As String])

Creates a notification.  Class is the notification class identifier to use for the notification; UID is used to subsequently identify the notification if its content should be updated, and when a hook is called.

Title and Text are the notification's title text and body text respectively; Icon is the icon to use (see the Icons section in the Developer Guide for more information about valid icon formats).

Duration indicates the amount of time, in seconds, the notification should be displayed for.  Generally speaking this should remain at the default of -1, which indicates the user-defined global setting within Snarl should be used.

If Callback is provided, then Snarl will launch the file or open the URL pointed to by it.  Note that the ext_NotificationInvoked() hook is not called if a callback is provided here.  See the Callbacks section of the Developer Guide for more details.

Priority indicates the urgency of the notification.  Typically this should be left to the default value of zero (normal) - see Notification Priorities in the Developer Guide for more information.  Similarly, Sensitivity indicates whether or not the notification contains sensitive information.  Certain styles alter how they handle notifications based on the sensitivity rating - see Sensitive Notifications in the Developer Guide and the documentation for the style in question for more information.

Actions should consist of one or more "Label,Identifier" entries separated by semi-colons - see the example below.


The following creates a high priority, confidential notification with three actions:

Show("newmail", _
     "new_mail", _
     "New mail from Peter Drake", _
     "Subject: Operation CORNERSTONE", _
     "!message-new-mail", _
     "", _
     -1, _
     1, _
     48, _



Sub ShowEx(Byval Request As String)

Allows the extension to send a free-form notify command.  Request is prefixed with "notify?" and the extension's signature and password before being passed to Snarl.


The following creates a notification with a tile, some text, and a meter set to 30% (if the style displaying it supports meters).  It also includes the custom variable "custom-foo" set to "bar".

ShowEx("title=Complex notification&text=With a meter&uid=^^complex^^&value-percent=30&custom-foo=bar")



InfoRead only: the ScriptExtensionInfo object associated with the extension
PathRead only: contains the path to the extension's script file.
UserPath Read only: contains the path to Snarl's user configuration folder. 


The ScriptExtensionInfo object allows the script to provide information about itself and must be completed during the call to ext_Init().  It is accessed through the ScriptExtension.Info property.


SetValue(Name As String, Value As String)

Adds a custom item to the object.  This is reserved for future use.


NameRequired The name of the extension.
VendorRequiredVendor name.
AuthorOptionalThe extension's author.
CopyrightOptional Copyright information.
DescriptionOptionalMore detailed explanation of what the extension does.
ErrorOptional Set to a non-zero value to indicate and error occurred.
IconOptional Icon to use, see notes below.
Reason OptionalMore detailed explanation of the problem if error is non-zero.
SupportURL Optional Support website.
VersionOptional Version information.


  • Icon can be a fully qualified path to an image on a local or remote filesystem, a URL, a standard Snarl icon (if prefixed with '!') or an HICON (if prefixed with '#').  If no icon is provided, Snarl will attempt to use the application's own icon - see the Icons section in the Developer Guide for more information
  • Name and Vendor are used to create the extension's signature


The following examples demonstrate the different features available.

Time of Day

This example uses the ext_Pulse() hook to display a notification showing the current time.  The pulse rate is set to 0.9 seconds as it doesn't need to be any more frequent than that.  On each pulse, a notification with UID "_the_time_now" is displayed.  Using the same UID saves screen real-estate as any existing notification will be updated rather than a new one created.  When the extension is stopped, the notification is removed immediately.

Function ext_Init()

  ' // configure only the most basic info
  sx.Info.Name = "Current Time"
  sx.Info.Vendor = "your-name-here"

End Function

Sub ext_Start()

  ' // default pulse rate is 250ms which is too much for us, so let's set it to a more sedate 0.9 secs
  sx.SetPulseRate 900

End Sub

Sub ext_Pulse()

  ' // by simply having this procedure defined, we tell the extension handler we want a regular
  ' // pulse, so let's show the current time in a notification
  sx.Show "", "_the_time_now", Now()

End Sub

Sub ext_Stop()

  ' // let's be kind and tidy up our annoying notification immediately
  sx.Hide "_the_time_now"

End Sub

External IP Address

This example shows how to use DoAsyncWebRequest() to retrieve the computer's current external IP address from  Again, we use the ext_Pulse() hook, but this time set it to only fire every 5 minutes.  Note that a notification is only displayed if the IP address has changed next time the request completes.

Dim CurrentIPAddress

Function ext_Init()

  ' // configure only the most basic info
  sx.Info.Name = "External IP Address Changes"
  sx.Info.Vendor = "your-name-here"

End Function

Sub ext_Start()

  ' // default pulse rate is 250ms which is too much for us, so let's set it to a more sedate 5 minutes
  sx.SetPulseRate 300000

  ' // kick-off our request now

End Sub

Sub ext_Pulse()

  ' // by simply having this procedure defined, we tell the extension handler we want a regular
  ' // pulse, so let's show the current time in a notification
  sx.DoAsyncWebRequest "url_removed"

End Sub

Sub ext_Stop()


End Sub

Handling Callbacks

This example shows how easy it is to create relatively complex notifications and also handle callbacks quickly and easily within a script environment.

Function ext_Init()

  ' // include a custom icon (sx.Path holds the path of the script)

  sx.Info.Name = "Demo"
  sx.Info.Vendor = "your-name-here"
  sx.Info.Icon = sx.Path & "icon.png"

End Function

Sub ext_Start()

  ' // display a bunch of notifications

  sx.Show "", "hello_world", "Hello, world!", "This is my first scripted extension", "!system-info"
  sx.Show "", "incoming#call", "Incoming call", "Steve Roberts (Home)", "!dun-connected", , , , ,   "Answer,@1;Ignore,@2;To Voicemail,@3"

  sx.Show "", "new$mail", "New email from Steve Roberts", "Subject: Have you seen this?", "!message-new_mail"
  sx.Show "", "im%received", "IM from Steve Roberts", "Don't read that email!", "!message-new_message"
  sx.ShowEx "title=Complex notification&text=With a meter&uid=^^complex^^&value-percent=30"

End Sub

Sub ext_NotificationInvoked(uid)

  ' // a notification was clicked, so display a messagebox showing the UID
  MsgBox uid, , sx.Info.Name

End Sub

Sub ext_NotificationAction(uid, data)

  ' // an action was selected, so display a messagebox showing the UID and the action identifier
  MsgBox "Action: " & uid & " > " & data, , sx.Info.Name

End Sub