MSDN Magazine - January 2009 - (Page 26) such as Integer and String are represented by classes or structures through System.Type; second, in .NET the compound types such as Array of Integer are represented through System.Type. The code that you need to dig through a TYPEDESC is quite straightforward (see Figure 8). Note that the case VT_USERDE FINED again uses a handle to a reference, which you must look up through GetRefTypeInfo. Figure 9 Using VARIANT ''' ''' VARIANT: this is called "Object" in Visual Basic. It's the universal ''' variable type for COM. ''' ''' The "vt" flag determines which of the other fields have ''' meaning. vt is a VarEnum. _ Public Structure [VARIANT] Public vt As UShort _ Public wReserved1 As UShort _ Public wReserved2 As UShort _ Public wReserved3 As UShort ' Public llVal As Long Public lVal As Integer Public bVal As Byte ' and similarly for many other accessors _ Public ptr As System.IntPtr ''' ''' GetObject: returns a .NET Object equivalent for this Variant. ''' Function GetObject() As Object ' We want to use the handy Marshal.GetObjectForNativeVariant. ' But this only operates upon an IntPtr to a block of memory. ' So we first flatten ourselves into that block of memory. (size 16) Dim ptr = Marshal.AllocCoTaskMem(16) Marshal.StructureToPtr(Me, ptr, False) Try : Return Marshal.GetObjectForNativeVariant(ptr) Finally : Marshal.FreeCoTaskMem(ptr) : End Try End Function End Structure The COM Representation of Value The next step is to actually dump a COM object, that is, print out the values of its properties. This task is easy if you know the names of those properties since you can just use a latebound call in Visual Basic: Dim com as Object : Dim val = com.SomePropName The compiler translates this into a runtime call of IDispatch::Invoke to fetch the value of the property. But in the case of reflection, you may not know the property name. Perhaps all you have is MEMBERID, so you have to call IDispatch::Invoke yourself. This isn’t very pretty. The first headache comes from the fact that COM and .NET represent values in very different ways. In .NET you use Object to represent arbitrary values. In COM you use the VARIANT struc ture, as shown in Figure 9. A COM value uses the vt field to indicate what type it is. It might be VarEnum.VT_INT, or VarEnum.VT_PTR, or any of the 30 or so VarEnum types. Knowing its type, you can figure out which of the other fields to look up in a giant Select Case statement. Luck ily, that Select Case statement has already been implemented in the Marshal.GetObjectForNativeVariant function. Dumping the Properties of a COM Object You’ll want to dump the properties of your COM object, more or less like the “Quick Watch” window in Visual Studio: DUMP OF COM OBJECT #28114988 ISpeechVoice.Status = System ComObject As Ref ISpeechVoiceStatus ISpeechVoice.Rate = 0 As Integer ISpeechVoice.Volume = 100 As Integer ISpeechVoice.AllowAudioOutputFormatChangesOnNextSet = True As Bool ISpeechVoice.EventInterests = 0 As SpeechVoiceEvents ISpeechVoice.Priority = 0 As SpeechVoicePriority ISpeechVoice.AlertBoundary = 32 As SpeechVoiceEvents ISpeechVoice.SynchronousSpeakTimeout = 10000 As Integer Figure 10 Looking at Get* and Is* Methods ' We'll only try to retrieve things that are likely to be side-effect' free properties: If (funcDesc.invkind And ComTypes.INVOKEKIND.INVOKE_PROPERTYGET) = 0 _ AndAlso Not funcName Like "[Gg]et*" _ AndAlso Not funcName Like "[Ii]s*" _ Then Continue For If funcDesc.cParams > 0 Then Continue For Dim returnType = CType(funcDesc.elemdescFunc.tdesc.vt, VarEnum) If returnType = VarEnum.VT_VOID Then Continue For Dim returnTypeName = DumpTypeDesc(funcDesc.elemdescFunc.tdesc, typeInfo) ' And we'll only try to evaluate the easily-evaluatable properties: Dim dumpableTypes = New VarEnum() {VarEnum.VT_BOOL, VarEnum.VT_BSTR, _ VarEnum.VT_CLSID, _ VarEnum.VT_DECIMAL, VarEnum.VT_FILETIME, VarEnum.VT_HRESULT, _ VarEnum.VT_I1, VarEnum.VT_I2, VarEnum.VT_I4, VarEnum.VT_I8, _ VarEnum.VT_INT, VarEnum.VT_LPSTR, VarEnum.VT_LPWSTR, _ VarEnum.VT_R4, VarEnum.VT_R8, _ VarEnum.VT_UI1, VarEnum.VT_UI2, VarEnum.VT_UI4, VarEnum.VT_UI8, _ VarEnum.VT_UINT, VarEnum.VT_DATE, _ VarEnum.VT_USERDEFINED} Dim typeIsDumpable = dumpableTypes.Contains(returnType) If returnType = VarEnum.VT_PTR Then Dim ptrType = CType(Marshal.PtrToStructure( _ funcDesc.elemdescFunc.tdesc.lpValue, _ GetType(ComTypes.TYPEDESC)), ComTypes.TYPEDESC) If ptrType.vt = VarEnum.VT_USERDEFINED Then typeIsDumpable = True End If The thing is, there are lots of different types in COM. It would be exhausting to write code to handle every single case correctly and hard to assemble enough test cases to test them all. Here I’ll settle for dumping a small set of types that I know I can handle correctly. And beyond that, what would be useful to dump? Besides the properties, it would also be useful to get a dump of anything ex posed through pure (sideeffectfree) functions such as IsTall(). But you wouldn’t want to invoke functions such as AddRef(). To discriminate between these two, I reckon that any function name such as “Is*” is fair game for dumping (see Figure 10). It turns out that COM programmers seem to use Is* functions a lot less fre quently than do programmers using .NET! In this code, the final kind of dumpable type you consider is a VT_PTR to a VT_USERDEFINED type. This covers the common case of a property that returns a reference to another object. The final step is to read the property you’ve identified by its MEMBERID or invoke the function. You can see the code to do it in Figure 11. The key method here is IDispatch.Invoke. Its first argument is the member id of the property or function that you’re invoking. The variable dispatchType is either 2 for a propertyget or Basic instincts Using IDispatch.Invoke 26 msdn magazine
Table of Contents Feed for the Digital Edition of MSDN Magazine - January 2009 Toolbox CLR Inside Out Basic Instincts Cutting Edge Test Run First Look Geneva Framework Silverlight Windows Mobile Service Station Security Briefs Extreme ASP.NET Foundations .NET Matters { End Bracket } MSDN Magazine - January 2009 MSDN Magazine - January 2009 - (Page Intro) MSDN Magazine - January 2009 - (Page Cover1) MSDN Magazine - January 2009 - (Page Cover2) MSDN Magazine - January 2009 - (Page 1) MSDN Magazine - January 2009 - (Page 2) MSDN Magazine - January 2009 - (Page 3) MSDN Magazine - January 2009 - (Page 4) MSDN Magazine - January 2009 - (Page 5) MSDN Magazine - January 2009 - (Page 6) MSDN Magazine - January 2009 - (Page 7) MSDN Magazine - January 2009 - (Page 8) MSDN Magazine - January 2009 - Toolbox (Page 9) MSDN Magazine - January 2009 - Toolbox (Page 10) MSDN Magazine - January 2009 - Toolbox (Page 11) MSDN Magazine - January 2009 - Toolbox (Page 12) MSDN Magazine - January 2009 - Toolbox (Page 13) MSDN Magazine - January 2009 - Toolbox (Page 14) MSDN Magazine - January 2009 - CLR Inside Out (Page 15) MSDN Magazine - January 2009 - CLR Inside Out (Page 16) MSDN Magazine - January 2009 - CLR Inside Out (Page 17) MSDN Magazine - January 2009 - CLR Inside Out (Page 18) MSDN Magazine - January 2009 - CLR Inside Out (Page 19) MSDN Magazine - January 2009 - CLR Inside Out (Page 20) MSDN Magazine - January 2009 - Basic Instincts (Page 21) MSDN Magazine - January 2009 - Basic Instincts (Page 22) MSDN Magazine - January 2009 - Basic Instincts (Page 23) MSDN Magazine - January 2009 - Basic Instincts (Page 24) MSDN Magazine - January 2009 - Basic Instincts (Page 25) MSDN Magazine - January 2009 - Basic Instincts (Page 26) MSDN Magazine - January 2009 - Basic Instincts (Page 27) MSDN Magazine - January 2009 - Basic Instincts (Page 28) MSDN Magazine - January 2009 - Basic Instincts (Page 29) MSDN Magazine - January 2009 - Basic Instincts (Page 30) MSDN Magazine - January 2009 - Cutting Edge (Page 31) MSDN Magazine - January 2009 - Cutting Edge (Page 32) MSDN Magazine - January 2009 - Cutting Edge (Page 33) MSDN Magazine - January 2009 - Cutting Edge (Page 34) MSDN Magazine - January 2009 - Cutting Edge (Page 35) MSDN Magazine - January 2009 - Cutting Edge (Page 36) MSDN Magazine - January 2009 - Cutting Edge (Page 37) MSDN Magazine - January 2009 - Cutting Edge (Page 38) MSDN Magazine - January 2009 - Test Run (Page 39) MSDN Magazine - January 2009 - Test Run (Page 40) MSDN Magazine - January 2009 - Test Run (Page 41) MSDN Magazine - January 2009 - Test Run (Page 42) MSDN Magazine - January 2009 - Test Run (Page 43) MSDN Magazine - January 2009 - Test Run (Page 44) MSDN Magazine - January 2009 - Test Run (Page 45) MSDN Magazine - January 2009 - Test Run (Page 46) MSDN Magazine - January 2009 - Test Run (Page 47) MSDN Magazine - January 2009 - Test Run (Page 48) MSDN Magazine - January 2009 - Test Run (Page 49) MSDN Magazine - January 2009 - First Look (Page 50) MSDN Magazine - January 2009 - First Look (Page 51) MSDN Magazine - January 2009 - First Look (Page 52) MSDN Magazine - January 2009 - First Look (Page 53) MSDN Magazine - January 2009 - First Look (Page 54) MSDN Magazine - January 2009 - First Look (Page 55) MSDN Magazine - January 2009 - First Look (Page 56) MSDN Magazine - January 2009 - First Look (Page 57) MSDN Magazine - January 2009 - First Look (Page 58) MSDN Magazine - January 2009 - First Look (Page 59) MSDN Magazine - January 2009 - First Look (Page 60) MSDN Magazine - January 2009 - First Look (Page 61) MSDN Magazine - January 2009 - First Look (Page 62) MSDN Magazine - January 2009 - First Look (Page 63) MSDN Magazine - January 2009 - Geneva Framework (Page 64) MSDN Magazine - January 2009 - Geneva Framework (Page 65) MSDN Magazine - January 2009 - Geneva Framework (Page 66) MSDN Magazine - January 2009 - Geneva Framework (Page 67) MSDN Magazine - January 2009 - Geneva Framework (Page 68) MSDN Magazine - January 2009 - Geneva Framework (Page 69) MSDN Magazine - January 2009 - Geneva Framework (Page 70) MSDN Magazine - January 2009 - Geneva Framework (Page 71) MSDN Magazine - January 2009 - Geneva Framework (Page 72) MSDN Magazine - January 2009 - Geneva Framework (Page 73) MSDN Magazine - January 2009 - Geneva Framework (Page 74) MSDN Magazine - January 2009 - Silverlight (Page 75) MSDN Magazine - January 2009 - Silverlight (Page 76) MSDN Magazine - January 2009 - Silverlight (Page 77) MSDN Magazine - January 2009 - Silverlight (Page 78) MSDN Magazine - January 2009 - Silverlight (Page 79) MSDN Magazine - January 2009 - Silverlight (Page 80) MSDN Magazine - January 2009 - Silverlight (Page 81) MSDN Magazine - January 2009 - Silverlight (Page 82) MSDN Magazine - January 2009 - Silverlight (Page 83) MSDN Magazine - January 2009 - Silverlight (Page 84) MSDN Magazine - January 2009 - Silverlight (Page 85) MSDN Magazine - January 2009 - Silverlight (Page 86) MSDN Magazine - January 2009 - Silverlight (Page 87) MSDN Magazine - January 2009 - Windows Mobile (Page 88) MSDN Magazine - January 2009 - Windows Mobile (Page 89) MSDN Magazine - January 2009 - Windows Mobile (Page 90) MSDN Magazine - January 2009 - Windows Mobile (Page 91) MSDN Magazine - January 2009 - Windows Mobile (Page 92) MSDN Magazine - January 2009 - Service Station (Page 93) MSDN Magazine - January 2009 - Service Station (Page 94) MSDN Magazine - January 2009 - Service Station (Page 95) MSDN Magazine - January 2009 - Service Station (Page 96) MSDN Magazine - January 2009 - Service Station (Page 97) MSDN Magazine - January 2009 - Service Station (Page 98) MSDN Magazine - January 2009 - Security Briefs (Page 99) MSDN Magazine - January 2009 - Security Briefs (Page 100) MSDN Magazine - January 2009 - Security Briefs (Page 101) MSDN Magazine - January 2009 - Security Briefs (Page 102) MSDN Magazine - January 2009 - Extreme ASP.NET (Page 103) MSDN Magazine - January 2009 - Extreme ASP.NET (Page 104) MSDN Magazine - January 2009 - Extreme ASP.NET (Page 105) MSDN Magazine - January 2009 - Extreme ASP.NET (Page 106) MSDN Magazine - January 2009 - Extreme ASP.NET (Page 107) MSDN Magazine - January 2009 - Extreme ASP.NET (Page 108) MSDN Magazine - January 2009 - Foundations (Page 109) MSDN Magazine - January 2009 - Foundations (Page 110) MSDN Magazine - January 2009 - Foundations (Page 111) MSDN Magazine - January 2009 - Foundations (Page 112) MSDN Magazine - January 2009 - Foundations (Page 113) MSDN Magazine - January 2009 - Foundations (Page 114) MSDN Magazine - January 2009 - Foundations (Page 115) MSDN Magazine - January 2009 - .NET Matters (Page 116) MSDN Magazine - January 2009 - .NET Matters (Page 117) MSDN Magazine - January 2009 - .NET Matters (Page 118) MSDN Magazine - January 2009 - .NET Matters (Page 119) MSDN Magazine - January 2009 - { End Bracket } (Page 120) MSDN Magazine - January 2009 - { End Bracket } (Page Cover3) MSDN Magazine - January 2009 - { End Bracket } (Page Cover4)
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.