The strange case of VSLangProj80.ProjectProperties3.AbsoluteProjectDirectory
When you have a System.Type that is a component, the best way to get its public properties is to use System.ComponentModel.TypeDescriptor.GetProperties(type), rather than System.Type.GetProperties(). This is so because a component type can have a designer which is able to add new properties to the type, and to remove or change existing properties. For example, controls have a Locked property that is added by the designer of controls (ControlDesigner class), it is not a property that belongs to the System.Windows.Forms.Control type.
If the type is not a component, I guess that System.ComponentModel.TypeDescriptor.GetProperties returns the same public properties than System.Type.GetProperties. System.ComponentModel.TypeDescriptor.GetProperties returns a collection of PropertyDescriptor, which has an IsBrowsable property that tells you if a property is browsable or not.
So, the other day I got an strange issue: I was calling System.ComponentModel.TypeDescriptor.GetProperties on the VSLangProj80.ProjectProperties3 type (which is not a component type but my code was called other times with types that are components), to get the properties that are likely to exist in the EnvDTE.Project.Properties collection. And I got in the results the "AbsoluteProjectDirectory" property, that I noticed that didn't appear in the Object Browser of Visual Studio, despite its IsBrowsable property returning True. How come?
I was aware that VSLangProj80 stuff is not pure .NET but an imported typelib or something like that, but it was not until I used .NET Reflector that I discovered that the get accessor method of the AbsoluteProjectDirectory property has the System.Runtime.InteropServices.TypeLibFuncFlags attribute with the &H40 value:
ReadOnly Property AbsoluteProjectDirectory As <MarshalAs(UnmanagedType.BStr)> String
<MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime), DispId(&H2732), TypeLibFunc(CShort(&H40))> _
which matches the FHidden value:
<Serializable, Flags, ComVisible(True)> _
Public Enum TypeLibFuncFlags
FBindable = 4
FDefaultBind = &H20
FDefaultCollelem = &H100
FDisplayBind = &H10
FHidden = &H40
FImmediateBind = &H1000
FNonBrowsable = &H400
FReplaceable = &H800
FRequestEdit = 8
FRestricted = 1
FSource = 2
FUiDefault = &H200
FUsesGetLastError = &H80
That explained the issue and I was able to tweak my code to deal with that case. BTW, notice that there is also a TypeLibFuncFlags.FNonBrowsable flag.