Monday, April 23, 2007

Fun with COM Interop.

The joy of registering .NET components for COM Interop is a most masochistic delight.

I am creating an Explorer extension for filtering the displayed files and folders to user-specified criteria. Basically, I want a simple Explorer bar not unlike the Google or Yahoo! or the myriad of other tool bar vendors. I am calling the tool, ExplorerFilterBar. Clever, huh?

After no small amount of cursing, here are the steps I took to get my toolbar running. Not working, just running. :-)

I begin by creating my ExplorerFilterBar C# Library project. I will eventually set it up for COM Interop and other stuff but we will get back to that.

My jumping off point is using the BandObjectLib, created by Pavel Zolnikov on CodeProject.com, for the basis of the Explorer Band. The only changes I made to the source were to recompile the application in .NET 2.0. The original source for the base band object can be found here: Extending Explorer with Band Objects using .NET and Windows Forms.

To use the BandObjectLib in my shell application I have to register it for COM Interop. I did this by copying the BandObjectLib.dll to a new folder and registering and creating a new type library.


C:\Program Files\BandObjectLib\bin>regasm /tlb BandObjectLib.dll
Microsoft (R) .NET Framework Assembly Registration Utility 2.0.50727.1318
Copyright (C) Microsoft Corporation 1998-2004. All rights reserved.

Types registered successfully
Assembly exported to 'C:\Program Files\BandObjectLib\bin\BandObjectLib.tlb', and the type library was registered successfully

C:\Program Files\BandObjectLib\bin>


Now we have a registered COM component that I will be able to extend to create Explorer bars. I can verify that the COM wrapper has been created by checking the references dialog and looking for "BandObjectLib". If it's there you are in good shape, if not, close VS.Net and then try again.

To begin creating my new toolbar I need to add a reference to the BandObjectLib.dll that I just registered with COM.

With my new reference I can create a new UserControl so I have a designer window for my toolbar.



using System.Runtime.InteropServices;

using BandObjectLib;

 

namespace FrogsBrain.ExplorerFilterBar

{

    [Guid( "29CF65E4-A7F8-4352-B55A-7EE413A64743" )]

    [BandObject( "Explorer Filter Bar", BandObjectStyle.Horizontal | BandObjectStyle.ExplorerToolbar | BandObjectStyle.TaskbarToolBar, HelpText = "Filter the contents of the Explorer window." )]

    public partial class ExplorerFilterBarControl : BandObject

    {

        /// <summary>

        /// Initializes a new instance of the <see cref="ExplorerFilterBarControl"/> class.

        /// </summary>

        public ExplorerFilterBarControl()

        {

            InitializeComponent();

        }

    }

}




Drag a button onto the form designed and set its Dock property to "Fill". You can delete it later, it's just for demonstration.

Now you are ready to setup for project for COM Interop.

The changes we are about to make have to be applied for the "Debug" and "Release" builds, so set your Project Property Configuration to "All Configurations".

Under the "Application" tab, click the button "Assembly Information". In the dialog box that is displayed check the "Make assembly COM-Visible". Then click "OK".

Create a strong name key file for the project.

Set the project to register and GAC your DLL. Add the following "Post Build" event. Obviously you will need to update the paths as appropriate for your configuration.


cd "$(TargetDir)"
"c:\windows\microsoft.net\framework\v2.0.50727\regasm.exe" /u $(TargetFileName)
"c:\program files\microsoft visual studio 8\sdk\v2.0\bin\gacutil.exe" /uf $(TargetName)
"c:\program files\microsoft visual studio 8\sdk\v2.0\bin\gacutil.exe" /if $(TargetFileName)
"c:\windows\microsoft.net\framework\v2.0.50727\regasm.exe" $(TargetFileName)


Under the Build tab, check the "Register for COM interop" box.

And for the last property dialog change, set the start action under the Debug tab to launch the Window's Explorer when you start the debugger.

The final step to setting up your DLL for COM Interop is the manually open your AssemblyInfo.cs file and set the ComVisible attribute to True.



    1 // Setting ComVisible to false makes the types in this assembly not visible

    2 // to COM components.  If you need to access a type in this assembly from

    3 // COM, set the ComVisible attribute to true on that type.

    4 

    5 [assembly : ComVisible( true )]




Now you should be able to run your application. Watch the Output window to see if any error messages are being generated by the RegAsm or GacUtil utilities, this will help with determining what problems occurred if the application won't build.

If everything went well you should be staring at a default Explorer window. You should now see a new option when you add a tool bar containing the name entered for the toolbar.

Submit this story to DotNetKicks

1 comments:

Graham said...

Hey - I'd be interested to see how you used BandObjectLib to get at information such as currently selected file(s)/folder(s). Are you publishing any more details?!