Sign in to follow this  
Followers 0

Memory leak using ADSI

7 posts in this topic

Posted

I'm experiencing a memory leak when creating IADsUser objects.

The script I'm running is like reads a list of users from an inputfile and gather some account information.

Even tried assigning $objUser=0 but the memory usage keeps growing.

Here is some example code of what I'm doing:

$file = FileOpen("input.txt", 0)

; Check if file opened for reading OK
If $file = -1 Then
    MsgBox(0, "Error", "Unable to open file.")
    Exit
EndIf

; Read in lines of text until the EOF is reached
While 1
    $line = FileReadLine($file)
    If @error = -1 Then ExitLoop

    $objUser=ObjGet("LDAP://CN=" & $line & ",DC=Fabrikam,DC=Com")
    ; Reads some user properties
    $objUser=0
Wend

FileClose($file)

In each loop iteration, the memory keeps growing. For a list of 20000 users, this is really a problem!

The script reached about 450MB of memory usage.

The same thing happens when not using an inputfile and getting the users list from an AD query.

A workaround I've found was to create another script, which creates the user object and reads the user information, and in each loop iteration, call this script. Doing this, when the called script is terminated, the memory is released, but this method is much slower, as a new process is created for each user.

Maybe I'm missing some function or method to release the memory, but assigning the variable to 0 is the only method I've found in the forums and documentation.

Hope someone can help me.

Thank You,

Leandro

Share this post


Link to post
Share on other sites



Posted

Can you create a script that doesn't use LDAP? I don't have access to anything like that. If you can demonstrate a memory leak with Microsoft Office or WMI or a standard Windows object, I can take a look but otherwise I don't have time to debug an issue I can't duplicate.

Share this post


Link to post
Share on other sites

Posted (edited)

I'm experiencing a memory leak when creating IADsUser objects.

Leandro, to ensure that the [possible] leak is where you think it is, you may wish to read your list of users into an array before looping. I have not noticed any issues with AD/au3 -- but neither I nor my clients have 20k users either :) Edited by flyingboz

Share this post


Link to post
Share on other sites

Posted

Valik,

I've reproduced the error using a WMI object.

flyingboz,

This script uses an array as you suggested.

The error ocurred only with ObjGet() function. I've tried another script with ObjCreate() and the error did not occurs.

Follows the script (there is a screen capture of the script execution process history attached):

#include <array.au3>

$files = _GetFiles("c:\windows\system32")

for $file in $files
    $escapedFileName=StringReplace($file,"\","\\")
    $objDataFile=ObjGet('winmgmts:\\localhost\root\cimv2:CIM_DataFile.Name="' & $escapedFileName & '"')

    ConsoleWrite( $objDataFile.name & @tab & $objDataFile.version & @lf)
    $objDataFile=0
Next

Func _GetFiles( $_folder )
    Local $_array
    $_array=0
    $search = FileFindFirstFile($_folder & "\*.*")

    If $search = -1 Then
        Return (1)
    EndIf

    While 1
        $file = FileFindNextFile($search) 
        If @error Then ExitLoop
        
        If $file<>"." and $file<>".." Then
            ;verify if is a directory
            if not StringInStr(FileGetAttrib($_folder & "\" & $file),"D") Then
                if IsArray($_array) Then
                    _ArrayAdd($_array,$_folder & "\" & $file)
                Else
                    $_array=_ArrayCreate($_folder & "\" & $file)
                EndIf
            EndIf
        EndIf
    WEnd

    ; Close the search handle
    FileClose($search)

    Return($_array)

EndFunc

Thanks

post-16518-1168897667_thumb.jpg

Share this post


Link to post
Share on other sites

Posted

I can see that the script is indeed leaking something. Not sure why yet. I'll take a closer look when I get a chance.

Share this post


Link to post
Share on other sites

Posted

Hello Leandro,

I currently have no solution for the memory problem itself, but I can give you some hints to avoid it.

Rule of thumb: try to avoid ObjGet commands inside loops. ObjGet/ObjCreate calls are very time and resource consuming,

So, when you design scripts, use this structure when looping and ObjGets are involved:

1. Open a connection to the object(s) required using ObjGet/ObjCreate.

2. start the loop

3. use object-functions or methods to retrieve your data

4. end loop

5. close the object(s) by assigning any values to their variable.

In case of your ADSI script you can solve it by using a ADODB connection:

; Section 1: open connections to object(s) required

$objConnection = ObjCreate("ADODB.Connection")
$objConnection.Open("Provider=ADsDSOObject;")
 
$objCommand = ObjCreate("ADODB.Command")
$objCommand.ActiveConnection = $objConnection

$file = FileOpen("input.txt", 0)


; Section 2: start the loop

While 1
  $line = FileReadLine($file)
  
  If @error = -1 Then ExitLoop

  ; Section 3: retrieve your data

   $objCommand.CommandText = "<LDAP://dc=fabrikam,dc=com>;(&(objectCategory=User)" & _
         "(cn=" & $line & "));cn,distinguishedName,samAccountName;subtree"

   ; Change the line above to suite your needs.
   ; This example retrieves the fields distinguishedName,cn and samAccountName from a user object
   ; using a subtree search  (remove the word 'subtree' when a subtree search is not required)

  $objRecordSet = $objCommand.Execute

  ; The command will return a RecordSet type, not a AdUser object type. 

  If $objRecordset.RecordCount = 0 Then
    ; user does not exist 
  Else
    ; Do anything you want with the retrieved properties

    While Not $objRecordSet.EOF
    ConsoleWrite($objRecordSet.Fields("cn") & "," & $objRecordSet.Fields("distinguishedName") & @CR)
    Wend

  EndIf


; Section 4: End loop

  $objRecordSet.close   ; Clean this up before next loop.
  $objRecordSet=0   ; not really required, but it looks better.
wend 


; Section 5: clean up objects and close the connection.

$objCommand=0
$objConnection.Close
$objConnection=0

FileClose($File)
oÝ÷ ÙK"®*m²Ú,yªÜ§-÷·¶òIìÊ{ZÆêå

Regards,

-Sven

Share this post


Link to post
Share on other sites

Posted

Moving this to NO BUG. There is a duplicate bug report at the link below. The issue will be addressed there. I'm not moving this to FIXED because it isn't fixed (yet), just cleaning up duplicate threads. Follow the new thread for developments.

http://www.autoitscript.com/forum/index.php?showtopic=59866

Share this post


Link to post
Share on other sites
Sign in to follow this  
Followers 0

  • Recently Browsing   0 members

    No registered users viewing this page.