[2005] BackgroundWorker error. Don't understand it
I have the following code
Code:
Private Sub GetOtherData()
If My.Settings.ScanServices Then
Me.GetServices()
End If
End Sub
Private Sub GetServices()
Dim Services_worker As New System.ComponentModel.BackgroundWorker
AddHandler Services_worker.DoWork, New System.ComponentModel.DoWorkEventHandler(AddressOf Me.WW.GetServices)
AddHandler Services_worker.RunWorkerCompleted, _
New System.ComponentModel.RunWorkerCompletedEventHandler(AddressOf Me.ServicesWorkerCompleted)
Services_worker.RunWorkerAsync()
End Sub
Private Sub ServicesWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs)
Dim ServColor As Color
For Each Item As ManagementBaseObject In DirectCast(e.Result, ManagementObjectCollection)
If CStr(Item("State")) = "Stopped" Then
ServColor = Color.Red
Else
ServColor = Color.Black
End If
MsgBox(Item("name"))
lvh.AddListViewItem(Me.lv_Services, _
"ico_services", _
ServColor, _
CStr(Item("Name")), _
New String() {CStr(Item("DisplayName")), _
CStr(Item("State")), _
CStr(Item("StartMode")), _
CStr(Item("StartName")), _
CStr(Item("PathName")), _
CStr(Item("Description"))})
Next
lvh.AutoSizeColumns(Me.lv_Services)
lvh.ExportLV2XML(Me.lv_Services, False, "Services")
Me.bln_ServicesInfo = True
End Sub
Code:
Option Strict On
Option Explicit On
Imports System.Management
Public Class WMIWrapper
Public Sub GetServices(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs)
e.Result = Me.RunQuery("select * from Win32_Service")
End Sub
End Class
I get a "Exception has been thrown by the target of an invocation."
Is the e.result from the DoWork event passed automatically to the RunWorkerCompleted method by the BackgroundWorker? If not, how can I pass it?
Re: [2005] BackgroundWorker error. Don't understand it
update: I wrapped the RunWorkerCompleted code in a Try/Catch statement and the error is "Value does not fall within the expected range". Not sure what's going on here.
And it ONLY happens when I run the WMI query with alternate credentials! God I hate WMI sometimes
Re: [2005] BackgroundWorker error. Don't understand it
OK, why this only happens when using alternate credentials I don't know. However, I believe I know what's happening. The backgroundworker completes and passes e.result (a ManagementObjectCollection) to the WorkerCompleted event, I then cast e.result to a ManageMentCollection. At this point, the collection gets enumerated.
So, when I come to loop through it, being a forward-only collection, I get an error.
Thus, the question is, how can RE-enumerate the collection? I've been reading up in IEnumerable but I can't see how it fits in here.
I'd really appreciate some input on this. It's the last bug to fix before I can go into beta!
Re: [2005] BackgroundWorker error. Don't understand it
Righto, small update. I can now get it to work by passing a ManagementObjectCollection.ManagementEnumerator object to e.result instead of a ManagementObjectCollection.
That allows me to enumerate the collection repeatedly. The other alternative was to put everything into a dataset in the DoWork method but that seemed a little clunky.
I still find it strange that casting e.result to a ManagementObjectCollection in the RunWorkerCompleted method enumerates the collection thereby making it impossible to use. I can't believe I'm the only one who wants to use WMI queries in BackgroundWorkers!!
Re: [2005] BackgroundWorker error. Don't understand it
Ok, so apparently my code was wrong and it didn't work using an Enumerator.
However, I HAVE now found a solution but I would appreciate someone with more knowledge than me explaining WHY this works.
Here's the code
Code:
Imports System.Management
Public Class Form1
Public MyWMISCope As ManagementScope
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim WMIConnectionOptions As New ConnectionOptions
Dim WMIScopeTarget As String = "foo"
With WMIConnectionOptions
.Username = "foo"
.Password = "foo"
End With
MyWMISCope = New ManagementScope("\\" & _
WMIScopeTarget & "\root\cimv2", WMIConnectionOptions)
MyWMISCope.Connect()
GetCodecs()
End Sub
Private Sub GetCodecs()
Dim Codecs_worker As New System.ComponentModel.BackgroundWorker
AddHandler Codecs_worker.DoWork, New System.ComponentModel.DoWorkEventHandler(AddressOf Me.RunCodecQuery)
AddHandler Codecs_worker.RunWorkerCompleted, _
New System.ComponentModel.RunWorkerCompletedEventHandler(AddressOf Me.CodecWorkerCompleted)
Codecs_worker.RunWorkerAsync()
End Sub
Private Sub RunCodecQuery(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs)
e.Result = Me.Invoke(New RunQueryDelegate(AddressOf RunQuery), "select * from Win32_CodecFile")
'e.Result = Me.RunQuery("select * from Win32_CodecFile")
End Sub
Public Sub CodecWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs)
Try
Me.ListView1.Items.Clear()
ListView1.Columns.Add("Codec Name")
For Each item As ManagementBaseObject In DirectCast(e.Result, ManagementObjectCollection)
ListView1.Items.Add(item("Path").ToString)
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Private Delegate Function RunQueryDelegate(ByVal QueryText As String) As ManagementObjectCollection
Private Function RunQuery(ByVal QueryText As String) As ManagementObjectCollection
Dim Query As New SelectQuery(QueryText)
Dim WMISearcher As New ManagementObjectSearcher(MyWMISCope, Query)
Return WMISearcher.Get()
End Function
End Class
If I run the WMI Query via a Delegate, it works. If I run it directly, it doesn't (try swapping the lines in the DoWork method). I'm stumped, quite frankly. This ONLY happens when running a WMI Query via a Backgroundworker with alternate WMI Credentials.
I've logged a call with MS to see if this is a bug or not.