Background:

VSPackages can offer up a set of custom properties for their Tools.Options pages, by registering the pages under Visual Studio's AutomationProperties registry key, by using the ProvideOptionPageAttribute. This allows for programmatic access to the Tools.Options properties via DTE.Properties(<categoryName>, <pageName>).

The Example.OptionsPage sample in the Visual Studio SDK is missing the following attributes on its DialogPage derived objects.

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]

Unfortunately, this mistake has been copied by many package partners (including internal teams here at Microsoft). Consequently, we occasionally see customers running into problems attempting to programmatically access Tools.Options properties with the above mentioned DTE.Properties interface.

Solution:

To help address this oft made mistake, Paul Harrington and Doug Hodges recently wrote the following macro which tests all VSPackages registered under AutomationProperties, to see which objects are implemented properly, and which are not. If you have a VSPackage that adds pages to the Tools.Options dialog, you may also which to add this macro to your arsenal of testing tools.

Imports Microsoft.Win32

Sub TestAutomationProperties()
   
Dim properties As EnvDTE.Properties
   
Dim ow As OutputWindow = DTE.ToolWindows.OutputWindow
   
Dim op As OutputWindowPane = ow.OutputWindowPanes.Add("Test Automation Properties")
   op.Activate()
   op.Clear()

   
Dim regrootKey As RegistryKey = Registry.LocalMachine.OpenSubKey(DTE.RegistryRoot, False)
   
Dim automationPropertiesKey As RegistryKey = regrootKey.OpenSubKey("AutomationProperties", False)
   
Dim categoryName As String

   
For Each categoryName In automationPropertiesKey.GetSubKeyNames
      
Dim categoryKey As RegistryKey = automationPropertiesKey.OpenSubKey(categoryName, False)
      
For Each pageName As String In categoryKey.GetSubKeyNames
         
Dim pageKey As RegistryKey = categoryKey.OpenSubKey(pageName, False)
      
Try
          properties = DTE.Properties(categoryName, pageName)
         
If properties.Count = 0 Then
             op.OutputString("*** BUG: " + categoryName + "." + pageName + " must add [ClassInterface(ClassInterfaceType.AutoDual)] attribute" + vbCrLf)
         
Else
             op.OutputString(categoryName + "." + pageName + " has " + properties.Count.ToString() + " properties" + vbCrLf)
         
End If
         Catch ex As Exception
            op.OutputString(
"*** BUG: " + categoryName + "." + pageName + " must add [ComVisible(true)] attribute" + vbCrLf)
         
End Try
      Next
   Next
End
Sub

Caveats:

While adding the [ClassInterface(ClassInterfaceType.AutoDual)] attribute allows you to expose the DialogPage's properties through the DTE.Properties method, it exposes 'all' public properties, including those from your base classes, such as the "Site", "AutomationObject" and "Container" properties, and others hidden from the Import/Export Settings feature (through the use of the DesignerSerializationVisibilityAttribute).

However, the development team is currently working to address this in VS 2010, and alleviate the need to use the ClassInterface attribute to expose the dialogs properties.