VB6 On Error Statements
On-Error-GoTo label
Description
Error handling statements in VB6 rely on labels that can produce complex code. Because of this, there are cases where the VBUC cannot perform an appropriate transformation, so an EWI is generated. In those cases, manual changes must be made to fix the issue.
Alternative solution
Consider the following VB6 code:
For that case, the On Local Error GoTo LabelError cannot be translated. The migrated version of the method would look like this:
Most cases can be translated into a try-catch-finally statement. The following code shows an equivalent way to transform the original error pattern:
Notice the migrated code shows a pattern: the LabelError contains statements to take action when an error occurs (prone to be in a catch block) and the LabelExit contains statements that execute regardless of the error occurring or not (prone to be in a finally block). In those cases, a regular expression can be helpful to make a massive transformation of the migrated code. If you are not familiar with regular expressions, please read the following information.
The following is a possible regular expression that identifies the pattern:
(?^\s)(?UpgradeHelpers."On Error Goto Label (LabelError)")(?(.|\s|\n)?)(?LabelError:)(?(.|\s|\n)?)(?LabelExit:)(?(.|\s|\n)*?)(?(return))
The following is a possible replacement pattern for the regular expression indicated above:
{p1}try\n{\n{p3}\n}\ncatch(Exception exc)\n{\n{p5}\n\n}\nfinally\n{{p7}\n}\n${p8}
Using expressions like the ones shown above can transform the code automatically for those cases where the patterns appear en masse.
On Error Resume Next
Description
In .NET, the equivalent structured model for On Error Resume Next would be a Try-Catch for every single statement in the block where the "resume next" is active. Applying that kind of conversion would result in very low-quality code. Instead, it is recommended that the error-prone statements be manually identified and handled individually with a different model.
Example 1
VB6 code:
C# code:
In this example, the programmer was expecting an error in CodeBlock1. If that happens, Err.Number is going to be a number different than 0, so the code flow will be entering the following if statement. The solution is to place CodeBlock1 in a try-catch and CodeBlock2 in the catch block.
Example 2
VB6 code:
C# code:
This is a small variation of the first example. What changes here is the programmer wanted to handle only a specific kind of error. Since Information.Err doesn't have the same behavior in .NET as in VB6, the solution is to find the corresponding exception to match the error code and catch it in the .NET migrated code.
Example 3
VB6 code:
C# code:
This is a combination of error handling with On Error Goto Label and On Error Resume Next. If an error happens in CodeBlock1 or CodeBlock4 it should be handled with CodeBlock5, but if something happens in CodeBlock2 the error handling is executed by CodeBlock3. The solution here is to create a combination of try-catch that allows this execution flow.
Example 4
VB6 code:
C# code:
This is probably the worst scenario you can find in error handling. Here, the VB6 programmer wanted every statement in CodeBlock1 to be executed, without caring about what happened in previous statements.
As we explain at the beginning of this section, the equivalent in .NET of CodeBlock1 will be a try-catch for every statement, but he is undesirable. For this case, the recommendation is to find every statement that could raise an error and put it within a try with an empty catch (if possible, you can create a better code that prevents the exceptions). There are many statements where you don't expect errors, such as variable assignments (i = 0), but you should consider a try-catch for statements that use COM objects or connections to databases.
Last updated