chadmanvb
asked on
mutiple threads calling the same function
I have an application that is running in 10 threads. Each thread is calling the same functions and procedures. I seem to have an issue where some threads might get duplicate results and they should not. I would think the function would only return the value to the thread that called it, but looking at my results this is not always the case. Can this happen if 2 threads call a function at the same time? Is there a way to fix this?
ASKER
Thannks for the help. I am calling a module in my form that contains a few funtions within it to get the user id of a user on a remote workstation. I call getuser from this module:
Imports System.Management
Imports System.DirectoryServices
Imports Microsoft.Win32
Imports System.Runtime.InteropServ ices
Module UserInfo
Dim objManagementClass As ManagementClass
Dim objManagementScope As ManagementScope
Dim objManagementBaseObject As ManagementBaseObject
Public Function GetUser(ByVal RemotePC As String) As String
Dim WMIScope As Management.ManagementScope
Dim WMIConnectionOptions As New Management.ConnectionOptio ns
Dim strRootDomain As String
Dim objRootLDAP As DirectoryEntry
Dim query As ManagementObjectSearcher
Dim queryCollection As ManagementObjectCollection
Dim oq As New System.Management.ObjectQu ery
Dim mo As New ManagementObject
Dim UserDomain As String
Dim UserID As String
Dim StrLoggedUserSID() As Byte
Dim Strcomputer As String = RemotePC 'My.Application.CommandLin eArgs.Item (0)
'Console.WriteLine(Strcomp uter)
With WMIConnectionOptions
.Impersonation = System.Management.Imperson ationLevel .Impersona te
.Authentication = System.Management.Authenti cationLeve l.Packet
End With
WMIScope = New Management.ManagementScope ("\\" & _
Strcomputer & "\root\cimv2", WMIConnectionOptions)
objRootLDAP = New DirectoryEntry("LDAP://Roo tDSE")
strRootDomain = objRootLDAP.Properties.Ite m("rootDom ainNamingC ontext").V alue.ToStr ing
oq = New System.Management.ObjectQu ery("SELEC T * from Win32_process Where Name='explorer.exe' and SessionID=0")
query = New ManagementObjectSearcher(W MIScope, oq)
queryCollection = query.Get()
If queryCollection.Count = 0 Then
Return ("Not logged in")
Exit Function
Else
Dim strKeyPath As String = "SOFTWARE\Microsoft\Window s NT\CurrentVersion\WinLogon "
objManagementScope = New ManagementScope
objManagementScope.Path.Se rver = Strcomputer
objManagementScope.Path.Na mespacePat h = "root\default"
objManagementScope.Options .EnablePri vileges = True
objManagementScope.Options .Impersona tion = ImpersonationLevel.Imperso nate
objManagementScope.Connect ()
objManagementClass = New ManagementClass("stdRegPro v")
objManagementClass.Scope = objManagementScope
objManagementBaseObject = objManagementClass.GetMeth odParamete rs("EnumVa lues")
objManagementBaseObject.Se tPropertyV alue("hDef Key", CType("&H" & Hex(RegistryHive.LocalMach ine), Long))
objManagementBaseObject.Se tPropertyV alue("sSub KeyName", strKeyPath)
UserDomain = CStr(GetRegValues("Default DomainName ", strKeyPath, "HKLM"))
UserID = CStr(GetRegValues("Default UserName", strKeyPath, "HKLM"))
UserID = "DOMAIN\" & UserID
Return (UserID)
'If the SID or the full name is needed sometime in the future the code is below
'If UCase(UserDomain) = UCase(strcomputer) Then
'Console.WriteLine("Logged on user = " & UserDomain & "\" & UserID & " (local user)")
'Exit Sub
'End If
'Dim LdapBind As String
'LdapBind = ("LDAP://" & strRootDomain)
'Dim deEntry3 As New DirectoryEntry(LdapBind)
'Dim DSearch As New DirectorySearcher(deEntry3 )
'With DSearch
' .SearchScope = SearchScope.Subtree
' .Filter = "(&(objectclass=user)(sAMA ccountName =" & UserID & "))"
' .PropertiesToLoad.Add("nam e")
' .PropertiesToLoad.Add("sAM AccountNam e")
' .PropertiesToLoad.Add("dis tinguished Name")
'End With
'Dim sResultSet As SearchResult
'For Each sResultSet In DSearch.FindAll()
' If UCase(GetProperty(sResultS et, "sAMAccountName")) = UCase(UserID) Then
' Console.WriteLine("Logged on user = " & GetProperty(sResultSet, "name") & " (as " & _
' UserDomain & "\" & UserID & ")")
' Dim deEntry4 As New DirectoryEntry("LDAP://" & GetProperty(sResultSet, "distinguishedName").ToStr ing)
' StrLoggedUserSID = CType(deEntry4.Properties( "objectSid ").Value, Byte())
' Console.WriteLine("User's SID = " & ConvertSid(StrLoggedUserSI D))
' End If
'Next
End If
End Function
Public Function GetProperty(ByVal srSearchResult As SearchResult, ByVal strPropertyName As String) As String
If srSearchResult.Properties. Contains(s trProperty Name) Then
Return srSearchResult.Properties( strPropert yName)(0). ToString()
Else
Return String.Empty
End If
End Function
Private Function GetRegValues(ByVal regkeyValue As String, ByVal regkey As String, ByVal Hive As String)
Select Case Hive
Case "HKLM"
Hive = CStr(RegistryHive.LocalMac hine)
Case "HKU"
Hive = CStr(RegistryHive.Users)
Case "HKCU"
Hive = CStr(RegistryHive.CurrentU ser)
Case "HKCR"
Hive = CStr(RegistryHive.ClassesR oot)
End Select
objManagementBaseObject = objManagementClass.GetMeth odParamete rs("GetStr ingValue")
objManagementBaseObject.Se tPropertyV alue("hDef Key", CType("&H" & Hex(Hive), Long))
objManagementBaseObject.Se tPropertyV alue("sSub KeyName", regkey)
objManagementBaseObject.Se tPropertyV alue("sVal ueName", regkeyValue)
objManagementBaseObject = objManagementClass.InvokeM ethod("Get StringValu e", objManagementBaseObject, Nothing)
GetRegValues = objManagementBaseObject("s Value")
End Function
Public Function ConvertSid(ByVal sid As Byte()) As String
Dim sidString As String
Dim sidPtr As IntPtr
Dim sidStringPtr As IntPtr
Dim res As Integer
sidPtr = Marshal.AllocHGlobal(sid.L ength)
Marshal.Copy(sid, 0, sidPtr, sid.Length)
res = ConvertSidToStringSid(sidP tr, sidStringPtr)
If res = 0 Then
Throw New System.ComponentModel.Win3 2Exception (Marshal.G etLastWin3 2Error())
End If
sidString = Marshal.PtrToStringAuto(si dStringPtr )
Marshal.FreeHGlobal(sidPtr )
Marshal.FreeHGlobal(sidStr ingPtr)
Return sidString
End Function
<DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Function ConvertSidToStringSid(ByVa l pSID As IntPtr, ByRef pSidString As IntPtr) As Integer
End Function
End Module
Imports System.Management
Imports System.DirectoryServices
Imports Microsoft.Win32
Imports System.Runtime.InteropServ
Module UserInfo
Dim objManagementClass As ManagementClass
Dim objManagementScope As ManagementScope
Dim objManagementBaseObject As ManagementBaseObject
Public Function GetUser(ByVal RemotePC As String) As String
Dim WMIScope As Management.ManagementScope
Dim WMIConnectionOptions As New Management.ConnectionOptio
Dim strRootDomain As String
Dim objRootLDAP As DirectoryEntry
Dim query As ManagementObjectSearcher
Dim queryCollection As ManagementObjectCollection
Dim oq As New System.Management.ObjectQu
Dim mo As New ManagementObject
Dim UserDomain As String
Dim UserID As String
Dim StrLoggedUserSID() As Byte
Dim Strcomputer As String = RemotePC 'My.Application.CommandLin
'Console.WriteLine(Strcomp
With WMIConnectionOptions
.Impersonation = System.Management.Imperson
.Authentication = System.Management.Authenti
End With
WMIScope = New Management.ManagementScope
Strcomputer & "\root\cimv2", WMIConnectionOptions)
objRootLDAP = New DirectoryEntry("LDAP://Roo
strRootDomain = objRootLDAP.Properties.Ite
oq = New System.Management.ObjectQu
query = New ManagementObjectSearcher(W
queryCollection = query.Get()
If queryCollection.Count = 0 Then
Return ("Not logged in")
Exit Function
Else
Dim strKeyPath As String = "SOFTWARE\Microsoft\Window
objManagementScope = New ManagementScope
objManagementScope.Path.Se
objManagementScope.Path.Na
objManagementScope.Options
objManagementScope.Options
objManagementScope.Connect
objManagementClass = New ManagementClass("stdRegPro
objManagementClass.Scope = objManagementScope
objManagementBaseObject = objManagementClass.GetMeth
objManagementBaseObject.Se
objManagementBaseObject.Se
UserDomain = CStr(GetRegValues("Default
UserID = CStr(GetRegValues("Default
UserID = "DOMAIN\" & UserID
Return (UserID)
'If the SID or the full name is needed sometime in the future the code is below
'If UCase(UserDomain) = UCase(strcomputer) Then
'Console.WriteLine("Logged
'Exit Sub
'End If
'Dim LdapBind As String
'LdapBind = ("LDAP://" & strRootDomain)
'Dim deEntry3 As New DirectoryEntry(LdapBind)
'Dim DSearch As New DirectorySearcher(deEntry3
'With DSearch
' .SearchScope = SearchScope.Subtree
' .Filter = "(&(objectclass=user)(sAMA
' .PropertiesToLoad.Add("nam
' .PropertiesToLoad.Add("sAM
' .PropertiesToLoad.Add("dis
'End With
'Dim sResultSet As SearchResult
'For Each sResultSet In DSearch.FindAll()
' If UCase(GetProperty(sResultS
' Console.WriteLine("Logged on user = " & GetProperty(sResultSet, "name") & " (as " & _
' UserDomain & "\" & UserID & ")")
' Dim deEntry4 As New DirectoryEntry("LDAP://" & GetProperty(sResultSet, "distinguishedName").ToStr
' StrLoggedUserSID = CType(deEntry4.Properties(
' Console.WriteLine("User's SID = " & ConvertSid(StrLoggedUserSI
' End If
'Next
End If
End Function
Public Function GetProperty(ByVal srSearchResult As SearchResult, ByVal strPropertyName As String) As String
If srSearchResult.Properties.
Return srSearchResult.Properties(
Else
Return String.Empty
End If
End Function
Private Function GetRegValues(ByVal regkeyValue As String, ByVal regkey As String, ByVal Hive As String)
Select Case Hive
Case "HKLM"
Hive = CStr(RegistryHive.LocalMac
Case "HKU"
Hive = CStr(RegistryHive.Users)
Case "HKCU"
Hive = CStr(RegistryHive.CurrentU
Case "HKCR"
Hive = CStr(RegistryHive.ClassesR
End Select
objManagementBaseObject = objManagementClass.GetMeth
objManagementBaseObject.Se
objManagementBaseObject.Se
objManagementBaseObject.Se
objManagementBaseObject = objManagementClass.InvokeM
GetRegValues = objManagementBaseObject("s
End Function
Public Function ConvertSid(ByVal sid As Byte()) As String
Dim sidString As String
Dim sidPtr As IntPtr
Dim sidStringPtr As IntPtr
Dim res As Integer
sidPtr = Marshal.AllocHGlobal(sid.L
Marshal.Copy(sid, 0, sidPtr, sid.Length)
res = ConvertSidToStringSid(sidP
If res = 0 Then
Throw New System.ComponentModel.Win3
End If
sidString = Marshal.PtrToStringAuto(si
Marshal.FreeHGlobal(sidPtr
Marshal.FreeHGlobal(sidStr
Return sidString
End Function
<DllImport("advapi32.dll",
Private Function ConvertSidToStringSid(ByVa
End Function
End Module
I haven't worked with WMI enough to know if that code is safe or not for use across multiple threads... =\
ASKER
Is there another way I can keep this running in mutiple threads? The application is too slow to run in a single thread so I would like to keep it like this. Chad
I am not sure if this would help but worth a try.
Create a class which contains two strings of machinename and username. Add the functions to the class to get the username and set the username property based on the machinename in the class. Then create a list of objects of this class, set the machinenames, and use threads on the methods in the objects. Or you may want to use a backgroundworker within the class to get the username.
Create a class which contains two strings of machinename and username. Add the functions to the class to get the username and set the username property based on the machinename in the class. Then create a list of objects of this class, set the machinenames, and use threads on the methods in the objects. Or you may want to use a backgroundworker within the class to get the username.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I still have not gotten this to work. I am stuck using net 2.0 on the server I have to run this on. Any other ideas how to make this call safe to use with mutiple threads?
ASKER
Could I also just I also make 10 modules and call them all separate names? Then have each thread call a different one? Currently I'm stuck running this in a single thread and it's taking to long.
Can we see the function?