Checking out Aivosto VB Project Analyzer's compatibility checklist

clock December 29, 2007 05:47

If you don't know about VB Project Analyzer, rush to Aivosto's web site and learn about this great tool. It performs code analysis, dead code detection and removal, coding and naming rule enforcement. It can find common programming errors (including memory leaks caused by undisposed API handles), can optimize your code much faster than the fastest and smartest developer, and can generate a thorough documentation of all classes, forms, and members (including cross-reference data to detect who call whom). Best of all, it works with VB6, VB.NET, and VBA.

If you are preparing your VB6 apps for migration to .NET this tool is also very helpful, because it can automatically spot most VB6 language elements that the Update Wizard doesn't convert correctly to VB.NET. The online help includes the list of all compatibility checks that VB Project Analyzer performs, and being the author of the most powerful VB migration tool on the market - not really on the market yet Laughing - I was especially interested in how well or bad our VB Migration Partner behaves with each of those compatibility issues. My findings were so exciting that I decided to share them in this blog. Please refer to the original list for an explanation of each compatibility issue. Of course, VBMP means VB Migration Partner.

VB.NET compatibility problems
Add-in model changed in VB.NET: VBMP is unable to migrate add-ins because the IDE object model is too different, but it emits a warning.
ADO required for data binding in VB.NET: VBMP supports DAO, RDO and ADO data-binding, including binding with DataEnvironment objects, ADO data source classes, and simple-bound data consumer classes. [SUPPORTED]
Array must start at 0 in VB.NET: VBMP supports several strategies for migrating arrays with non-zero LBound. Not only does it fix the array declaration, it can even modify the index used to reference individual array elements. [SUPPORTED]
As Any not allowed in VB.NET: VBMP correctly converts As Any arguments by producing one or more overloads of the Declare statement. [SUPPORTED]
As New doesn't auto-instantiate if object released in VB.NET: VBMP optionally supports the lazy-instancing feature of As New variables. [SUPPORTED]
As New unsupported for arrays in VB.NET: VBMP can correctly translate As New arrays by preserving the VB6 semantics.[SUPPORTED]
ByRef property params unsupported by VB.NET: VBMP converts ByRef arguments inside properties into ByVal arguments because VB.NET requires it; howver it emits a warning if the argument appears to be modified inside the property procedure – or is passed to another method that can modify it. [SUPPORTED]
ByVal/ByRef not allowed in API calls in VB.NET: VBMP safely resolves ByVal and ByRef in calls to API methods. [SUPPORTED]
Circle and Oval unsupported by VB.NET: VBMP correctly converts Line and Shape controls, and even translates graphic methods such as Line, Circle, PSet, PaintPicture, etc. [SUPPORTED]
Class Instancing changes in VB.NET. VBMP deals with SingleUse objects as if they were MultiUse, because .NET has no notion of “single use” objects. However, Global objects are converted correctly. [SUPPORTED]
COM method not callable from VB.NET: VBMP can’t handle COM module methods.
COM+/MTS not upgradable to VB.NET:VBMP correctly converts all frequently used MTS/COM+ features into the corresponding .NET features. [PARTIALLY SUPPORTED]
Conditional block will not upgrade to VB.NET: VBMP doesn’t migrate code inside an #IF block whose condition is false.
Control unsupported by VB.NET: VBMP converts 60+ controls, including all those included in the VB6 toolbox with the only exception of OLE Container. It supports other commonly used controls such as WebBrowser and ScriptControl, and all the windowless controls in the MSWLESS library. [SUPPORTED]
DDE unsupported by VB.NET: VBMP doesn’t support DDE, because VB.NET doesn’t support it either.
Diagonal line unsupported by VB.NET: VBMP supports the Line control, with any inclination and style.[SUPPORTED]
DoEvents() returns no value in VB.NET: VBMP provides a DoEvents6 replacement statement that returns the number of open forms.[SUPPORTED]
Drag-and-drop requires rewrite for VB.NET: VBMP fully support OLE drag-and-drop, in both the manual and automatic flavors. Current VBMP version doesn’t support “classic” (non-OLE) drag-and-drop, but we plan to add this feature in a future release. [PARTIALLY SUPPORTED]
Event behavior changes in VB.NET: VBMP fully supports all these (and other) events, no work is required after update. [SUPPORTED]
Event log model differs in VB.NET: VBMP supports all the Event Log-related properties and methods. [SUPPORTED]
Initialized arrays in UDTs unsupported by VB.NET: VBMP correctly initializes UDTs containing arrays, fixed-length strings, and auto-instancing (As New) object variables. It even generates special code to correctly convert assignments between UDTs that contain these members. (The Upgrade Wizard doesn’t even emit a warning in that case.) [SUPPORTED]
MDIForm event unsupported in VB.NET: VBMP correctly handles mouse-related events inside MDI forms. [SUPPORTED]
Member cannot be default in VB.NET: VBMP offers the same degree of support that the Upgrade Wizard does. In addition, VBMP can convert a default method with parameters into a VB.NET ReadOnly Property and then mark it as the default member of that class.[SUPPORTED]
Module not upgradable to VB.NET. VBMP doesn’t migrate DHTML and WebClass components. However, it converts UserDocument and PropertyPages into VB.NET UserControls, thus you have something to work with after the migration even though you'll need additional manual coding to have it work as expected. [PARTIALLY SUPPORTED]
No control arrays in VB.NET: VBMP correctly converts all sorts of VB6 control arrays, including arrays of menus and 3rd-party ActiveX controls.[SUPPORTED]
Old VB project not upgradable to VB.NET: VBMP has the same limitation and requires that you migrate VB3, VB4, and VB5 projects to VB6 before attempting the migration to VB.NET.
OLE Automation unavailable in VB.NET: VBMP converts OLE Automation features into do-nothing members that are marked as obsolete. Calling these members has no effect or throws an exception, but at least you can start testing other portions of the application without having to fix one or more compilation errors. [PARTIALLY SUPPORTED]
ParamArray is ByVal in VB.NET: VBMP emits a warning when an element of a ParamArray parameter is assigned inside the method; you can then use a FixParamArray pragma to automatically generate code that fixes this problem. [SUPPORTED in upcoming version 0.92]
Parameterless default properties unsupported in VB.NET: VBMP behaves  like the Upgrade Wizard when the object variable is typed; when the variable uses late binding, VBMP can generate code that determines the default member at runtime. [SUPPORTED]
Property mixes scopes: VBMP correctly converts property procedures with mixed scope. [SUPPORTED]
Property passed ByRef: As an option, VBMP can automatically convert ByRef parameters into ByVal parameters if the parameter isn’t assigned inside the method, therefore this issue is less serious than it would be if a conversion is attempted with the Upgrade Wizard. [SUPPORTED]
Resource file requires work in VB.NET: VBMP converts both the resource file and all LoadRes* methods; it even converts them to My.Resources members if possible. [SUPPORTED]
ScaleMode must be vbTwips for VB.NET: VBMP supports all ScaleMode settings, including 0-vbUser. [SUPPORTED]
Setting .Interval does not enable/disable timer in VB.NET: Applications converted by VBMP don’t suffer from this issue. [SUPPORTED]
String byte functions unavailable in VB.NET: VBMP partially support byte-oriented string functions, such as LenB or InStrB; it also support implicit conversion between strings and byte arrays, and conversions between ANSI and Unicode strings. [PARTIALLY SUPPORTED]
Sub Main not executed in VB.NET: VBMP fixes this issue: a VB.NET class library project that is the result of converting a VB6 ActiveX DLL project correctly executes the Sub Main method before any class in the library is instantiated. [SUPPORTED]
Sub Main: VB.NET program exits at End Sub: VBMP can handle this issue by adding a proper  InsertStatement pragma. [SUPPORTED]
TTF/OTF fonts required by VB.NET: VBMP supports the FormFont pragma, which enables the developer to set which font should be used for all forms in the converted project; also, the ReplaceFont pragma allows to replace any given font with another font, thus you never need to manually fix form fonts before the migration. [SUPPORTED]
Type unsupported by VB.NET: VBMP comes with a VB6FixedString type that perfectly mimics the VB6 fixed-length string type; also, VBMP can convert arrays of fixed-length strings; additionally, fixed-length strings in UDTs can be converted into standard strings and still retain the fixed-length behavior. [SUPPORTED]
Unavailable in VB.NET: VBMP supports CVErr, GoSub, Return, vbDataObject, vbUnicode, vbFromUnicode, IsEmpty, and a limited form of LSet that works with UDTs. (It doesn’t support VarPtr, ObjPtr, and StrPtr undocumented functions, though.) [PARTIALLY SUPPORTED]
Underscore _names not hidden in VB.NET: VBMP doesn’t deal names with a leading underscore in a special way, however it recognizes VB6’s hidden members and convert them correctly to VB.NET.  [SUPPORTED]
VB5 project may not upgrade to VB.NET: VBMP converts only VB6 projects, therefore VB5 projects must be converted to VB6 first. However, it supports the Common Windows controls released with VB5. [PARTIALLY SUPPORTED]
WebClasses upgrade to ASP.NET: VBMP doesn’t convert WebClass projects. We strongly believe that such projects should be upgraded to ASP.NET in all cases.

Compatibility related optimization issues
Function without type specification:
VBMP emits a warning if a function or property has no As clause; however, you can use the SetType pragma to define the type returned by the VB.NET function without altering the VB6 code. [SUPPORTED]
Variable without type specification: VBMP emits a warning if a variable or parameter has no As clause; however, you can use the SetType pragma to define the type of the VB.NET variable without altering the VB6 code. [SUPPORTED]

Compatibility related style issues
ByVal/ByRef missing: By default, VBMP doesn’t take any action if an explicit ByRef/ByVal keyword is missing and converts these parameters as ByRef parameters; however, it emits a warning if a ByRef parameter can be safely converted as a ByVal parameter and you can use the UseByVal pragma to automatically convert such parameters into ByVal parameters. [SUPPORTED]
Option Explicit missing: VBMP doesn’t take any specific action if Option Explicit is missing; however, you can use a pragma to automatically create VB.NET variables for all VB6 variables that weren’t explicitly declared.  [SUPPORTED]
Optional parameter missing default value: VBMP automatically add the property default value for Optional parameters if necessary. [SUPPORTED]
Variable/Parameter with generic type: VBMP provides statistics about Variant variables and allows you to use the SetType pragma to change the type of a variable or parameter during the conversion to VB.NET, without affecting the existing VB6 code.[SUPPORTED]

To recap, VB Migration Partner can fully or partially handle 43 of the 49 compatibility issues that are left unresolved by the Upgrade Wizard.  The remaining 6 unresolved issues are related to features that just don't make sense under .NET - such as OLE-related properties, the IDE extensibility object model, and WebClasses components - or that are truly not replicable under VB.NET (e.g. calling COM modules or using DDE).

Frankly, VB Migration Partner fixes many more compatibility issues than those listed in this page. As a matter of fact, VBMP solves many problems that even VB Project Analyzer fails to detect. (Read here for a more exhaustive list of migration problems.)

 



Speed up string concatenations after the migration from VB6

clock December 22, 2007 03:41

When you migrate code from VB6 - regardless of whether you are using VB Migration Partner, the Upgrade Wizard, or another automatic conversion tool - chances are that string-intensive code will actually run slower under VB.NET, if it uses a lot of string concatenation operations. For example, this code takes 2.8 seconds when it runs in VB6 and 27 seconds after its conversion to VB.NET on my 3GHz system:

Dim s As String = ""
For i As Integer = 1 To 100000
    s = s + "*"
Next

The solution is of course trivial: just replace the string variable with a StringBuilder object. Alas, this fix requires that you completely revise the VB.NET code, because you need to replace all + and & operators with the Append method, not to mention cases where the StringBuilder is used as an argument to string functions such as Trim or Len.

Is there a way to speed up the previous code with a minimal impact on the code itself? The answer is yes and the solution is actually very simple: you just need to create a VB.NET class that is based on the System.Text.StringBuilder object, that redifines the + and & operators, and that supports the implicit conversion to and from the System.String type. Authoring such a StringBuilder6 class is a matter of minutes:

' a wrapper for the StringBuilder object, with support for + and & operators

Public Class StringBuilder6

    Private buffer As New System.Text.StringBuilder

    ' return the inner string

    Public Overrides Function ToString() As String
       
Return buffer.ToString()
    End Function

    Public Shared Operator +(ByVal op1 As StringBuilder6, ByVal op2 As String) As StringBuilder6
        op1.buffer.Append(op2)
       
Return op1
    End Operator

    Public Shared Operator &(ByVal op1 As StringBuilder6, ByVal op2 As String) As StringBuilder6
        op1.buffer.Append(op2)
        Return op1
    End Operator

    ' convert to string

    Public Shared Widening Operator CType(ByVal op As StringBuilder6) As String
       
Return op.ToString()
    End Operator

    ' convert from string

    Public Shared Widening Operator CType(ByVal str As String) As StringBuilder6
        Dim op As New StringBuilder6()
        op.buffer.Append(str)
        Return op
    End Operator

End Class

Once the StringBuilder6 class is in place, you just need to replace the type of the String variable:

Dim s As StringBuilder6 = ""

After this edit, the loop runs in 0.008 seconds, that is about 2000 times faster!!! Not bad, for such a simple fix :-)

The StringBuilder6 class is so useful that we decided to include it in the forthcoming version 0.92 of VB Migration Partner. Even better, you can use a SetType pragma right in the original VB6 code to tell our tool that a given string variable must be rendered with this new type:

'## s.SetType StringBuilder6
Dim s As String = ""
For i As Integer = 1 To 100000
    s = s + "*"
Next

 



New features in version 0.91.03

clock December 9, 2007 12:55

A few days ago we released version 0.91.03 to our beta testers. In addition to fixing a few minor bugs, the new version introduces a couple of all-important pragmas and a new way to specify project-level pragmas and share them among different projects.

The PreProcess pragma is similar to PostProcess, except that it processes the VB6 code before VB Migration Partner parses it. This pragma allows you to solve a large categories of migration issues. For example, you can change the name or the type of a VB6 control before it is converted to VB.NET. The ImportTypeLib pragma allows you to specify the exact command to be passed to the TlbImp.exe tool when VB Migration Partner imports a type library, for example to produce a strong-named DLL assembly.

Just as important, version 0.91.03 introduces the VBMigrationPartner.pragmas file, which is a text file that you can create in the VB6 project's directory and that can hold one or more project-level pragmas. You can copy the same file to different directories, which is a simple way to have multiple VB6 project to share the same project-level pragmas. As a matter of fact, ImportTyleLib pragmas and project-level PreProcess pragmas can only be stored inside a VBMigrationPartner.pragmas file.