Option Strict On and InvokeMember and WMI

H

Howard Kaikow

I am trying to retrive some WMI properties using Option Strict On.
This requires the use of InvokeMember.

I know that there are alternative ways to get the values, but I want to
learn how to use WMI with InvokeMember and Option Strict On.

I'm getting an "Unknown Name" error in the following statement in the code
below.

objProp = typeObjProps.InvokeMember("Item", _
BindingFlags.Default Or BindingFlags.GetProperty, Nothing, _
objProps, New Object() {propIndices(i)})

I expect that I am using the wrong object type somewhere or I need different
Binding flags.

Suggestions?

The code runs in the click event for a Button and uses a ListBox1 for
output.

Option Strict On
Imports WbemScripting
Imports System.Reflection
Public Class Form1
Inherits System.Windows.Forms.Form
Enum props
ComponentId
LocalServer32
ProgId
VersionIndependentProgId
End Enum
Private Sub btnRunMe_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnRunMe.Click
Const high As Integer = props.VersionIndependentProgId
Const strComputer As String = "." ' "." for local computer
Dim i As Integer
Dim objProp As Object
Dim objProps As Object
Dim propIndices(high) As String
Dim propValue(high) As String
Dim typeObjProp As Type
Dim typeObjProps As Type
Dim wmiObjectSet As SWbemObjectSet
Dim wmiServices As SWbemServices
propIndices(props.ComponentId) = "ComponentId"
propIndices(props.LocalServer32) = "LocalServer32"
propIndices(props.ProgId) = "ProgId"
propIndices(props.VersionIndependentProgId) = "VersionIndependentProgId"
wmiServices = DirectCast(GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer _
& "\root\cimv2"), SWbemServices)
wmiObjectSet = wmiServices.ExecQuery _
("Select * from Win32_ClassicCOMClassSetting WHERE " _
& "VersionIndependentProgId='Mozilla.Browser'" _
& "Or VersionIndependentProgId='InternetExplorer.Application'" _
& "Or VersionIndependentProgId='Excel.Application'" _
& "Or VersionIndependentProgId='Word.Application'")
' Note: The following runs slowly. Give it a minute or so.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''
' Following is not correct
For Each objProps In wmiObjectSet
typeObjProps = objProps.GetType()
For i = 0 To propIndices.Length - 1
Try
objProp = typeObjProps.InvokeMember("Item", _
BindingFlags.Default Or BindingFlags.GetProperty, Nothing, _
objProps, New Object() {propIndices(i)})
If objProp Is Nothing Then
propValue(i) = ""
Else
typeObjProp = objProp.GetType()
propValue(i) = typeObjProp.InvokeMember("Value", _
BindingFlags.Default Or BindingFlags.GetProperty, Nothing, _
objProp, New Object() {}).ToString()
End If
Catch ex As Exception
propValue(i) = ""
'MessageBox.Show(ex.Message, propIndices(i))
End Try
Next i
With ListBox1
With .Items
.Add("ProgId = " & propValue(props.ProgId))
.. Add("VersionIndependentProgId = " &
propValue(props.VersionIndependentProgId))
.Add("ComponentId = " & propValue(props.ComponentId))
.Add("LocalServer32 = " & propValue(props.LocalServer32))
End With
.Update()
End With
Next objProps

objProp = Nothing
objProps = Nothing
typeObjProp = Nothing
typeObjProps = Nothing
wmiObjectSet = Nothing
wmiServices = Nothing
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()
End Sub
End Class
 
L

Larry Lard

Howard said:
I am trying to retrive some WMI properties using Option Strict On.
This requires the use of InvokeMember.

I know that there are alternative ways to get the values, but I want to
learn how to use WMI with InvokeMember and Option Strict On.

I'm getting an "Unknown Name" error in the following statement in the code
below.

objProp = typeObjProps.InvokeMember("Item", _
BindingFlags.Default Or BindingFlags.GetProperty, Nothing, _
objProps, New Object() {propIndices(i)})

I expect that I am using the wrong object type somewhere or I need different
Binding flags.

Suggestions?

I would love to be able to say I had solved all your problems but I ran
into problems of my own.

First off: The problem in your code is that you have missed out a level
of the object hierarchy: what you call objProps is not a PropertySet,
but just a SWbemObject, so you would need to obtain it's Properties_
property (which IS a PropertySet) and then interrogate that.

However, I tried that, and I just COULD NOT get InvokeMember("Item"...)
to work on a PropertySet object. InvokeMember("Count"...) worked, so
the object itself was fine - it's just that somewhere in the
combination of Interop, Reflection, the optional parameter (maybe), and
the indexed property, something goes wrong.

HOWEVER

While I applaud your efforts to understand and get to grips with
InvokeMember, I must take issue with this:
I am trying to retrive some WMI properties using Option Strict On.
This requires the use of InvokeMember.

I know that there are alternative ways to get the values, but I want to
learn how to use WMI with InvokeMember and Option Strict On.

It looks to me like it's entirely possible to use WMI with Strict On.
This code snippet does what yours wants to do, with no InvokeMember and
all strongly typed:

Private Sub btnRunMe_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles btnRunMe.Click
Const high As Integer = props.VersionIndependentProgId
Const strComputer As String = "." ' "." for local computer
Dim i As Integer

'These are the objects we will use as we dig down the object
hierarchy
Dim wmiServices As SWbemServices
Dim wmiObjectSet As SWbemObjectSet
Dim owmiObject As Object 'a SWbemObject in the above
collection
Dim wmiObject As SWbemObject 'the above, strongly typed
Dim owmiPropertySet As Object 'the SWbemPropertySet that is
the Properties_ property of the above
Dim wmiPropertySet As SWbemPropertySet 'the above, strongly
typed
Dim wmiProperty As SWbemProperty 'a SWbemProperty in the
above collection

'the properties we obtain
Dim hshProperties As Hashtable

wmiServices = DirectCast(GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer _
& "\root\cimv2"), SWbemServices)

wmiObjectSet = wmiServices.ExecQuery _
("Select * from Win32_ClassicCOMClassSetting WHERE " _
& "VersionIndependentProgId='Mozilla.Browser'" _
& "Or
VersionIndependentProgId='InternetExplorer.Application'" _
& "Or VersionIndependentProgId='Excel.Application'" _
& "Or VersionIndependentProgId='Word.Application'")

'wmiObjectSet is a SWbemObjectSet
For Each owmiObject In wmiObjectSet
hshProperties = New Hashtable

If TypeOf owmiObject Is SWbemObject Then
wmiObject = CType(owmiObject, SWbemObject)

'get the properties collection of this SWbemObject
owmiPropertySet = wmiObject.Properties_
If TypeOf owmiPropertySet Is SWbemPropertySet Then
wmiPropertySet = CType(owmiPropertySet,
SWbemPropertySet)

For Each wmiProperty In wmiPropertySet
hshProperties.Add(wmiProperty.Name,
wmiProperty.Value)
Next

'now we have the properties we desire, show in list
box
With ListBox1
With .Items
Dim DesiredProperty As String
For Each DesiredProperty In
System.Enum.GetNames(GetType(props))
.Add(DesiredProperty & " = " &
hshProperties(DesiredProperty).ToString)
Next
.Add("--")
End With
.Update()
End With
End If
End If
Next

End Sub
 
H

Howard Kaikow

With your code, I now have 3 different ways to use Option Strict On with
WMI, without using InvokeMember.

1. Your method with hashtables.
2. StringReader on the wmiObject.GetObjectText_
3. GetProperties on each object in the result of the ExecQuery.

It seems that there has to be a way to use InvokeMember, otherwise there'a a
bug in .NET.
 
H

Howard Kaikow

The following seems to be better alternative.

Private Sub btnRunMe_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnRunMe.Click
Const high As Integer = props.VersionIndependentProgId
Const strComputer As String = "." ' "." for local computer
Dim i As Integer
Dim propIndices(high) As String
Dim propValue(high) As String
Dim wmiObject As SWbemObject
Dim wmiObjectSet As SWbemObjectSet
Dim wmiServices As SWbemServices
propIndices(props.ComponentId) = "ComponentId"
propIndices(props.LocalServer32) = "LocalServer32"
propIndices(props.ProgId) = "ProgId"
propIndices(props.VersionIndependentProgId) = "VersionIndependentProgId"
wmiServices = DirectCast(GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer _
& "\root\cimv2"), SWbemServices)
wmiObjectSet = wmiServices.ExecQuery _
("Select * from Win32_ClassicCOMClassSetting WHERE " _
& "VersionIndependentProgId='Mozilla.Browser'" _
& "Or VersionIndependentProgId='InternetExplorer.Application'" _
& "Or VersionIndependentProgId='Excel.Application'" _
& "Or VersionIndependentProgId='Word.Application'")
For Each wmiObject In wmiObjectSet
With wmiObject
With .Properties_
For i = 0 To high
propValue(i) = .Item(propIndices(i)).Value.ToString()
Next i
End With
With ListBox1
With .Items
..Add("ProgId = " & propValue(props.ProgId))
..Add("VersionIndependentProgId = " &
propValue(props.VersionIndependentProgId))
..Add("ComponentId = " & propValue(props.ComponentId))
..Add("LocalServer32 = " & propValue(props.LocalServer32))
End With
..Update()
End With
End With
Next wmiObject
wmiObjectSet = Nothing
wmiObject = Nothing
wmiServices = Nothing
End Sub
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top