OLEObject in thread locks main thread?

Hello everybody,

I’m trying to do a simple login window, where the actual login is based on a LDAP query to an Active Directory server. The objective is to grant logon if the user is able to logon to AD and is member of a specified security group. I’ve got the code working, but during the process the GUI freezes, despite having the code in a separate thread (with a timer that checks when the thread is done). The threads reads and writes to a number of properties on the login window.

Is there a problem running OLEObject from threads, or am i doing something wrong?

This is the code from the Run event of the thread:

[code] Dim strUser, strPassword, strServer, strQuery As String
Dim adoConnection, adoCommand,adoRecordset As OleObject
Dim Success As Boolean

//Set strings for user and pass based on properties
strUser = UserNamePrefix + TheUser
strPassword = ThePassword

//Try to get DC if not specified
If LogonServer = “” Then
LogonServer = ReplaceAll(system.EnvironmentVariable(“LOGONSERVER”), “”, “”)
End If

//Defines the query based on properties
strQuery = “SELECT sAMAccountName FROM 'LDAP://” + LogonServer + “’ WHERE objectCategory = ‘Person’ AND memberOf = '” + LDAPQuery + "’ "

//Defines the connection
adoConnection = new OLEObject(“ADODB.Connection”)
adoConnection.Provider = “ADsDSOOBJECT”
adoConnection.Properties(“User ID”) = strUser
adoConnection.Properties(“Password”) = strPassword
adoConnection.Properties(“Encrypt Password”) = false
adoConnection.open (“DS Query”, strUser, strPassword)

adoCommand = New OleObject(“ADODB.Command”)
adoCommand.ActiveConnection = adoConnection
adoCommand.CommandText = strQuery

adoRecordset = New OLEObject(“ADODB.Recordset”)

adoRecordset = adoCommand.Execute()
Catch ExecuteError As OLEException
// Did not manage to login. Puts error message in property and resets connection.
ErrMsg = ExecuteError.message

adoConnection = Nil
adoCommand = Nil
adoRecordset = Nil

End Try

//Loops through recordsets and tries to find the matching username.
While Not adoRecordset.eof
If adoRecordset.Fields(“sAMAccountName”).Value = NthField(strUser, “”, 2) Then
//Found match and flags success
Success = True
End If

// Set property LoginResult depending on if match was found.
If Success Then
LoginResult = True
LoginResult = False
End If

//Resets connection.
adoConnection = Nil
adoCommand = Nil
adoRecordset = Nil

exception err as oleexception
ErrMsg = err.message[/code]

In addition there is a timer, and this is what it does:

[code] If LoginThread.State <> Thread.Running Then
Me.Mode = Timer.ModeOff
ProgWheel.Visible = False

//If there is no error message from thread.
If ErrMsg = "" Then
  //Checks whether the login was successful or not.
  If LoginResult Then
    LoginResult = False
    MsgBox "Login successful"
    MsgBox "Login failed"
  End If
  //Displays error message.
  MsgBox ErrMsg
  ErrMsg = ""
End If

End If[/code]

Why does my GUI freeze when running this?

Hi Henrik,
You will need to manually initialize COM with the multi-threaded concurrency model in App.Open for example, and in each thread that it is used. The declare would look something like this:

#if TargetWin32
Declare Sub CoInitializeEx Lib “ole32” (reserved As Integer, model As Integer)

We don’t do this by default since doing so breaks ActiveX controls and potentially other COM related things.

Hi William,
Thanks for the info. I’ve done as you suggested, but it does not seem to help. Maybe I’m not doing it the way its supposed to be done.

I’ve added

#if TargetWin32
Declare Sub CoInitializeEx Lib “ole32” (reserved As Integer, model As Integer)

in both App.Open as well as in the beginning of the Run-event of the thread (don’t know if that is necessary…). Unfortunately it still freezes for about three to four seconds before working. If I run the code one more time though, it seems to work fine, with no freezing or delay. So it’s probably the initializing that makes the GUI freeze.

Think I may have to do a workaround of some sort here…

A helper app comes to mind.

Thought of a helper app, but seems overly complicated just to avoid a couple of seconds of delay. Think I’ll just throw in a label that says “Please wait…” for now…