Jump to content

This site uses cookies. By continuing to browse the site you are agreeing to our use of cookies. Find out more here. X
X


Photo

Memory leak using ADSI


  • Please log in to reply
6 replies to this topic

#1 Leandro Conca

Leandro Conca

    Seeker

  • Active Members
  • 12 posts

Posted 15 January 2007 - 08:03 PM

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







#2 Valik

Valik

    Former developer.

  • Active Members
  • PipPipPipPipPipPip
  • 18,879 posts

Posted 15 January 2007 - 08:19 PM

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.

#3 flyingboz

flyingboz

    The Network Is All

  • Active Members
  • PipPipPipPipPipPip
  • 768 posts

Posted 15 January 2007 - 09:44 PM

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, 15 January 2007 - 09:45 PM.

Reading the help file before you post... Not only will it make you look smarter, it will make you smarter.

#4 Leandro Conca

Leandro Conca

    Seeker

  • Active Members
  • 12 posts

Posted 15 January 2007 - 09:52 PM

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):

AutoIt         
#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

Attached Thumbnails

  • memoryLeak.jpg


#5 Valik

Valik

    Former developer.

  • Active Members
  • PipPipPipPipPipPip
  • 18,879 posts

Posted 16 January 2007 - 12:05 AM

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.

#6 SvenP

SvenP

    AutoIt COMposer

  • Developers
  • 639 posts

Posted 20 January 2007 - 08:23 PM

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:

AutoIt         
; 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

#7 Valik

Valik

    Former developer.

  • Active Members
  • PipPipPipPipPipPip
  • 18,879 posts

Posted 23 December 2007 - 03:31 PM

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




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users