Introduction
I was inspired to write this article after seeing this article by Kant. Kant wrote a utility that allows creation of quotes collection and saving in XML format. User can chose to copy a random quote to the clipboard which can be pasted in the signature field when posting a message to a CP message board. The same feature is also available in Desktop Bob. I imagined that it would be kind of nice if a random quote automatically got into the signature field. This utility does that. When you install the utility and navigate to any url in CP from where you can post a message, the signature field is automatically filled with one of the quotes from an XML file. All you need to do is to write some quotes in an XML file either manually or using the CodeProjectQuote utility. A default XML file (copied from Kant's article) is provided with the setup and the source.
Installation and Use
Here are the steps you need to take to install and use the utility.
- Download and extract the setup zip file
- Double click on the AutoSigSetup.msi from Windows Explorer. You need to have windows installer 2.0 on your machine. It is very likely that your system already has it. You also need to be an administrator on the machine to install the utility.
- Navigate to a URL in code project from where you can post a new message. The signature field is automatically filled in. Every time you renavigate (not refresh) to this page a different signature comes up. Note that your default signature will be replaced. If you want to keep your default sig just rfresh the page.
- Obviuosly you will need to add your own quotes to the signature XML file. The default installation of the utility places an XML file named sigs.xml in the same folder as the app itself (Although this is not a very good practice in general). You can edit the file there itself.
- If you chose you can point to a different location for the signature XML file by modifying the registry value SigFilePath under the key HKEY_CURRENT_USER\Software\CodeProject\AutoSig. The string data you place in this registry value should be the full path of the new signature XML file.
Building the Code
If instead of using the installation app you decide to build the utility yourself, you need to take the following steps.
- Download and extract the source zip file
- Open AutoSig2000.sln if you are using VS.NET 2002 or AutoSig.sln if you are using VS.NET 2003.
- Build the solution.
- Open a command prompt window and go to the output directory of the AutoSig2002 or AutoSig project
- Type Regasm /codebase AutoSig.dll . This will register the utility.
- Copy sigs.xml file to the output directory or see step 5 in the Installation and use section to specify a different path
- Edit sigs.xml file to add your own quotes
How it Works
The utility is a Browser Helper Object. A Browser Helper Object is a COM object that is instantiated for every Internet Explorer browser window. Internet Explorer passes the IWebBrowser2
interface pointer to the Browser Helper Object. It is upto the Browser Helper Object to make use of it in whatever way it wants to. The BHO needs to implement the COM interface IObjectWithSite
. In C# the interface looks like this.
[
ComVisible(true),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352")
]
public interface IObjectWithSite
{
[PreserveSig]
int SetSite([MarshalAs(UnmanagedType.IUnknown)]object site);
[PreserveSig]
int GetSite(ref Guid guid, out IntPtr ppvSite);
}
Internet explorer calls the
SetSite
method after it instantiates the BHO. The
site
parameter is actually an object which implements
IWebBrowser2
interface. In case of AutoSig the implementation of this method reads configuration values from the registry and adds an event handler to the
DocumentComplete
event and stores the object in a member variable. When Internet Explorer window closes, it calls the
SetSite
method again passing a
null
value. The AutoSig BHO removes the event handler when such condition occurs.
if (site != null)
{
webBrowser = (WebBrowser)site;
webBrowser.DocumentComplete +=
new DWebBrowserEvents2_DocumentCompleteEventHandler(
this.OnDocumentComplete);
}
else
{
webBrowser.DocumentComplete -=
new DWebBrowserEvents2_DocumentCompleteEventHandler(
this.OnDocumentComplete);
webBrowser = null;
}
Now everytime the browser completes navigation to a web site the OnDocumentComplete
method is called. The code in this method does the following:-
- Checks whether the naviagtion URL belongs to one of the CodeProject domains.
- If the above condition was true it sees whether the URL is one used in CP to post a message to a forum (either a new message or a reply).
- If both the conditions are true. The code obtains a reference to the DOM object corrensponding the the textarea element where the user types a signature.
object sigObj = document.all.item(destElemId, 0);
IHTMLTextAreaElement sig = sigObj as IHTMLTextAreaElement;
- Now all that needs to be done is to get a signature from the XML file and assign it to the
value
property of the textarea. This is done asynhcronously for the simple reason that reading from the XML file may take some time during that time the user can still continue typing his message. In practice however I find that the time taken is negligible. The XML file could have been read at once and stored in memory but I prefer conserving memory as much as possible so the file is read each time. The asynchronous call is done using an asynchronous delegate.
SetRandomSigDelegate delg = new SetRandomSigDelegate(
this.SetRandomSig);
delg.BeginInvoke((IHTMLTextAreaElement)sig,
new AsyncCallback(this.OnAsyncCallComplete), delg);
The SetRandomSig
method which gets called from a thread in the threadpool reads the xml file and selects a value from it and places it in the textarea.
Final Comments
I hope the utility proves useful to fellow CPians. Currently there is only one known bug, that is when the page is refreshed the signature is not set. This happens because the DocumentComplete
event does not get fired. Any suggestions on how to solve this problem is welcome. Thanks to Kant and Daniel Truni for providing inspiration for the article.
Update July 2, 2003
A common problem people faced was that the installation app did not work. This was because microsoft.mshtml.dll - an assembly required by the project was not included with the setup. This was done because this file increased the setup size to almost 2 MB. In this version now the dependency on the assembly is removed. Instead I have created a new assembly called mshtmlsubset.dll which includes only those interfaces used by AutoSig. This reduces the size of installation drastically.
History
- July 2, 2003 - Fixed to remove dependency on mshtml.tlb
- June 7, 2003 - Initial Release