Before I begin with the article let me first mention that this is my first article on CodeProject. I
have a habit of browsing through almost all of the articles on the net on VC++/MFC. I happened to come
across an article on a Plug-in Architecture
Framework for Beginners. I went through it and found it interesting and worth a try.

Introduction

Ever wondered how your applications can be made flexible/robust without providing the source code to
third parties. Well it's possible. A very common and "the" best example is "WinAmp", supporting
hundreds of plug-ins made by developers around the world. And the number increasing with each minute.

So what's behind this "Plug-In" thing???

To put it simply, it is a feature using which the applications look for various Add-Ins when starting up.
Once all the "Add-Ins" have been located they are loaded by the main app one by one, or selectively so as
to use their in-built features. These "add-ins" are normally DLLs in disguise. They could be residing in a
pre-defined directory or in the search path of Windows.

DLLs are the most effective way to implement plug-in functionality. Even Windows itself uses DLLs
extensively for most of its tasks. DLLs can be delivered easily as a patch or as an upgrade version, without
worrying about re-compiling the main application again and again. Once installed/copied they can be loaded at
runtime by the main application to use the functionality provided using exported functions/classes within the DLL.
Now many of you would question, that how would the application know what all functions are to be called?
The answer to this would be that, all the DLLs must conform to some basic, generic, pre-defined interface.
The call to the function (inside the DLL) can be issued only after knowing the function name. So the main app should,
beforehand, know what all the functions that can be called. So this is the reason why a generic/pre-determined
interface should be developed.

I hope all of you should be familiar with the DLL concept, so I will be starting with the actual
application itself.

Overview of steps involved:

So how should we go about making one??? The basic steps are as follows:

The main app is initialized (i.e. started)

The DLLs/Plug-Ins are searched in the directory (may be pre-determined)

Once "valid" DLLs are found, all or selected DLLs are loaded

"Init" function is invoked on all loaded DLLs

The instance and the DLL name/path are cached for future use (method invocation)

User uses the functionality of the DLLs (using GUI interfaces provided by the DLLs)

Once done, the main application invokes "Destroy" function of the DLLs one by one to free resources

The main application exits

Quite simple isn't it??? Well, it is simple given the concept. Actual implementations may be a bit on the
tougher side depending on how big a framework you are developing. My article is just a simple example,
describing the basic functionality used to develop such apps.

A detailed example:

First develop a regular Windows DLL in Visual Studio app-wizard (I used VS 7.0). Export a function
called InitPlugIn taking a CToolBar pointer as input and returning a
UINT, as given below:

Once this has been done, create the ID_BUTTON_PLUGIN_1 by going to the resource view, and
then selecting "Resource Symbols" menu option from the edit menu. Now create a 16x15 bitmap image in
the DLL resource. This image is supposed to show up on the toolbar of the main application which we
would be developing shortly. Name that bitmap IDB_PLUGIN_1.

The implementation of the SetToolBarPointer(), AddButtonToToolBar(),
RemoveButtonFromToolBar() methods is given in the demo app source code. You all can refer to that.
Basically SetToolBarPointer() stores the pwndToolBar pointer of internal use.
AddButtonToToolBar() uses this pointer to add a button dynamically to the main app's toolbar
when this DLL is initialized. RemoveButtonFromToolBar() does the opposite, it removes the button
when the DLL is un-loaded or destroyed.

Now this is some of the basic functionality we added to the DLL. There's more in the demo app. You can
refer to it's source code to learn more.

Now our next step would be to make the main application which would in turn use this plug in.

Create a Win32 executable SDI application from the app-wizard. Now our job is to enable the user to view all
available plug-ins in the directory and selectively load them. Since this process is a bit lengthy, but easy, so
you can refer to the source code again for this. As of now, I would be explaining the basic functionality you
have to provide.

According to the steps I described earlier, first we have to find-all available plug-ins. For this we can
use the _findfirst() and _findnext() C APIs defined in "io.h". You could
also use the CFileFind class instead. The code for this is given in the
PlugInSelectDialog::FindDLLs() method in the source code. It's job is to find the Plug-In file (*.PLX),
load it using LoadLibrary method, and then un-load it, verifying in the process whether it is a valid Plug-In or not.
The extension PLX is a custom defined, you can use .DLL instead. Just make sure to search for DLL files
instead of PLX files in the source code. The validation of the DLL can be done in various ways. I used a method
to extract the name of the DLL/plug-in by invoking an exported GetPlugInName function. If this function exists
and return a name then I consider it as a valid Plug-In. Users can use different methods that suite their needs.

Now before you look at the source code, I must mention that I have used a class named "CDLLManager" to
handle all the loading/un-loading of DLLs. This is just to make the code much more modular and easy to understand/debug.
This class holds all required information about each DLL loaded such as it's name, path, instance handle, toolbar button ID,
etc. It also takes care of initializing the DLL (remember the InitPlugIn() method) and also to destroy the
plug-in and free resources used by it (remember the DestroyPlugIn() method) These functions are invoked by
this class for each and every plug-in loaded. The sequence can be seen in the source code.

Now once the plug-ins are correctly loaded, new buttons would be added to the default toolbar of the main app. The
toolbar pointer of the CMainFrame class is passed as an argument while calling the InitPlugIn()
method of the plug-in. The function calls to the DLL can be made, by first calling the GetProcAddress() Win32
method to get the function address within the DLL/plug-in and then using that pointer to invoke that function. One thing to
remember is that we must free each and every DLL loaded once we are through with it, i.e. after using it. Otherwise,
resources may not be freed, and that is not a good thing to do. This can be done using the FreeLibrary() method.
CDLLManger class takes care of this using its destructor, where it calls its FreeDLL() method,
which destroys the DLL and then un-loads it.

Now, with all this done. the user should be able to use the plug-in at runtime by clicking on the toolbar buttons just
added. By default the buttons are disabled, since the compiler cannot find any "MESSAGE MAP" entries for it in the application.
And also we cannot add the message map entry beforehand as the "Main" application doest not know even if the plug-ins existed
or not beforehand, and also what resource IDs they use. After all, the main application has to be designed to be generic and
flexible. So this must be done at runtime (enabling the buttons and handling events on them).

To do this we override OnCmdMsg in the CMainFrame class. The method is given below:

In this method we catch the CN_UPDATE_COMMAND_UI event to enable the toolbar button, and we also catch the
CN_COMMAND event to handle the mouse buttons clicks on the toolbar button. To handle this we call
OnCallPlugInManager() method of the CMainFrame class, that in turn calls the PlugInEventHandler
function of the plug-in, passing all the required arguments. This function in the DLL, is supposed to re-direct the call
to CPlug_InApp::OnCmdMsg() method so that the DLL can handle the message intended for it.

In the demo app provided, the plug-ins don't do very important tasks. They just open the Notepad or Calculator window
depending on what Plug-In was invoked. This is just to explain the concept behind plug-in frameworks.

Problems and Limitations of the example provided:

As I have already stated that this example is not meant to be a full-blown framework for implementing plug-ins. It just
describes the basic steps involved to implement this functionality in your applications. It might seem a bit confusing at
first, but so was I when I first started. Believe me but it's not that tough though. Hopefully shortly I would be giving
a good update for this article, with the code optimized and easier to understand. So pardon me in case of any coding or
documentation problems. You all feel free to contact me for details and problems. :-)

I would not term the following as problems, but would rather refer to them as limitations or workarounds:

The message handling capability of the DLL

As of now I am not able to handle the messages such as clicking on the toolbar button in the DLL directly. The event has
to transferred from CMainFrame::OnCmdMsg() to the DLL's PlugInEventHandler() and from there to
the CPlug_InApp::OnCmdMsg(), so a single event has to travel this much so as to be handled by the DLL. I am not
impressed by this. Any possible "workarounds"? Any help in this regard would be highly appreciated. Actually this is what took
most of my time while developing this example application.

I would really like to handle DLL-specific events within the DLL itself, such as WM_LBUTTONDOWN,
ON_COMMAND, WM_MESSAGE, etc. I tried it before, but the message handlers are never called, may be
due to some silly mistake I had made. But anyways, due to the hurry to submit this code, I used to present method instead.

The DLL till now is not able to access the main applications resources, views, document, etc.

So no concrete work can be done as of now. For example I can draw anything on the view until I make a new function
PlugInDrawOnClient (CPlugSDIView *pView). But this involves sharing the header file PlugSDIView.h to
compile the plug-in, which till now I am not able to figure out what would be the best way to do this. It might come as an update
to this article. Hope I am able to take time out during my job soon, and update this article.

The code is not optimized fully, and may also be a bit confusing to browse through due to the similar variable names
I have used. I would definitely update this too.

While debugging the demo application, I found out that there is some bug in adding/removing toolbar button methods within
the DLL.

I say this due to that fact that upon deleting the toolbar button, the actual image count of the toolbar increases. I am, up to
now, unable to figure out why. You can re-produce this bug by constantly adding and then removing the plug-in a few times and then
checking the image count of the toolbar using the GetImageCount() method of the CToolBar class.

Conclusion

So, concluding my first article on CodeProject. I am jumping a bit up and down my seat. At last I've joined the herd after a
long time indeed! But anyways, I know that there would be a thousands silly mistakes and a million errors in the code, but still
for me it's an achievement. I spent a full day writing this article, and two weeks for developing the demo application, taking
my time out from office work. Hope my project manager does not get to know about it.

Any help to overcome the limitations I mentioned would be highly appreciated, especially the event handling limitation!

So till the next update, it's bye from me, and happy coding!!!

Credits

Mr. Jürgen Suetterlin for
providing me help on how to handle messages/events in the DLL, and how to enable the
toolbar buttons without using OnCmdMsg in the CMainFrame class. He has described to me a
method that would make it simple to decide what resource IDs to use in DLLs without the
ID define values clashing with each other.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Share

About the Author

Living in New Delhi (India). Did my Engg (Comp. Science) in 2000, and since then working on and off with VC++. It's my passion, and would really love to learn it to the very detail. Presently working as a software engg in a Telecom based firm. I've got around 3yrs experience in NMS (network management systems). Well thats all about me for now. Feel free to contact me...

To mimic the Winamp, any third-party could provide a plug-in dll and run it with Winamp immediately, which means, it is not necessary to recompile the code by including the correspodning lib files. But in your example, both 'Plug_In_1.lib' and 'Plug_In_1.plx' are needed. any idea about this?

I'm writing an exchange client extension application using visual c++, and I'm trying to get the handle of the popup menu when a user right mouse click on Message(mail ) in Outlook. And I want to add one menu item.

I'd like to handle the above event. I need help on getting handle of the coming popup menu whenever user right mouse clik on mail in outlook.

Hello,
I am trying to develop the Add-in for MS outlook in VC, I need to develop the component for toolbar and button which will loaded dynamically. Does anybody knows how to develop the component or provide some sample code so that I can get Idea

after using the scheme provided here, I have strange problem (even that I use the SAME code as in the example) - I can't add buttons to the toolbar. First, I found that I get for button count 0 - which was because I'm calling the dll from a modal dialog (which is the plug-in manager). Then, i switched to nomodal dialog, so that the dll may modify the main app toolbar, but I come to a crash here:

I solved my problems by pointers and all there glory.
http://retart.game-deception.com/module
http://retart.game-deception.com/files/Core%20Interface%20Public.zip
I still have lots work that needs to be done on it, but if you will take notice of STL usage in the classes which works perfect I might add. This is only allowed because of pointer usage. The class is in core module, the client only gets it's address, take notice the core modoule is also loading all DLL'(memory access owns ) so no problems arise from this. Also allows for dynamic exporting of anything, given a header with typedefs.
P.S.
This is one my on going projects I do work on it from time to time, it is by no means finshed in my eyes. Feel free to comment my work. Core Interface is closed source I will provide it on request only.
I can be found for chat here:
irc.rizenet.org
#game-deception
- RetarT -
Side Info about myself
I'm 19 years old and live in ohio.
I've only been programming for about 2 years.
Cheating and creating hacks for counter-strike, got me interested programming. Now I have I have moved on to really wanting to learn how to truly be a programmer.
I just seem have trouble with getting comments on my work :p.

Hi, I am now just learning about these DLLs myself and wanted to implement run-time plugins. Have you considered the approach of using an Extension DLL and DllMain() rather than the DLL instanciating another WinApp? Do you know whether msg/event handling in this case can be within the DLL or does it have to be within the main application?

I've done this already. I created an application that will load a dll dynamically using LoadLibrary function. In the DLL (implmented as MFC Extension DLL), I created a global function that retrun an instance of a dialog based from a basedialog on the Main Application. So, when I call the global function DLL in the main application, it can manipulte the dialog.

But there is again a limitation. If there is an event in the derived dialog and it needs to call a function in the main application, I dont know how to do it. I need to call a function in my View (SDI) from the DLL.

Hi Dears
I've to make a plug-in for MS Outlook. This plug-in will take a particular date, and will delete all the attchments of the e-mails which are older than that specific date.
Kindly guide me for the task. How can I start the task and which programming envirornment is best. Provide/guide me some sample code if possible. I'll be very grateful to you.
Waiting for your kind response.
Atif

Watch Your Thoughts for they will become your actions.
Watch Your Actions for they will become your habits.
Watch Your Habits for they will become your beliefs.
Watch Your Beliefs for they will determine your destiny.

Hello Dear
I'm student.
I also want to know how to add plug-in in outlook.
I've to make a plug-in for MS Outlook. This plug-in will take a particular date, and will delete all the attchments of the e-mails which are older than that specific date.
Kindly guide me for the task in ATL or VB or suggest some other. I'll be very grateful to you.
Waiting for your kind response.
Atif

Watch Your Thoughts for they will become your actions.
Watch Your Actions for they will become your habits.
Watch Your Habits for they will become your beliefs.
Watch Your Beliefs for they will determine your destiny.