none
Unable to catch error in function RRS feed

  • Question

  • Hello all, 

    Lately I have decided to write some functions because I copy/paste a lot of my VBS code. Functions should make it easier to recycle written code, but I'm having troubles with catching errors in case anything goes wrong... 

    The code inside the functions is what we used all the time in hundreds of scripts (always copy / pasted, without functions) so I'm absolutely positive that is correct and works, but when I place it inside a function, the function quits when anything goes wrong like deleting a folder from which a file is still in use. When I remove the start and the end of the function around the code, the error is caught and written to the log, but inside the function it quits and goes on with the rest of the scipt... 

    We've been looking with a few colleagues for hours, without results. Hope you guys can tell me what we're doing wrong. 

    A script without functions to delete the folder C:\Program Files\Alfa which works, whether you have a file in that folder in use or not. It will write the error to the log in that case: 

    On error resume next
    Dim objFS,strRunCmd,killErr,strErcode,WshShell,strInstallPath,strLogFile
    Set objFS = CreateObject("Scripting.FileSystemObject")
    Set WshShell = WScript.CreateObject("WScript.Shell")
    OsType = WshShell.RegRead("HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\PROCESSOR_ARCHITECTURE")
    AppData = WshShell.ExpandEnvironmentStrings("%APPDATA%")
    UserName = wshShell.ExpandEnvironmentStrings("%USERNAME%")
    Set objNet = WScript.CreateObject("Wscript.NetWork")
    strComputerName = objNet.ComputerName
    strComputer = "."
    Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
    
    exitcode = 0
    
    'Log name
    Set strLogFile = objFS.CreateTextFile("C:\Windows\Temp\Alfa_Adsuite_2013_2.log", True,False)
    
    'Log info
    strInstallPath = objFS.GetFile(WScript.ScriptFullName).Parentfolder
    strLogfile.WriteLine("***************************************************")
    strLogfile.WriteLine("***************************************************")
    strLogfile.WriteLine("************** Alfa Adsuite 2013.2 ****************")
    strLogfile.WriteLine("***************************************************")
    strLogfile.WriteLine("***************************************************")
    strLogfile.WriteBlankLines(1)
    strLogfile.WriteLine(" - Install path = " & strInstallPath)
    strLogfile.WriteLine(" - Time = " & now)
    strLogfile.WriteBlankLines(2)
    
    'Determine OS Type
    If (instr(osType,"64")) Then
    	processor = "x64" 
    	pf = "Program Files (x86)"
    	sysfolder = "SysWOW64"
    	strLogfile.WriteLine("Processor architecture = " & osType) 
    	strLogfile.WriteLine("--> 64-bit Windows found <--") 
    	strLogfile.WriteBlankLines(2)
    Else
    	processor = "x86"
    	pf = "Program Files"
    	sysfolder = "System32"
    	strLogfile.WriteLine("Processor architecture = " & osType) 
    	strLogfile.WriteLine("--> 32-bit Windows found <--")
    	strLogfile.WriteBlankLines(2)
    End If
    
    '''''''''''''''
    ''' INSTALL '''
    '''''''''''''''
    
    strFolderName = "C:\Program Files\Alfa"
    strNumber = 10
    
    'Delete Alfa folder
    strLogfile.WriteLine("*** Delete folder " & strFolderName & " for max " & strNumber & " times - " & now)
    strLogfile.WriteBlankLines(1)
    FolderFound = 1
    Index = 1
    IndexEnd = strNumber
    
    'Try X times to delete folder
    If objFS.FolderExists (strFolderName) Then
    	Do While FolderFound = 1 And Index < IndexEnd + 1
    		strLogfile.WriteLine(" * Attempt " & Index)
    		Err.Clear
    		objFS.DeleteFolder (strFolderName)
    		
    		If Err.Number <> 0 Then 
    			FolderFound = 1
    			strLogfile.WriteLine(" - Unable to delete " & strFolderName & ": " & Err.Description)
    			strLogfile.WriteBlankLines(1)
    			Err.Clear
    			wscript.sleep 10000
    		Else
    			FolderFound = 0
    			strLogfile.WriteLine(" + Folder " & strFolderName & " deleted")
    			strLogFile.WriteBlankLines(1)
    		End If
    
    		Index = Index + 1
    	Loop
    	
    	'Check if folder is gone, otherwise count as error
    	If objFS.FolderExists (strFolderName) Then
    		exitcode = exitcode + 1
    	End If
    Else
    	strLogfile.WriteLine(" * " & strFolderName & " not found")
    	strLogfile.WriteBlankLines(1)
    End If
    
    'End Script
    strLogfile.WriteBlankLines(1)
    StrLogfile.WriteLine("Exitcode = " & exitcode & " - " & now)
    
    strLogFile.Close
    
    wscript.quit(exitcode)

    A script with a function to delete the folder C:\Program Files\Alfa which DOES NOT WORK when you have a file in that folder in use but which DOES WORK when no files are in use, you can try it for yourself:

    On error resume next
    Dim objFS,strRunCmd,killErr,strErcode,WshShell,strInstallPath,strLogFile
    Set objFS = CreateObject("Scripting.FileSystemObject")
    Set WshShell = WScript.CreateObject("WScript.Shell")
    OsType = WshShell.RegRead("HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\PROCESSOR_ARCHITECTURE")
    AppData = WshShell.ExpandEnvironmentStrings("%APPDATA%")
    UserName = wshShell.ExpandEnvironmentStrings("%USERNAME%")
    Set objNet = WScript.CreateObject("Wscript.NetWork")
    strComputerName = objNet.ComputerName
    strComputer = "."
    Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
    
    exitcode = 0
    
    'Log name
    Set strLogFile = objFS.CreateTextFile("C:\Windows\Temp\Alfa_Adsuite_2013_2.log", True,False)
    
    'Log info
    strInstallPath = objFS.GetFile(WScript.ScriptFullName).Parentfolder
    strLogfile.WriteLine("***************************************************")
    strLogfile.WriteLine("***************************************************")
    strLogfile.WriteLine("************** Alfa Adsuite 2013.2 ****************")
    strLogfile.WriteLine("***************************************************")
    strLogfile.WriteLine("***************************************************")
    strLogfile.WriteBlankLines(1)
    strLogfile.WriteLine(" - Install path = " & strInstallPath)
    strLogfile.WriteLine(" - Time = " & now)
    strLogfile.WriteBlankLines(2)
    
    'Determine OS Type
    If (instr(osType,"64")) Then
    	processor = "x64" 
    	pf = "Program Files (x86)"
    	sysfolder = "SysWOW64"
    	strLogfile.WriteLine("Processor architecture = " & osType) 
    	strLogfile.WriteLine("--> 64-bit Windows found <--") 
    	strLogfile.WriteBlankLines(2)
    Else
    	processor = "x86"
    	pf = "Program Files"
    	sysfolder = "System32"
    	strLogfile.WriteLine("Processor architecture = " & osType) 
    	strLogfile.WriteLine("--> 32-bit Windows found <--")
    	strLogfile.WriteBlankLines(2)
    End If
    
    '''''''''''''''
    ''' INSTALL '''
    '''''''''''''''
    
    'Delete Alfa folder
    delete_alfa = fn_delete_folder_X_attempts ("C:\Program Files\Alfa",10)
    StrLogfile.WriteLine("--> Delete Alfa folder functioncode = " & delete_alfa)
    strLogfile.WriteBlankLines(1)
    
    'End Script
    strLogfile.WriteBlankLines(1)
    StrLogfile.WriteLine("Exitcode = " & exitcode & " - " & now)
    
    strLogFile.Close
    
    wscript.quit(exitcode)
    
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ''' FUNCTIONS - DO NOT EDIT UNLESS YOU KNOW WHAT YOU ARE DOING !!! '''
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ''' INDEX ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ''' fn_delete_folder_X_attempts
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    
    '---------------------------------------------------------------------------------
    '*** fn_delete_folder_X_attempts - Delete a folder, retry X times when failing ***
    '---------------------------------------------------------------------------------
    'EXAMPLE
    'Folder_B = fn_delete_folder_X_attempts ("C:\Folder_A\Folder_B",5)
    '-----------------------------------------------------------------
    Function fn_delete_folder_X_attempts (strFolderName,strNumber)
    	strLogfile.WriteLine("*** Delete folder " & strFolderName & " for max " & strNumber & " times - " & now)
    	strLogfile.WriteBlankLines(1)
    	fn_delete_folder_X_attempts_code = 0
    	FolderFound = 1
    	Index = 1
    	IndexEnd = strNumber
    	
    	'Try X times to delete folder
    	If objFS.FolderExists (strFolderName) Then
    		Do While FolderFound = 1 And Index < IndexEnd + 1
    			strLogfile.WriteLine(" * Attempt " & Index)
    			Err.Clear
    			objFS.DeleteFolder (strFolderName)
    			
    			If Err.Number <> 0 Then 
    				FolderFound = 1
    				strLogfile.WriteLine(" - Unable to delete " & strFolderName & ": " & Err.Description)
    				strLogfile.WriteBlankLines(1)
    				Err.Clear
    				wscript.sleep 10000
    			Else
    				FolderFound = 0
    				strLogfile.WriteLine(" + Folder " & strFolderName & " deleted")
    				strLogFile.WriteBlankLines(1)
    			End If
    
    			Index = Index + 1
    		Loop
    		
    		'Check if folder is gone, otherwise count as error
    		If objFS.FolderExists (strFolderName) Then
    			exitcode = exitcode + 1
    			fn_delete_folder_X_attempts_code = fn_delete_folder_X_attempts_code + 1
    		End If
    	Else
    		strLogfile.WriteLine(" * " & strFolderName & " not found")
    		strLogfile.WriteBlankLines(1)
    	End If
    
    	Err.Clear
    	
    	'Function result
    	fn_delete_folder_X_attempts = fn_delete_folder_X_attempts_code
    End Function



    Tuesday, December 24, 2013 3:09 PM

Answers

  • Hint.

    Just before this line:

    objFS.DeleteFolder (strFolderName)

    Add "On Error Resume Next"

    Get rid of all Err.Clear statements


    ¯\_(ツ)_/¯

    Tuesday, December 24, 2013 11:22 PM

All replies

  • Hi,

    1. Remove the On Error Resume Next. That line of code masks all errors. Do not use that line unless you understand what it does and how it works.

    2. For quickest help, you need to post a short, self-contained, working example script that provides only the minimum amount of code needed to reproduce the problem, and then ask a specific question.

    Bill

    • Proposed as answer by jrv Tuesday, December 24, 2013 5:37 PM
    • Unproposed as answer by Jonathan De Nil Tuesday, December 24, 2013 10:28 PM
    Tuesday, December 24, 2013 4:45 PM
    Moderator
  • Bill's answer is exactly what you need.  I would add that you need to review how to use error handling in functions.  The rules are a bit different when in a function.

    There is a section on the VBScript learning page about how to use error management.

    http://technet.microsoft.com/library/ee176982.aspx

    Function error handlers only work inside the function and are canceled when you leave the function or are returned to the state set by the function caller.

    Functions also inherit the state of the caller. 

    Example:

    A
    
    Function A()
    On Error Resume Next
    B
    End Function
    
    Function B()
    x = 1/0
    End Function
    

    Function A turns off automatic error handling and calls function B which generates an error.  If you run it you will never see the error in B.

    Normally I write small simple functions with an error handler and only ever turn on error handling at the lowest level.  THis makes code design easier most of the time although it isn't useful in every case.


    ¯\_(ツ)_/¯

    Tuesday, December 24, 2013 5:50 PM
  • I should have mentioned that I had tried removing "on error resume next" from the script already but that makes it only more curious. When executing the second script that I posted (try to delete a folder from which a file is open) without this line, a pop-up error is thrown for the line "objFS.DeleteFolder strFolderName" with the description "Permission denied". So I know that the error is there, where I expect it because the file is open, but when I run that same script WITH the line "on error resume next" that error is not written into the log file, although that's what I'm asking to do in the function. That's the part I don't get: there is an error, but I can't catch it and write it to the log. On top of all that the function exits.

    I know I posted long code but I wanted to be complete and very specific here because I have the feeling that it could be more complex than it looks at first sight. It is very easy to reproduce though, and I would really appreciate if someone of you could follow these steps to do so and see what happens exactly for yourself (by looking into the logfile). 

    1. Create a folder "Alfa" in "C:\Program Files"

    2. Create a text file inside that folder. Write a few words in it, save it and leave it open. 

    3. Run the second script I posted, the folder will not be deleted (which is normal), but the error is not written to the logfile in "C:\Windows\Temp\Alfa_Adsuite_2013_2.log" for the reason I can not understand.

    4. Run the first script. It does not include a function, but the exact same code that was inside the function of the second script. It acts as it should: the folder is not deleted, but it tries 10 times to delete the folder and writes the errors into the logfile. 

    Thank you for helping me tracking this down. 

    Tuesday, December 24, 2013 10:28 PM
  • Hi,

    It's really not the purpose of this forum to try to reproduce your problem and then fix your code for you.

    If you want free help, please write a short example script that contains only the minimum amount of code needed to fix the problem, and post that. Along with the short sample post, tell what error(s) you get (please copy and paste the error and tell specifically what line causes the error; remember, we can't see your screen).

    This is sometimes called the Short, Self Contained, Correct (Compilable), Example (sscce) (compilable, in a scripting context, means the script interpreter doesn't immediately fail to start running the script).

    Bill

    Tuesday, December 24, 2013 10:58 PM
    Moderator
  • Along with Bill's suggestion also not that an earlier error can make all future code execute like nonsense.

    Yu have to start by learning how to use error management.  That is on you to do.  The link I posted has an excellent explanation of what is happening and how to use the error management bits.


    ¯\_(ツ)_/¯

    Tuesday, December 24, 2013 11:18 PM
  • Hint.

    Just before this line:

    objFS.DeleteFolder (strFolderName)

    Add "On Error Resume Next"

    Get rid of all Err.Clear statements


    ¯\_(ツ)_/¯

    Tuesday, December 24, 2013 11:22 PM
  • Adding On Error Resume Next inside the function did it! I thought putting it on top of the script would be enough, I had no idea that functions work in a different way. 

    Thank you so much for your hint. 

    Thursday, December 26, 2013 9:07 AM