FRANCESCO BALENA ON VB MIGRATION

 

Bugs that drove us crazy

clock June 25, 2008 00:02

We all know that writing software requires a vast assortment of skills and, above all, a lot of patience. You usually need the latter to feel comfortable when you realize that you've wasted hours and days over someone else's bug.  Here's the story.

Like many commercial applications, VB Migration Partner has a splash screen. No big deal. VB Migration Partner is written in VB2005, therefore we could use VB.NET application framework. As a matter of fact, defining a splash screen in VB.NET is as easy as selecting an item in a combobox in the Application tab of the My Project designer.



During the beta test period a few users reported that at times VB Migration Partner threw an exception at launch, immediately after closing the splash screen. We never managed to reproduce the problem on our computers. Fortunately the exception occured quite rarely. Until a user running Windows 2000 reported that he was seeing the exception at nearly every launch. After installing VB Migration Partner on Windows 2000 in our lab, we could indeed verify that we had a problem.

 

It took a while to find out that we weren't  the only ones suffering from this issue. As a matter of fact, Microsoft recognizes that it is a VB.NET bug. Fortunately, they also offer a workaround. According to whis workaround you must create an invisible form from inside the Form_Load event of your splash screen, something like this:

   Private Sub Form_Load(ByVal sender As Object, ByVal e As EventArgs) _
          Handles MyBase.Load
     Dim frm As New Form
      frm.Opacity = 0
      frm.ShowInTaskbar = False
      frm.FormBorderStyle = FormBorderStyle.None
      frm.Show()
      Return frm
   End Function

Unbelievably, this code makes the problem vanish away! You can find more details in this Microsoft KB article.

We realized that *all* applications written in VB.NET could suffer from this issue, thus we added a method to our support library, named SplashScreenBugFix6, which creates the invisible form for you. You just need to add an InsertStatement pragma in the original VB6 splash screen form, so that a call to this method is automatically generated anytime you convert the VB6 project:

    ' in the VB6 project
    Private Sub Form_Load()
      '## InsertStatement SplashScreenBugFix()
      ' more code in the Load event
   End Sub

Currently rated 5.0 by 3 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Neat tricks for smooth migration of calls to Windows API methods

clock June 12, 2008 21:13
VB Migration Partner does a superb in dealing with Windows API calls. Here's a summary of the features that it supports and that are out of reach for the Upgrade Wizard included in Visual Studio 2005/2008:

  • converts As Any parameters, by creating all the necessary overloads
  • deals correctly with API methods that take a callback address (e.g. EnumWindows, EnumFonts)
  • provides recommendation about the .NET object/method that can effectively replace the API method; we cover 300+ different API calls. (Enterprise Edition only)
  • in a few cases, it automatically replace API calls with calls to the corresponding .NET object/method
  • ensures that string immutability doesn't prevent the VB.NET code from working correctly (see this article)
  • generates the correct MarshalAs attributes for elements in Type (Structure) blocks
  • correctly translates fixed-length strings inside Type blocks, so that they work correctly when passed to the Windows API method
  • automatically initializes static arrays inside Type blocks, so that you don't get unexpected crashes when invoking an API method that expects to find a buffer there
  • creates a wrapper method that ensures that orphaned delegates don't cause an unexpected runtime exception, an advanced programming technique discussed in this KB article (Enterprise Edition only)
  • includes the VB6WindowsSubclasser class that helps you correctly migrate subclassing-based techniques (as explained here)

In spite of all these innovations, there are cases when you still need to manually edit either the original VB6 code or the converted VB.NET. This happens, for example, if the original code uses the VarPtr, StrPtr, or ObjPtr functions to pass memory pointers to an external API method. These three functions aren't supported under VB.NET and there is no simple way to simulate them.

The good news is that in the vast majority of cases you don't need to deal with memory pointers under .NET, because the .NET Framework offer a valid "pure" alternative to the API method in question. In this article I'll illustrate how you can take advantage of VB Migration Partner features to reduce manual edits to the very minimum and take advantage of the convert-test-fix methodology.

For simplicity's sake, let's focus on one of the simplest API methods, the GetSystemDirectory Windows API. Here's a piece of VB6 code that displays the system directory path:

    ' Main.Bas module
    Public Declare Function GetSystemDirectory Lib "kernel32.dll" Alias "GetSystemDirectoryA" _
        (ByVal lpBuffer As String, ByVal nSize As Long) As Long

    Sub Main()
        Dim buffer As String, length As Long, windir As String
        buffer = Space(256)
        length = GetSystemDirectory(buffer, Len(buffer))
        winDir = Left(buffer, length)
        MsgBox winDir
    End Sub

The first step is in refactoring this code so that you make all the Declares private and move them to another BAS module, that exposes them by means of standard VB6 methods. (If you usually write tidy and maintainable VB6 code, odds are that you have already taken this step.)

    ' This is the APIHelpers.Bas file
    Private Declare Function GetSystemDirectory Lib "kernel32.dll" Alias "GetSystemDirectoryA" _
        (ByVal lpBuffer As String, ByVal nSize As Long) As Long

    ' returns the Windows directory
    Public Function SystemDirectory() As String
        Dim buffer As String, length As Long
        buffer = Space(256)
        length = GetSystemDirectory(buffer, Len(buffer))
        SystemDirectory = Left(buffer, length)
    End Function

The code that actually displays or otherwise uses the Windows directory path is now simpler. Notice that we explicitly include the module name (APIHelpers) in the method call. This tip reduces the odds that another method with same name exists elsewhere in the project, but the technique explained later works even if you don't include such a name:

    ' the Main.Bas module
    Sub Main()
        Dim windir As String
        winDir = APIHelpers.SystemDirectory
        MsgBox winDir
    End Sub

At this point you have a VB6 project that works exactly like the original one, but it is better organized and structured, with all Declares statements gathered in one single module. Let's see how to migrate this code to VB.NET and get rid of all dependencies from non-NET code.

First and foremost, we prepare a VB.NET module that exposes the same methods as the original APIHelpers.bas but doesn't use any Declare statement. Here's how we can render the SystemDirectory function using native .NET calls:

    ' This is the APIHelpers.vb file (VB.NET)
    Module APIHelpers
        Public Function SystemDirectory() As String
            Return Environment.SystemDirectory
        End Function
    End Module

Next, we use an ExcludeCurrentFile pragma to exclude the APIHelpers.bas VB6 module from migration process and we use an AddSourceFile pragma to add the APIHelpers.vb VB.NET file to the converted Visual Studio project. The neat result is that the code in Main now calls the .NET version of the method, which doesn't use any unmanaged calls:

    ' This is the APIHelpers.Bas file
    '## ExcludeCurrentFile
    '## AddSourceFile "c:\vbnet\modules\apihelpers.vb"

    Private Declare Function GetSystemDirectory Lib "kernel32.dll" Alias "GetSystemDirectoryA" _
        (ByVal lpBuffer As String, ByVal nSize As Long) As Long
    ' ... remainder of module as before...

This solution works great, but we can improve it. In fact, a (minor) problem is that the resulting VB.NET code still uses wrapper methods and doesn't look like the "native" .NET code that an experienced VB.NET developer would write. Fear not, because all you need is a project-level PostProcess pragma:

    ' This is the APIHelpers.Bas file
    '## ExcludeCurrentFile
    '## project:PostProcess "(APIHelpers\.)?SystemDirectory", "Environment.SystemDirectory"

Notice that I dropped the AddSourceFile pragma because you don't need the wrapper method any longer (at least in this simplified example). Using similar techniques you can provide a .NET equivalent for most methods that require API calls under VB6, including methods that take arguments.

One of the long-terms goals we have in Code Architects is to apply these concepts on a larger scale to create VB6 helper modules and their corresponding VB.NET versions, to help all VB6 developers to easily migrate their API-intensive applications. Just stay tuned, as usual!

Currently rated 4.7 by 3 people

  • Currently 4.666667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


What are your options to survive in the next decade?

clock May 29, 2008 01:51

Well, I really mean "what are the options to have your VB6 application survive in the next decade?". After nearly 30 years in the field - I started my Computer Science studies in 1979, go figure! - many of which spent consulting for companies in Europe and United States, I have seen many tecnology revolutions, including the advent of IBM PC and of Windows 1.0. Each one thaught me a little piece of experience.

Let's quickly see the alternatives. 

1) DO NOTHING (AKA "IF IT AIN'T BROKE, DON'T FIX IT")
If the application is at the end of its life cycle, for example because it doesn't fullfil a widespread need any longer, you might decide to have it die of a natural death. There is no reason to invest in a dying creature, therefore you might stay with VB6 and just fix some major bugs when your users complain aloud. Don't add any new feature or extend it in any way, because it would be too expensive too.

2) EXTEND THE VB6 APPLICATION USING COM INTEROP AND THE FORMS INTEROP TOOLKIT
In this case you leave the main application in VB6 but extend it by invoking .NET components using COM Interop, or display .NET forms using Microsoft's Forms Interop Toolkit. Version 2.0 of this add-on is a major improvement, as it even supports hosting of .NET controls inside VB6 forms. Best of all, the toolkit is fully supported by Microsoft and comes with full source code. [Thanks to Rob Windsor for remainding me of this option, see comments]

While the toolkit is free, adopting it has some obvious and hidden defects and costs, though. First and foremost, this approach isn't really a solution to the problem, is more of a technique to soften the migration path and lessen its impact on your organization. If you need to migrate because your app doesn't work well under Windows Vista, or because it's slow, or because you don't want to rely on a language that Microsoft doesn't support any longer, using COM Interop and the Forms Interop Toolkit is just a way to postpone the time when you truly need to find a reliable solution. Second, the communication between the VB6 and VB.NET portions of the application is often awkward and leads you to inefficiencies (due to COM Interop) and complex roundtrips that don't make your code easily maintanable.

The bottom line: you should use the Forms Interop Toolkit only in the bigger picture of a phased migration (as Rob suggests in this comment). That is, while a group of developers is working on the porting from VB6, another group is already extending the application using VB.NET. Before taking this approach, you should compare it with the effort required by migrating it to VB.NET in one step using a *good* migration tool (ours, that is :-) )

3) CONVERT TO VB.NET, USING THE UPGRADE WIZARD AVAILABLE IN VISUAL STUDIO
Why not giving it a try? it's free! While your hard disk spins for hours trying to convert your real-world business app, you can have enough time to google for less-then-gentle comments about this tool from the VB community. Let's skip to next option.

4) CONVERT TO VB.NET, USING VB MIGRATION PARTNER
Using our conversion tool to migrate to VB.NET makes sense in many cases. First, when the original application works well and is thoroughly tested, but needs to be extended with new features and implementing these extensions with VB6 would be too difficult or expensive. Second, when the application is so large that rewriting it from scratch would require a very intensive test phase. Third, if time-to-market is essential to beat your competition and make your existing users happy. In these cases you can leverage VB Migration Partner higher speed and precision (as noted by our beta testers)

5) CONVERT TO VB.NET, USING ANOTHER 3RD-PARTY TOOL
There are other VB6-to-VB.NET migration tools on the market. Choosing a conversion tool is a critical decision, so you might want to ask our competitors for a trial version and compare it with our VB Migration Partner. Please do it! Please compare its feature, precision, and speed with VB Migration Partner and then let us know. If you don't have time to waste, however, ask yourself the following questions before considering another conversion tool:

a) how many VB Migration Partner's feature does this tool support? for example, does it fully support all 60+ VB6 controls, drag-and-drop, graphic methods, arrays with any LBound, Gosubs, As New semantics, IDisposable objects, As Any parameters and callbacks in Declares, etc. 
b) are there any significant features that this tool support and that VB Migration Partner doesn't?
c) why they don't make their entire documentation available online before you buy?
d) why don't they dare to publish real-world VB6 apps and the VB.NET code that their tool generates?

As far as we know, Code Architects is the only vendor who has uploaded dozens of VB6 code samples and the corresponding, converted VB.NET project, to let potential customers see and test the VB.NET applications we produce. We don't upload artificially-conceived tiny VB6 projects that highlights the tool's strengths and hide its weakness. Instead, our code sample section gathers open-source VB6 projects taken from the Internet, and we guarantee that we edited neither the original VB6 code (which is in fact downloadable from its original URL) nor the converted VB.NET.

Now ask yourself: why no other vendor took this obvious step to show the world how powerful their tool is?

6) MANUALLY RE-WRITE IT TO VB.NET
In some cases, manually re-writing the application to VB.NET is a viable solution. Well, let me be absolutely honest on this point: in (very) few cases, this is the solution we recommend to our customers. If the application is a huge amount of contorted spaghetti code, has a orrible architecture and a ugly user interface....well, in this case you don't want to spend more time and money on automatic porting, because you would also port these issues to VB.NET. 

When weighing a complete re-writing from scratch against automatic porting, you should take several factors into account, including:

a) rewriting often takes from 50% to 90% of the time and money that was necessary to write the original application. (Sorry, no official statistics on this, just our field experience...)
b) you need a team of developer who are experienced in both VB6 and VB.NET, and they also need to be familiar with issues related to the specific application, therefore you can't simply hire them from outside your company
c) how do you cope with continuous edits/improvements to the original VB6 code during the months required by the rewrite? In other words, can you count on something similar to our convert-test-fix methodology?
d) can really you afford the extra time required by a complete re-write? what will your competitor do in the meantime?

7) MANUALLY RE-WRITE TO C#, JAVA, OR ANOTHER LANGUAGE
I heard that a few ISVs are taking this path. In my opinion this is an irrational decision, often motivated by the anti-VB (or even anti-Microsoft) feeling that is so fashionable today. Let me explain why you shouldn't even think of jumping from VB6 to any .NET language other than VB.NET.

Rewriting a complex VB6 application into a different language has all the drawbacks of rewriting it to VB.NET (see point 6), plus the many problems that you have when switching from VB.NET to C# or Java. How do you implement On Error Resume Next in C#? How do you render a DTPicker control in Java without carefuly mapping each and every property, method, and event? But the decisive argument is: do you have enough developers who are equally familiar with VB6 and C# or Java and the application being migrated?

Briefly stated: taking this route is a technological suicide similar to point 1), except it takes longer, costs more, and is more agonizing. You can only hope that your competitors are in love enough with C# or Java to invest their energies in this option. If you hear that they are doing it, relax and be happy: you don't have anything to worry about for a long time :-)

8) CONVERT IT TO C# USING AN AUTOMATIC CONVERSION TOOL
Come on! To get an idea of how tough this "solution" (so to speak) is, take all the issues listed at point 5) and multiply them by all the problems mentioned at point 7). Then double the result to have a more reasonable estimate of the actual cost and effort.

More seriously, just think of this: there are a few commercial tools on the market that can automatically migrate VB.NET to C#, for example Instant C# or C-Sharpener for VB. I have actually used a couple of these tools, they do a great job. However, they still require a few manual edits after the conversion, to adjust minor differences between VB.NET and C#. The main reason is that the resulting C# code doesn't look like native C# and requires some fixes to be more readable and easily maintainable.

Before your consider this approach, ask yourself two questions:

a) if you believe that automatic conversion between two .NET languages (VB.NET and C#) is difficult, how can you expect that a tool be able to automatically convert from VB6 to C# in one single step?
b) on the other hand, if you think that conversion from VB.NET to C# can be fully automated, why not going from VB6 to VB.NET using our VB Migration Partner (or another tool, if you prefer) first and then using Instant-C, C-Sharpener for VB, or another similar tool for doing the final move to C#?

If you really want a C# app as the final deliverable of your conversion efforts, keep in mind that jumping from VB6 directly to C# doesn't give you more than switching from VB6 to VB.NET first and then from VB.NET to C#. Well, it actually does give you something more.... many more headaches, for precision's sake :-)

Currently rated 3.7 by 9 people

  • Currently 3.666667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Comparing the & operator, the String.Concat method and the String.Format method

clock February 20, 2008 06:16

You might be aware that VB.NET supports at least 4 techniques to append strings:

    1) the & operator (or the + operator)

    2) the String.Concat static method

    3) the String.Format static method

    4) the StringBuilder object and its Append and Insert methods

By peeking at the code that the VB.NET compiler generates for the & (or +) operator, you can quickly realize that this operator is rendered as a call to the String.Concat method, thus using either technique #1 or #2 has no impact on performance and is just a matter of coding style. I usually prefer the & operator over String.Concat for readibility's sake, and I guess most VBers do the same, but it should be clear that the two are perfectly equivalent if you are concerned only about speed. (NOTE: when working with values other than strings, you might find String.Concat more readable, because it doesn't force you to explicitly invoke the ToString() method of each operand.)

When working with long strings that undergo many concatenations, the StringBuilder object is the fastest technique, period. Too much digital ink has been spilled on this topic, and I won't repeat those well-known concepts here. (BTW, if you're looking for a smart way to replace the & operator with the StringBuilder object without messing up your existing code, read here.)

However, when you have to perform a few concatenations on many short strings, the overhead needed to setup the StringBuilder object often shadows the benefits of its Append method. In these scenarios, the choice is among techniques #1 (or #2, which is equivalent) and technique #3. Today I decided to take some time to compare their performance. I run 100,000 concatenations over two or more 10-char strings. Here are the results on my on a 2.20 GHz Core Duo, 2G RAM Dell notebook running Vista (timings are in milliseconds and are averaged over several runs):

# of operands   Concat    Format
2                  12         60
3                  22         95
4                  28        150
5                 125        160
6                 185        192
7                 210        215
8                 235        239
9                 270        272

To summarise, the Concat method runs 4-5 times faster than Format with 4 operands of fewer, but there is no significant difference with 6 or more operands. It is interesting to notice the steep increase (from 28 to 125 milliseconds) for the Concat method when passing fro 4 to 5 arguments. The reason: there is no String.Concat overload that takes 4 arguments, therefore the VB.NET (and C#) compiler has to build a temporary array with 5 elements and pass it to the String.Concat overload that takes a ParamArray. The same thing happens with the String.Format method when you pass from 3 to 4 arguments.

In general, I prefer to use the String.Format method when appending 3 or more strings, except inside time-critical code. For example, I use it for building error messages and other UI elements; in this case the loss of speed rarely (or never) affects the overall execution speed. Another advantage of String.Format is that you can easily create a table of messages and store them on a database, an XML file, or just a plain text file (possibly stored as a resource). For example, all VB Migration Partner error and warning messages are stored in a format like this:

        Using the '{0}' Windows API method as an argument to the '{1}' function might result in an string filled with spaces. Please split the next line in two statements.

This approach makes the code more readable and maintenable. Plus, localizing the code for a language other than English will be a breeze, if I ever need to.

---------------------------------------

Speaking ofconcatenations, the fact that Concat, Format and other static methods of the System.String class have an overload that takes a ParamArray (and therefore a standard array) makes it possible to implement a few nice tricks. For example, you can quickly concatenate all the elements in an array using this code:

    Dim arr() As String = {"one", "two", "three", "four"}
    Dim res As String = String.Concat(arr)    ' => onetwothreefour

If you need to use a delimiter between each element or concatenate onlya subset of the array, use the String.Join method:

    res = String.Join(" ", arr)         ' => one two three four
    res = String.Join(" ", arr, 1, 2)   ' => two three

When working with arrays of 10 elements or fewer, or you are interested in just the first 10 elements, you can use the Format method in creative ways, as in this code:

    ' display elements in random order
    res = String.Format("{3} {1} {0} {2}", arr)    ' => four two one three 

 

Currently rated 4.0 by 2 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Three new code samples are available

clock January 9, 2008 03:45

Yesterday we added three new samples to our code samples section:

Virtual Night Sky shows how the sky appears at the specified place and time, and provides info on stars under the mouse cursor.
Barcode Generator displays Bar Codes 39 and 128 and lets you copy them to clipboard and save to file.
Grid-Net Waves 3D animates a 3D graph.

What they have in common is that they display graphic output using a combination of VB6 and API methods. VB Migration Partner fully supports both techniques and converts these samples with little or no effort (in all cases you need pragmas to release the device context handle).

I especially like the Virtual Night Sky sample: it took me just two convert-test-fix cycles to have a fully working version, and the entire process took me less than five minutes! I didn't even had to study the source code to understand how it works: the entire process was quite "mechanical", in the sense that I run the VB6 code through the tool a first time to see which compilation errors I got. I added a few pragmas and got a zero-compilation and zero-runtime error VB.NET code, which worked at the first attempt. If only all VB6 applications could be converted so simply!

BTW, this sample showed an interesting (and undocumented, of course) difference between the PictureBox control in VB6 and VB.NET. The original VB6 application allows you to use the Shift+left and Shift+right key combinations to move your point of view on the horizon. Oddly, these key combinations aren't trapped by the VB.NET PictureBox control: instead, they are translated to the Tab and Shift-Tab sequences. In other words, they move the input focus to a different control on the form. We decided NOT to replicate this minor difference in VB Migration Partner's support library: instead, we changed the converted app to use the Alt+left and Alt+right key combinations to achieve the same result. Spotting and fixing this issue took me five more minutes, but I can now explore my night sky with a fully .NET application. 

Note to Beta Testers: if you migrate these three samples with current version 0.92 you'll need to manually fix a few VB.NET statements. These fixes won't be necessary with the upcoming version 0.93.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Checking out Aivosto VB Project Analyzer's compatibility checklist

clock December 28, 2007 23: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.)

 

Currently rated 3.0 by 2 people

  • Currently 3/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Setting the default value for enumerated properties in VB.NET

clock November 17, 2007 03:56

When defining a property of a Windows Forms control, you typically need to define its default value. Such a default value fulfills two goals: first, it reduces the amount of code that Visual Studio generates in the *.Designer.vb file, which in turn speeds up form instantiation; second, it allows developers to quickly reset the property to its default value by right-clicking on the property inside Visual Studio’s Property Grid and then selecting the Reset menu command. All property values that aren’t equal to the default value appear in boldface, therefore the Reset command restores a non-boldface value.



You can declare the default value of a property by means of the System.ComponentModel.DefaultValue attribute, as in:

    Private m_ScaleLeft As Single = 0
    <DefaultValue(0.0!)> _
    Public Property ScaleLeft() As Single
          Get
                Return m_ScaleLeft
          End Get
          Set(ByVal Value As Single)
                m_ScaleLeft = Value
          End Set
    End Property

Unfortunately, VB.NET has a bug and doesn’t allow you to select a default value for enumerated properties. For example, consider the ScaleMode enumerated property, which is exposed by the VB6Form in VB Migration Partner’s support library:

    Private m_ScaleMode As ScaleModeConstants = ScaleModeConstants.vbTwips

    <DefaultValue(ScaleModeConstants.vbTwips)> _
    Public Property ScaleMode() As ScaleModeConstants
          Get
                Return m_ScaleMode
          End Get
          Set(ByVal value As ScaleModeConstants)
                m_ScaleMode = value          
          End Set
    End Property

The problem is, this code doesn’t work in VB 2005. More precisely, you can reset the ScaleMode property to its default value using the Reset command, but the property value is always displayed in boldface and is always serialized in the *.Designer.vb file. It turns out that all enumerated properties manifest this bug. (I consider it as a VB.NET bug because C# doesn’t exhibit this odd behavior.)

I tried all the techniques I was aware of to fix the problem, including adding a ShouldSerialize* method, as in:

    Public Function ShouldSerializeScaleMode() As Boolean
          Return Me.ScaleMode <> ScaleModeConstants.vbTwips
    End Function

I had always given up, when I discovered an overload of the DefaultValue attribute, which takes a System.Type and a string argument. To my great surprise, it worked!

    <DefaultValue(GetType(ScaleModeConstants), "1")> _
    Public Property ScaleMode() As ScaleModeConstants
          …
    End Property

Thanks to this fix, all the controls in VB Migration Partner’s library now serialize only the properties that have been set to a nondefault value. I haven’t checked yet whether Microsoft fixed this bug in VB2008, but for sure the VB2005 workaround is so counterintuitive that I felt the urge to document it here.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


VB Migration Partner - Subscribe to our feed RSS  blog RSS
 
AddThis Feed Button
 
 

Home blog
 
AddThis Social Bookmark Button


 

Sign in

Search

Calendar

<<  July 2008  >>
SuMoTuWeThFrSa
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

Archive

Categories

 

Microsoft Regional Director
Microsoft is a registered trademark of Microsoft Corporation in the United States and other countries and is used under license from Microsoft
 

My Blogs


My programming tools



VB Migration Partner


VBMaximizer for VB6


Form Maximizer for .NET

 

My books


Programming Microsoft Visual Basic 6


Programming Microsoft Visual Basic 2005: The Language


Practical Guidelines and Best Practices for Microsoft Visual Basic .NET and Visual C# Developers