WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

UDF - UDS Library
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

Free WinBatch Resources UDF

 Keywords:  Unload Free Resources Garbage Collector Collection UDF UDS IntControl 77 File Handle Variables Binary Buffer COM OLE Object Arrays Registry DLL WinBatch 

;***************************************************************************
;**            udfFreeResources( nScopeFlag, nShowFlag )
;**
;** Keywords: Free Unload Resources Garbage Collector Collection UDF UDS
;**
;** Purpose: Close open handles and free resources explicitly.
;**          This UDS should be called at the END of your script.
;**
;** Background: WinBatch automatically frees resources when it exits. However If you have a main script calling
;**  multiple scripts using the Call function, the resources created by the called script are not freed upon return
;**  One way to handle this is to use RunWait() instead of Call(). The issue with RunWait is the variables are not
;**  shared between the Main script and the Called scripts.
;**
;** Parameters:
;**  [nScopeFlag Parameter]
;**   0 : Free All Resources. This will also free resource in the Main Script!!!!
;**       This option does not handle Registry & Dll handles.
;**
;**   1 : Free Only Prefixed Resources. This assumes you named all the various elements in your script
;**       with these leading characters:
;**            f_   File handles
;**            b_   Binary buffers
;**            o_   COM Object handles
;**            v_   Variables - includes: Strings, Integer, Floating Point, Arrays & Variants
;**       This option can also be used to handle closing these prefixed Registry & Dll handles:
;**            r_   Registry handles defined with RegOpenKey.
;**            d_   Dll handles defined with DllLoad.
;**            c_   DllCallback handles defined with DllCallbackCreate.
;**
;**  [nShowFlag Parameter]
;**   0 : Do Not Show Progress Messages.
;**   1 : Show Progress Messages.
;**
;** DevNotes:
;**  The Drop function automatically free Arrays, COM object and Strings but
;**  Binary Buffers, File Handles, Remote Registry handles and Dll/DllCallBack handles are not.
;**
;**  WinBatch automatically frees the following resources when it exits: Arrays, COM object and Strings
;**  That is because WinBatch reference counts these items.
;**  However binary buffers, file, registry and Dll/DllCallBack handles are not reference counted and
;**  are the responsibility of the script developer to release them.
;**
;**
;** TO DO: nada.
;**
;** Revisions:
;**  1.0 ( 2012.11.15 ) Deana Falk
;**  Initial Release.
;**  1.1 ( 2013.01.31 ) Deana Falk
;**  Added code to attempt to free any loaded extender dlls.
;**
;***************************************************************************
#DefineSubRoutine udfFreeResources(nScopeFlag,nShowFlag)

   sVars = IntControl (77, 12, 0, 0, 0) ; List of variables assigned
   nTimeout = 0 ; Effects the amount of time used to display messages if nShowFlag = 1

   sSkipVars = 'n,sVars,sVarEntry,nType,nTimeout,sPreFix,nScopeFlag,nShowFlag' ; Ignore these vars for now , will drop later
   If nShowFlag Then BoxOpen('Freed Resources - Total Items = ' : ItemCount( sVars, @TAB ), '' )

   For n=1 To ItemCount( sVars, @TAB )
      sVarEntry = ItemExtract( n, sVars, @TAB ) ; Get assigned variable name

      ; Skip UDS variables and Drop() them just before returning
      If ItemLocate( StrLower( sVarEntry ), StrLower( sSkipVars ), ',' ) Then Continue

      nType = VarType( %sVarEntry% ) ; Gets the data type of a variable
      sPrefix = StrSub( sVarEntry, 1, 2 ) ; Gets the Prefix of the varaible

      Switch nType
         Case -1   ; Function name, reserved word or string constant
         Case 0    ; Undefined
            ; Ignore function name, reserved word or string constant and UNDEFINED variables
            Break
         Case 1    ; Integer
            If sPreFix == 'r_' && nScopeFlag == 1  ; Registry Key Handle
               If nShowFlag Then BoxText( 'Closing Registry Handle: ': sVarEntry )
               TimeDelay( nTimeout )
               RegCloseKey( %sVarEntry% )
            EndIf
            If sPreFix == 'c_' && nScopeFlag == 1  ; DllCallback Handle
               If nShowFlag Then BoxText( 'Closing DllCallback Handle: ': sVarEntry )
               TimeDelay( nTimeout )
               DllCallbackDestroy( %sVarEntry% )
            EndIf
         Case 2    ; String
             If sPreFix == 'd_' && nScopeFlag == 1  ; Dll Handle
                If nShowFlag Then BoxText( 'Closing Dll Handle: ': sVarEntry )
                TimeDelay( nTimeout )
                DllFree( %sVarEntry% )
            EndIf
         Case 32   ; Floating point value
         Case 128  ; LPWSTR or "Unicode"
         Case 256  ; Array
         Case 512  ; Variant
            If nShowFlag Then BoxText( 'Dropping Variable: ': sVarEntry )
            TimeDelay( nTimeout )
            Break
         Case nType|4 ; File Handle
            If nShowFlag Then BoxText( 'Closing File Handle Variable: ': sVarEntry )
            TimeDelay( nTimeout )
            If sPreFix == 'f_' && nScopeFlag == 1
               FileClose( %sVarEntry% )
            Else
               FileClose( %sVarEntry% )
            EndIf
            Break
         Case nType|64 ; Binary Buffer
            If nShowFlag Then BoxText( 'Closing Binary Buffer Handle: ': sVarEntry )
            TimeDelay( nTimeout )
            If sPreFix == 'b_' && nScopeFlag == 1
               BinaryFree( %sVarEntry% )
            Else
               BinaryFree( %sVarEntry% )
            EndIf
            Break
         Case nType|1024 ; COM Object Handle
            If nShowFlag Then BoxText( 'Closing COM Object Handle: ': sVarEntry )
            TimeDelay(nTimeout)
            If sPreFix == 'o_' && nScopeFlag == 1
               %sVarEntry% = 0
            Else
               %sVarEntry% = 0
            EndIf
            Break
      EndSwitch

      If nScopeFlag == 1 ;Check flag - Free Only Called Resources.
         If sPreFix == 'f_' || sPreFix == 'b_' || sPreFix == 'o_'  || sPreFix == 'v_' || sPreFix == 'r_' || sPreFix == 'd_' || sPreFix == 'c_'
            Drop(%sVarEntry%)
         EndIf
         ; Must Also Explicitly Remove Params
         If StrSub( StrLower( sVarEntry), 1, 5 ) == 'param'
            Drop(%sVarEntry%)
         EndIf
      Else
         Drop(%sVarEntry%) ;Drops All Vars Regardless of Prefix
      EndIf
   Next

   ;***************************************************************************
   ;**
   ;**   Frees all UDF/UDS's
   ;**
   ;**   IMPORTANT: This cannot be called inside any UDS/UDF
   ;**   Make sure to call this function after calling this UDS.
   ;**   NOTE: Frees all UDS/UDFs from both the Main and any called scripts.
   ;**
   ;***************************************************************************
   ;**   IntControl(78, 0, 0, 0, 0)

   ;***************************************************************************
   ;**
   ;**   Unload Extenders using udfRemoveExtender
   ;**   Unfortunately there is currently no way to accomplish this currently
   ;**
   ;***************************************************************************
   ;
   ; nExtender = IntControl (77, 40, 0, 0, 0) ; number of extenders loaded
   ; nSlots = IntControl (77, 41, 0, 0, 0) ; number of extender slots available
   ; sExtList = IntControl (77, 42, 0, 0, 0) ; tab-delimited list of extenders loaded
   ;If IntControl (77, 40, 0, 0, 0) > 0
      ;; Exiting the script automagically frees Extender resources
      ;udfRemoveExtender( AskItemList("Extenders Loaded", IntControl (77, 42, 0, 0, 0), @Tab, @Sorted, @single ) )
   ;EndIf

   ;***************************************************************************
   ;**
   ;**      Drop all variables defined in this UDS
   ;**
   ;***************************************************************************
   ;
   If nShowFlag Then BoxText( 'Done Freeing Resources' )
   sSkipVars = sSkipVars:',sSkipVars'; Don't forget to include this var
   Drop(%sSkipVars%)


   ;***************************************************************************
   ;**
   ;**  Error Checking
   ;**  Confirm Resources Have Been Freed
   ;**
   ;***************************************************************************
   ;
   ;   20 number of files open
   ;   30 number of binary buffers open
   ;   40 number of extenders loaded  ( not currently handled  )
   ;   60 number of COM/OLE objects open
   ;   90 number of UDF's defined ( not currently handled - expect 1  )
   ;   110 number of DDE conversations open
   ;Pause( 'Number of Files Open', IntControl(77,20,0,0,0)); Expect 0
   ;Pause( 'Number of Binary Buffers Open', IntControl(77,30,0,0,0)); Expect 0
   ;Pause( 'Number of COM/OLE Objects Open', IntControl(77,60,0,0,0)); Expect 0
   If IntControl( 77,20,0,0,0 ) != 0 Then Pause( 'Notice', 'Number of Files Open ' : IntControl(77,20,0,0,0) )  ; Number of Files Open - Expect 0
   If IntControl( 77,30,0,0,0 ) != 0 Then Pause( 'Notice', 'Number of Binary Buffers Open ' : IntControl(77,30,0,0,0) )  ; Number of Binary Buffers Open - Expect 0
   If IntControl( 77,60,0,0,0 ) != 0 Then Pause( 'Notice', 'Number of COM/OLE Objects Open ' : IntControl(77,60,0,0,0) )  ; Number of COM/OLE Objects Open - Expect 0

   Return 1

#EndSubRoutine

#DefineFunction udfRemoveExtender( dllname )
   ; Free Unload Remove Delete Extender
   ;
   ; if udfRemoveExtender is used you must call
   ; Quiet function avoid the Exit Error : Could not access Extender Entry 0x02
   ;
   ; Get Module Handle
   modulehandle = DllCall(StrCat(DirWindows(1),"kernel32.dll"),long:'GetModuleHandleA',lpstr:dllname)
   If modulehandle == 0
      err = DllLastError()
      Message('GetModuleHandleA Failed', err)
      Exit
   EndIf
   ; Free Module
   result = DllCall(StrCat(DirWindows(1),"kernel32.dll"),long:'FreeLibrary',long:modulehandle)
   Return result
#EndFunction
;------------------------------------------------------------------------------
;                   MAIN
;------------------------------------------------------------------------------

AddExtender( 'wwint44i.dll' )

;------------------------------------------------------------------------------
;                   Inputs
;------------------------------------------------------------------------------
;nScopeFlag = 0 ; Frees Resources for Main and Called scripts : excludes Registry and Dll handles
nScopeFlag = 1 ; Frees Prefixed Resources : includes Registry and Dll handles
;nShowFlag = 0  ; Do Not Show Progress Messages.
nShowFlag = 1  ; Show Progress Messages.

;------------------------------------------------------------------------------
;                   Test Variables
;------------------------------------------------------------------------------
param0 = 1
param1 = 'nada'
v_sample = "dummy"
v_array = ArrDimension( 1,1 )
f_handle = FileOpen( 'c:\temp\dummy.txt', 'Write' )
b_buffer = BinaryAlloc(1)
o_object = ObjectCreate( 'WbemScripting.SWbemLocator' );ObjectCreate( 'InternetExplorer.Application' )
If nScopeFlag == 1 ;Only test these variables if nScopeFlag = 1
   r_regkey = RegOpenKey( @REGCLASSES, '.wbt' )
   d_dll = DllLoad( DirWindows(1):'USER32.DLL' )
   #DefineFunction udfDummyCallback()
     Return 1
   #EndFunction
   c_callback = DllCallbackCreate('udfDummyCallback', 'LONG', '')
EndIf

;------------------------------------------------------------------------------
;                   Free Resources UDS
;------------------------------------------------------------------------------
udfFreeResources( nScopeFlag, nShowFlag )

;------------------------------------------------------------------------------
;                   Free All UDF / UDSs
; Note: Frees all UDF/UDS's. Global Scope. Only call IntControl 78, if necessary.
;------------------------------------------------------------------------------
;IntControl(78, 0, 0, 0, 0)

;------------------------------------------------------------------------------
;                   Confirm Results
;------------------------------------------------------------------------------
; Proof Resources Have Been Freed
AskItemlist('udfFreeResources : ' : ItemCount( IntControl (77, 12, 0, 0, 0), @TAB ), IntControl (77, 12, 0, 0, 0), @TAB, @SORTED, @SINGLE)
If IsDefined(v_sample) || IsDefined(v_array) || IsDefined(f_handle) || IsDefined(b_buffer)|| IsDefined(o_object) || IsDefined(r_regkey)  || IsDefined(d_dll) || IsDefined(c_callback) || IsDefined(param0)
    Pause('Problem','These should no longer be defined.')
EndIf



;*****IMPORTANT *******
; if udfRemoveExtender is used you must call
; Quiet function avoid the Exit Error : Could not access Extender Entry 0x02
;IntControl( 38, 1, '', 0, 0)
Exit

Article ID:   W18333
Filename:   Free WinBatch Resources UDF.txt
File Created: 2013:01:31:16:50:22
Last Updated: 2013:01:31:16:50:22