Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.
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