by Doug Schwartz
March 2, 2007
Introduction
The latest major release of AOL instant messaging, AIM 6, includes support for plugins, which are pieces of code that add features and functionality to the AIM client. This article discusses how you can create a simple plugin in C# using the Microsoft .NET framework. This plugin lets the user translate their message using a scheme where letters are shifted 13 places--"a" becomes "n" and so on. What this plugin really demonstrates is how you, the developer, can intercept the instant message (IM) before it is sent by the user, and do whatever you want with the text.
What Do I Need to Develop a Plugin?
- The first step is to get an account on the AIM developer website.
- Next, get a developer key for your plugin. There are different keys for different stages of development. For now, you need only a developer key. Later on, if you decide to make your plugin available to others, you will need a deployment key. To get a key, go to the AIM Plugin Registration web page and follow the instructions. You will need the key value to run your plugin.
- Once you have registered, you can download the SDK. This article leads you through creating a C# plugin,
Rotate. For the complete source for this article, see Source Code.
Creating the Plugin
I used Visual Studio 2003 to create the source code for this plugin. If you are using a different version, such as Visual Studio 2005, there may be some slight variations in the location of some settings. At worst case, you can grab the source, open it in Visual Studio 2005, and it will convert the project to the newer version.
We are going to create the plugin in the following order:
Creating the C# Project
Perform the following steps to create the Rotate project:
- Open Visual Studio
- Click File -> New -> Project.
- In the Project Types section, select Visual C# Projects.
- In the Templates section, select Class Library.
- In the Name section, enter Rotate.
- Enter "C:\Plugins" in the Location section.
- Click OK
Your project window should look like Figure 1.

Figure 1. The new project settings
Configure the Project to Use COM
The library that comes with the SDK is written to use the Microsoft Common Object Model (COM). To use this type of library with the .NET framework, we must add a project setting.
- Select Project -> Rotate Properties.
- In the Configuration section, select All Configurations.
- In the left window, select Configurations, and then Build.
- In the right window, set the Register for COM Interop setting to true.
- Click OK.
Your property window should look like Figure 2.

Figure 2. The Rotate project settings
Creating a Reference to the SDK Library
To create a reference to the SDK library, AccCoreLib.dll, perform the following steps:
- Select Project -> Add Reference.
- Click the COM tab.
- Click Browse and navigate to the folder where you installed the SDK, and then dist\release and select acccore.dll.
- Make sure the component name appears in the bottom window, and click OK.
Your reference window should look like Figure 3.

Figure 3. The COM reference
You also must create references to two .NET libraries,
System.Drawing.dll and System.Windows.Forms.dll. Add these references by selecting Project -> Add Reference, clicking the .NET tab, selecting the System.Drawing and System.Windows.Forms components, and clicking OK.
Your reference window should look like Figure 4.

Figure 4. The Windows references
Adding Self-Registering
Self-registering allows your application to add information to the registry so that your plugin is known to AIM. Add the following code to your class:
#region Plugin Registration
[ComRegisterFunctionAttribute]
public static void RegisterFunction(Type t)
{
RegistryKey key = Registry.LocalMachine.CreateSubKey(PluginKeyName(t));
key.SetValue("Name", t.Name);
}
[ComUnregisterFunctionAttribute]
public static void UnregisterFunction(Type t)
{
Registry.LocalMachine.DeleteSubKey(PluginKeyName(t));
}
private static string PluginKeyName(Type t)
{
return "Software\\America Online\\AIM\\Plugins\\" +
'{' + t.GUID.ToString() + '}';
}
#endregion
Implementing the Interfaces
Now that we have a reference to the COM library, let's use some of that code. We are going to implement the IAccPlugin and IAccCommandTarget interfaces.
But first, to keep from getting errors as we implement these interfaces, add the following declarations to the top of your Class1.cs source file:
using System.Drawing; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; using Microsoft.Win32; using AccCoreLib;
Now we are going to change our class declaration to include a reference to our developer key (replace DEVELOPER_KEY in the following code with the key value) and the two interfaces we use from the SDK. Change your class declaration from:
public class Class1
to:
[GuidAttribute("DEVELOPER_KEY")]
public class Class1 : IAccPlugin, IAccCommandTarget
NOTE: The source to this article does not have a GUID. You must get a key to run the plugin.
As you enter the interface names,
Visual Studio will prompt you to press the Tab key to create empty
methods to implement the interfaces.
You should then have two new regions,
IAccPlugin Members and
IAccCommandTarget Members.
The next step is to add code to the empty methods in these regions.
Before we implement these methods, we need to create some variables; otherwise, we will get errors as we implement the methods. At the top of the class, just above the empty constructor, add the following declarations:
const int kCommandId = 0; private AccSession m_session; private bool xlate = false;
The first declaration creates a constant value that represents a command. The second is a session object we use to keep track of user preferences. The last is a Boolean that tells our plugin whether to translate the text message.
Let's implement some methods. Find the Init method in the IAccPlugin region and add the following code:
this.m_session = session; IAccCommand command = pluginInfo.AddCommand(kCommandId); command.set_Property(AccCommandProp.AccCommandProp_Text, "Toggle Translation"); this.m_session.BeforeImSend +=new DAccEvents_BeforeImSendEventHandler(m_session_BeforeImSend);
As soon as you type "+=" after this.m_session.BeforeImSend,
Visual Studio prompts you to press the Tab key to add the rest of the statement,
and then prompts you to create the empty m_session_BeforeImSend method to handle the
BeforeImSend event. We will add code to this event handler in a moment.
Add the following code to the Shutdown method:
this.m_session = null;
This releases the memory we use to keep the preference information while our plugin is loaded.
Add the following code to the m_session_BeforeImSend method:
if(this.xlate)
{
im.Text = this.transmogrify(im.Text);
}
Let's implement the transmogrify method. I am not going to show all 52 case statements, but you get the idea.
private string transmogrify(string s)
{
StringBuilder output = new StringBuilder();
char[] chs = s.ToCharArray();
for (int i = 0; i < s.Length; i++)
{
switch(chs[i])
{
case 'a':
output.Append("n");
break;
// ...
default:
output.Append(chs[i].ToString());
break;
}
}
return output.ToString();
}
Figure 5 shows an example of the rotated text.

Figure 5. A rotated "Hello world"
Creating an Action and a Preferences Form
Actions are commands that the user invokes at the bottom of the IM page. The preferences form is displayed whenever the user wants to set the preferences for the plugin. We are going to create a simple action that toggles between sending translated text and plain text. We are going to create a form with two buttons so the user can select whether to send translated text or plain text.
The Exec method is called when the action associated with the plugin is selected; the QueryStatus method is called when the user selects the plugin preferences. By default, QueryStatus returns false, but since we are going to let the user set a preference, we want to return true when the command is to set the preferences.
Replace the existing code in the QueryStatus method in the IAccCommandTarget region with the following code:
if (command == (int)AccCommandId.AccCommandId_Preferences || command == kCommandId)
{
return true;
}
else
{
return false;
}
Add the following to the Exec method in the IAccCommandTarget region:
if (command == kCommandId)
{
if(!xlate)
{
MessageBox.Show("Translation is enabled");
this.xlate = true;
}
else
{
MessageBox.Show("Translation is disabled");
this.xlate = false;
}
}
else if (command == (int)AccCommandId.AccCommandId_Preferences)
{
Form MyForm = new Form();
MyForm.AutoScaleBaseSize =
new System.Drawing.Size(5, 13);
MyForm.ClientSize =
new System.Drawing.Size(292, 266);
MyForm.Text = "Plugin Settings";
Label label1 = new Label();
label1.Font =
new System.Drawing.Font(
"Microsoft Sans Serif",
8.25F,
System.Drawing.FontStyle.Bold,
System.Drawing.GraphicsUnit.Point,
((System.Byte)(0)));
label1.Location =
new System.Drawing.Point(32, 24);
label1.Name = "label1";
label1.Size =
new System.Drawing.Size(144, 23);
label1.TabIndex = 0;
label1.Text = "Translate the IM text?";
MyForm.Controls.Add(label1);
Button button1 = new Button();
button1.Location =
new System.Drawing.Point(40, 208);
button1.Name = "button1";
button1.TabIndex = 1;
button1.Text = "Yes";
button1.Click +=
new System.EventHandler(this.button1_Click);
MyForm.Controls.Add(button1);
Button button2 = new Button();
button2.Location =
new System.Drawing.Point(144, 208);
button2.Name = "button2";
button2.TabIndex = 2;
button2.Text = "No";
button2.Click +=
new System.EventHandler(this.button2_Click);
MyForm.Controls.Add(button2);
MyForm.Show();
}
Once again, as you type the "+=," Visual Studio creates the empty event handler. You need to change these two methods as follows:
private void button1_Click(object sender, System.EventArgs e)
{
this.xlate = true;
}
private void button2_Click(object sender, System.EventArgs e)
{
this.xlate = false;
}
Figure 6 shows what this form looks like when the user selects Edit -> Settings -> Plugins -> Rotate -> Settings.

Figure 6. The preferences form in action
Figure 7 shows what the user sees in the Actions menu:

Figure 7. The "Toggle Translation" action
Figure 8 shows what the user sees the first time they select this action:

Figure 8. Selecting the "Toggle Translation" action the first time
Conclusion
Now you understand how to create a simple plugin. If you are feeling brave, take a look at the SDK and try to figure out how you would create a plugin for the recipient of the translated text. Which event would you trap? (Hint: the answer is below, in white text on this white background. Just highlight the bracketed word on the following line and you can see the answer.)
[BeforeImReceived]
Source Code
The source code discussed in this article is available in the following .zip files.
- rotate.zip contains the complete source code for this article
- unrotate.zip is a simple Windows form utility that you can use to unrotate text. Just copy the rotated text from the IM window into the text field and click the Unrotate button. I've included the source in case you are interested.
References
Here are a number of web pages where you can get further information about plugins.
- AIM Plugin is the web page dedicated to plugin developers
- The AIM Developer FAQ contains additional information about Open AIM and AIM plugins
- AOL Developer Resources contains a wide variety of developer resources
- AIM Plugins Forum: Ask and answer questions about plugins
- gbcypes's blog is an AOL Developer Network blog written by Greg Cypes, one of the AOL developers who wrote many of the AIM plugins
- Gregs blog is Greg's blog on journals.aol.com
- AIM Developer Key Management is where you go to get a deployment key for your plugin
