TimeSnapper Plugin FAQ

If your question isn't answered here, you might also like to read the Plugin Development Wiki for TimeSnapper. For more in-depth help developing plugins, don't hesitate to contact us.

What is a TimeSnapper Plugin?

A plugin is a way of extending and customizing the way TimeSnapper behaves.

At the code level, it is a .net class that implements an interface (ITimeSnapperPlugin) that TimeSnapper will seek out talk to.

At the file level, a TimeSnapper plugin is a dll that ends with the word "Plugin" -- for example "SamplePlugin.dll". It sits in a subfolder called "Plugins" located under the TimeSnapper folder. For example "C:\Program Files\TimeSnapper\Plugins".

A plugin can subscribe to TimeSnapper events, and it can add items to menus inside TimeSnapper.

What events can a plugin subscribe to?

A plugin can choose to be notified when any of these things happen:

Where can a plugin extend TimeSnapper's menus?

In addition to subscribing to events, a plugin can tell TimeSnapper to put extra menu items into some of the context menus in the TimeSnapper application.

In particular a plugin can add menu items to these locations:

What can you do inside a plugin?

Just about anything you like, of course.

The standard answer we've given to tricky questions for the last year has always been "If you want to do that, you'll need to write a plugin".

A sample that ships with the latest version of TimeSnapper is called 'the Animated GIF' plugin. It lets you export a series of images as an animated gif.

Achieving this inside a plugin was quite trivial (we did it by following Jon Galloway's lead when he built the same plugin feature for Cropper. We tinkered with the NGif project at codeproject, and then leveraged public domain portions of the animated gif plugin that Jon wrote.)

Here are more ideas for plugins:

Connect to TFS, get outstanding tasks and assign time against them. Or -- connect to TFS, read what work items a user completed, and drop them into the timeline as flags.

Run over older images, resize them and/or convert them to lower resolution. Record current application activity in outlook Journal.

Integrate with a user's Outlook Calendar and note in the timeline that the user was in a meeting from 2-3pm instead of showing a gap.

How do I write a TimeSnapper Plugin?

Create a new project in visual studio, of type "Class Library". (In other words, we will be creating a DLL.)

Add a reference to "ITimeSnapperPlugin.dll"

Give a suitable name to your class, and then implement "ITimeSnapperPlugin"

using System;
using TimeSnapperPluginAPI;

namespace CSharpSamplePlugin { class AnotherPluginSample : ITimeSnapperPlugin {

Create a new guid. We'll use this to make sure our plugin doesn't clash with any other plugins.

Return the guid you've created, from the 'PluginID' property getter.

Return the name of your plugin from the "Friendly Name" property getter:

string ITimeSnapperPlugin.FriendlyName
get { return "My Sample Plugin"; }

Next, you should return a paragraph describing your plugin from the "Description" property getter.

string ITimeSnapperPlugin.Description
get { return "This plugin demonstrates some of the ways that plugins work."; }

The two properties above are used by TimeSnapper for providing information about the plugin, inside the 'Options' dialog:

How do I subscribe to an event?

When TimeSnapper first loads up our plugin, it will ask it which events it wants to subscribe to.

It asks this question by calling the "SubscribesTo" method.

From "Subscribes to" you return an array of enums, chosen from the enumeration "TimeSnapperEvent"

So, if you want your plugin to subscribe to the "Flag Saved" event and the "Snapshot Saved" event, you would write this code:

TimeSnapperEvent[] ITimeSnapperPlugin.SubscribesTo()
return new TimeSnapperEvent[] 
{ TimeSnapperEvent.FlagSaved, 
TimeSnapperEvent.SnapshotSaved };

How do I add menu items to TimeSnapper?

Similarly, when TimeSnapper loads up our plugin, it asks if there are any menu items it wants to add to any menus.

It asks this question by calling the "MenuItems" method, from which the plugin can return an array of TimeSnapperMenuItem classes.

How do I handle a TimeSnapper event?

When the event itself occurs, you are notified in a method called "HandleEvent".

In 'HandleEvent' you write a switch statement, (a Select case, in Visual Basic speak), with one case for each event you want to handle.

Select Case TimeSnapperEvent
Case TimeSnapperEvent.SnapshotSaved
MessageBox.Show("A snap shot saved!") 

Here's one for our example:

object ITimeSnapperPlugin.HandleEvent
(TimeSnapperEvent TimeSnapperEvent, EventArgs args)
switch (TimeSnapperEvent)
case TimeSnapperEvent.FlagSaved :
Debug.WriteLine("A flag was saved");
case TimeSnapperEvent.SnapshotSaved :
Debug.WriteLine("A snapshot was saved");
Debug.Assert(false, "Hey! I didn't subscribe to " + 
TimeSnapperEvent.ToString() + 
"... so this default case won't occur");
return null;

How can I let the end user configure my plugin?

Each plugin has a readonly Boolean property named "Configurable."

Most simple plugins do not need any configuration by the end user, so their authors would simply return 'false' from this property, like so:

bool ITimeSnapperPlugin.Configurable
get { return false; }

But if your Plugin is a little more complex, and requires the end user to configure it, you will want to return "true" from this property.

What exactly does that do? It means that the "Configure" button, in the "Plugin" tab of the Options dialog will be enabled, when your plugin is selected.

If "Configurable" returns true, then the button will be enabled. When the user presses the button, TimeSnapper will call the "Configure" method on your plugin.

It's up to you, as the plugin author, to decide what your plugin will do when the Configure method is called. You could show a modal windows dialog, you could launch a url inside a browser, you could show a WPF form -- anything you like.

It's also up to you how you will persist the user's choices across sessions (if required). You might for example, write an xml file into the user's app settings folder, or record settings in the registry.

Why do some of the events have 'Cancel' on the end of their name?

The full list of events you can subscribe to is provided in the enumeration TimeSnapperPluginAPI.TimeSnapperEvent and it looks like this:

public enum TimeSnapperEvent
SnapshotTakingCancel = 0,
SnapshotTakenSavingCancel = 1,
SnapshotSaved = 2,
AutoPoppingUpCancel = 3,
FlagSavingCancel = 4,
FlagSaved = 5,
PluginsLoaded = 6,
Closing = 7,
ArchivingCancel = 8,
Archived = 9,
SnapshotDeletingCancel = 10,
SnapshotDeleted = 11,

Some events have the word 'Cancel' on the end of their name, because they are events that give you the opportunity to Cancel an activity from occuring.

For example, if you subscribe to the SnapshotTakenSavingCancel event, you will be notified whenever a snapshot has been taken and it is about to be saved. You will have the opportunity to cancel the saving of the snapshot.

All events pass an 'eventArgs' parameter -- whose base class is the familiar .net class "System.EventArg".

The events whose name ends with cancel, pass through a subclass of this, using the familiar "System.ComponentModel.CancelEventArgs" derivation.

You cancel an event by setting the Cancel property of the event args to 'True'.

If you cancel an event, then no other plugin will see that event, and the action won't go ahead. (The saving won't occur, in this example.) You can think about that from another point of view as well: any other plugin may cancel an event before it gets to you.

Here is how you cancel an event...

Make sure the event is one of the ones that end in 'Cancel'. Cast it to a System.ComponentModel.CancelEventArgs, and set it's cancel property to true.

object ITimeSnapperPlugin.HandleEvent
(TimeSnapperEvent TimeSnapperEvent, EventArgs args)
switch (TimeSnapperEvent)
case TimeSnapperEvent.AutoPoppingUpCancel:
//No! we won't let the auto popup occurr...
((System.ComponentModel.CancelEventArgs)EventArgs).Cancel = true;

Here's a similar example in VB.net, where we stop a snap shot from being taken...

Public Function HandleEvent(ByVal TimeSnapperEvent As TimeSnapperEvent, _
ByVal args As EventArgs) _
As Object Implements ITimeSnapperPlugin.HandleEvent
Select Case TimeSnapperEvent
Case TimeSnapperEvent.SnapshotTakingCancel
'You plan to take a snapshot hey. Let me cancel that!
Dim realargs As System.ComponentModel.CancelEventArgs
realargs = CType(args, System.ComponentModel.CancelEventArgs)
realargs.Cancel = True 'Stop it from happening!

Can I download some sample code, in C#?

Here is a very simple example of a plugin, written in C#

Sample Plugin -- C# (zip)

Can I download some sample code, in Visual Basic .net?

Here is a very simple example of a plugin, written in Visual Basic .net

Sample Plugin -- Visual Basic.net (zip)

Can I download some sample code, in F#, IronPython and IronRuby?

Sorry, example are not currently provided in languages other than C# and VB.net. Why not write one and share it with the world?

Why isn't my plugin loaded?

TimeSnapper looks for plugins in a subfolder called "Plugins" located under the TimeSnapper application folder.

For example "C:\Program Files\TimeSnapper\Plugins".

Here's the trickiest part... TimeSnapper only looks inside files whose name ends with "Plugin.dll".

So for example, "SamplePlugin.dll" would be inspected for ITimeSnapeprPlugin's -- but PluginSample.dll would NOT be inspected and loaded.

Just repeating that one more time: your DLL's name must end with "Plugin.dll" or it will not be loaded.

(Why is this done? This is so that if a plugin references a lot of supporting dlls, they can live in that same folder, without slowing down the startup time for TimeSnapper.)

How can I debug my plugin?

If errors occur during loading or activating a plugin, details are written to the TimeSnapper log file.

Also, you can emit debug statements from your plugin, and then look at them using a debug listener, such as the one provided by sysinternals.

Can I share a plugin I've writen?

You are most welcome to share your plugins!

We intend to provide a gallery of plugins from on TimeSnapper.com, to encourage their usage, and I would like to further promote them on my blog at secretGeek.net.

It is still very early days, but we are hoping for some activity here.

Can I make money from writing plugins?

You certainly may.

You are welcome to sell or to give away your plugins. You can include your own licensing registration mechanism within your plugin if you wish. We don't ask for a share of any royalties from your plugin, if it does make money. The only caveat we have is that we insist you don't use your plugins to circumvent the goals of TimeSnapper, or to damage our existing licensing and protection.

What plugins are available?

Currently, the only plugins available are the Animated Gif plugin and the sample plugins. We hope to have more available soon. (Written March 2009)