[INTERVIEW] Yours truly on .NET Rocks!

clock May 2, 2014 16:30

A few weeks ago I had an interesting and entertaining conversation with Carl Franklin and Richard Campbell of .NET ROCKS, about VB6 migration, the effect that Windows XP retirement is having on companies that can't afford keeping their mission-critical VB6 apps on an unsupported operating system, and a lot more. Yesterday the interview went online, at this URL

Happy listening!



Lecture on VB6 migration at MS Wester Europe ALM Partner Summit, Madrid

clock October 5, 2011 15:07

Next Tuesday (Oct 11) I am giving a speech at the Microsoft Western Europe ALM Partner Summit, Madrid. The topic is of course VB6-to-.NET migration and the title of the session is VB6-to--NET Migration:Myths, Truths, and Real-World Experiences.

If you are there, please pass by and say hi.

 



Vote for a VB6 migration session at TechEd Europe 2010

clock October 14, 2010 16:45

I submitted a BoF session at TechEd Europe 2010, entitled "VB6-to-.NET Migration: Myths, Truths, and Real-World Experiences".

There is a poll on these Birds-of-Feathers sessions, and only the ones that get most votes will be accepted.

Regardless of whether you attend TechEd, you can help by voting for my session. In addition to having me speak at TechEd, a lot of votes on this session will hopefully convince Microsoft that VB6-to-.NET migration is a hot topic and that they should invest more in that direction.



Basta! 2010 slides available

clock September 27, 2010 15:45

We just uploaded the two slide packs of my session at Basta! 2010 in Frankfurt, Germany.

VB6 to .NET Migration: Myth, Truth, and Real-World Experiences

VB6 to .NET Migration: Tips, Traps, and Techniques

Happy reading!



Facebook Fan Page: Francesco Balena on VB6 Migration

clock January 27, 2010 22:32

Alive and kicking.

We just opened Francesco Balena's fan page on Facebook  (yes, FB on FB!), where I'll publish news about VB6 and migration experiences, including useful technical information, tips, whitepapers, and other resources.

The easiest way to always stay up-to-date on VB6, how to convert your legacy code to .NET, and how to recycle your skills in a more modern programming environment.



Pay attention to orphaned ADODB objects

clock September 2, 2009 01:26

Don't take me wrong: COM Interop is a great piece of technology, and Microsoft developers made wonders with it. If you consider how different the COM and .NET worlds are, it's a miracle that they can communicate with each other in such a smooth way.

Actually, COM Interop is such a magic that it's easy to forget that all the COM objects that we manipulate from .NET aren't the "real" COM objects. Instead, they are .NET wrappers that redirect all calls to the actual COM object by means of COM Interop. This fact has many implications. Consider for example this VB6 code:

Function GetRecordCount(ByVal cn As ADODB.Connection, ByVal sql As String) As Integer
   Dim rs As New ADODB.Recordset
   rs.Open sql, cn
   GetRecordCount = rs.RecordCount
End Function

As you see, the Recordset object isn't closed explicitly, but it isn't a problem in VB6 because all COM objects are automatically closed when they are set to Nothing or go out of scope. However, if you translate this code to VB.NET you are in trouble, because nothing happens when the method exits. In other words, you'll have an open recordset hanging somewhere in memory and cause unexplainable errors later in the application. For example, you'll get an error when you'll later try to open another recordset on the same connection.

We know that some customers had to work around this issue by enabling the MARS option with SQL Server, which enables multiple active recordsets on any given connection. This might be a viable solution if you are working with SQL Server 2005 or 2008, but VB Migration Partner offers a better way to handle this case: use the AutoDispose pragmas.

In fact, when this pragma is used, all disposable objects are correctly disposed of when they go out of scope. In this case, VB Migration Partner emits the following code:

Function GetRecordCount(ByVal cn As ADODB.Connection, ByVal sql As String) As Integer
   Dim rs As New ADODB.Recordset
   Try
      rs.Open(sql, cn)
      GetRecordCount = rs.RecordCount
   Finally
      SetNothing6(rs)
   End Try
End Function

where the SetNothing6 helper method takes care of orderly invoking the Close or Dispose method, if necessary.



Dynamic Data Exchange (DDE) can be migrated, at last!

clock July 25, 2009 01:41

If you've never heard of Dynamic Data Exchange - a.k.a. DDE - consider yourself a lucky developer. In short, DDE is a simple communication protocol that allows two or more Windows processes to communicate with each other. DDE never really caught on, however a number of Microsoft applications and languages supported it, including of course Visual Basic (starting with version 3, if I remember correctly).

The main pros of DDE are its simplicity and flexibility: in most cases, you just need to set a few properties and you soon have a number of controls in a DDE client application reflect the state of a control in another application. More precisely, you can have a TextBox, Label, or PictureBox in an application (known as the DDE client) to be "linked" to a similar control in another application (known as the DDE server). You can even have multiple clients linked to the same server application, so that when the control in the server app changes, all the client apps automatically receive the new value. The DDE protocol allows other variations on this theme, for example the code in the client app can poke a value into a server's control, so that a client can indirectly notify all other clients that a new value is available.

DDE has several shortcomings, too, which explain why it never became very popular. For one, it appears to be quite fragile and you have no warranty that all the processes involved in the communication received the notification. For these reasons, it was soon replaced by COM in all developers' minds and hearths.

Regardless of what your opinion about DDE is, it's a fact that many VB6 applications - especially those that were born as VB3 projects - do rely on DDE. In the last few months we received several enqueries from potential customers who needed to migrate a VB6 app that was based on DDE to some extent. In these cases we could only suggest to replace DDE code with COM code before the migration, or replace portions of the VB.NET code with calls to native .NET technologies, such as remoting or WCF.

This is what all articles about migration recommend and is also what all our competitors do, but clearly wasn't what our customers liked to hear, especially because implementing a robust communication mechanism based on .NET requires time and skilled developers, plus the time required to fix the migrated VB.NET code to use the new mechanism.

About one month ago we rolled up our sleeves and we are now proud to announce the VB Migration Partner now supports all DDE properties, methods, and events!

Instead of implementing the "real" DDE protocol - an approach that would inherit all the DDE limitations and weaknesses - we decided to adopt a different approach based on Windows messages. This gives "our" DDE more robustness and better efficiency, while keeping it source-code-compatible with all existing DDE code written in VB6. In other words, we do support all the DDE properties and methods even if we internally use a different implementation.

Because of the approach we chosen, there are only a few minor differences with the "real" DDE protocol. The main limitation is that a migrated VB.NET app can use DDE only to communicate with another migrated VB.NET app. (If you used DDE to communicate with Microsoft Excel you can't use our prioprietary implementation, for example.) Also, our DDE protocol is inherently synchronous, therefore we don't support the LinkTimeout property and the LinkError event. Except for these details, the implementation is complete and sound. If your VB6 app uses DDE, this single feature can save you weeks during the migration process.

If you are interested in seeing a migrated VB.NET app that uses DDE, you can download a good sample here. The sample includes two projects - the client and the server - so you should launch the DDE server first and then one or more instances of the DDE client application. You will see that changing a field in the server app affects the linked control in all clients. You can compare the VB.NET behavior with the original VB6 application, whose source code are available here.

It almost goes without saying the VB Migration Partner is the FIRST and ONLY migration software that supports DDE, an achievement that confirms that our product is simply the state-of-the-art in its market segment.



Can your VB6 conversion tool handle null propagation?

clock May 21, 2009 09:13

If you have massively used Variants in your VB6 apps, the migration to .NET might be a nightmare. The best that the Upgrade Wizard and other tools can do is translating each “As Variant” into “As Object”, on the assumption that the Object type can do everything that a Variant does.

You shouldn’t be surprised to learn that this is one of the false migration myths, or is a gross oversimplification of the truth, to say the least. In fact, the .NET Object type lacks what arguably is the most useful feature of Variants: support for Null values and Null propagation in expressions.

Under VB6 a Variant variable can hold the special Null value and – even more important – all the string and math expression that involve a Null operand also deliver a Null Variant value. Virtually all database-intensive applications deal with Null values and have used null propagation to an extent. Now, let’s consider this VB6 code:

' rs is an ADODB.Recordset
Dim realPrice As Variant
realPrice = rs("Price")
realPrice = realPrice * (100 – rs("Discount")) / 100
If Not IsNull(realPrice) Then DisplayPrice(realPrice)

Under VB6, if either the Price or the Discount field is Null, the realPrice variable is assigned Null and the DisplayPrice method isn’t invoked. Now, consider the “canonical” VB.NET version of the above code:

Dim realPrice As Object
realPrice = rs.Fields("Price").Value
realPrice = realPrice * (100 – rs.Fields("Discount").Value) / 100
If Not IsNull(realPrice) Then DisplayPrice(realPrice)

Under .NET a Null database field returns a DBNull object – more precisely, the DBNull.Value element. The problem is, no math or string operation is defined for the DBNull type, something I consider one of the most serious mistakes Microsoft made in this area. As a result, the third statement throws an exception if either field is Null. So long, functional equivalence! Welcome, migration head-aches!

Null propagation is a serious problem not to be underestimated. One of our customers has found that, on the average, one out of 40 statements uses Variant expression and relies on null propagation. To put things in the right perspective, in a middle-sized real-world application you can expect to manually fix several thousand statements that use null propagation. What’s worse, there is no simple way to work around Null values in VB.NET, short of splitting all statements in portion and testing each and every subexpression for the DBNull.Value value.

If you use VB Migration Partner, you can solve the above problem in the most elegant and painless way. Just use the following project-level pragmas:

 '## project:NullSupport
 '## project:ChangeType Variant, VB6Variant

The NullSupport pragma tells VB Migration Partner to map some VB library functions – such as Left, Mid, Right, and a few others – to special methods that are defined in VB Migration Partner’s support library and that, not surprisingly, correctly return a Null value if their argument is Null (as they do under VB6).

The ChangeType pragma converts all Variant members – variable, fields, properties, methods, etc. – as the special VB6Variant type (also defined in VB Migration Partner’s support library) which redefines all the math, comparison, string, and logical operators to support null values.

Yes, this is all you need to add null propagation support to your VB.NET code! This feature alone can save you literally weeks in a real-world migration project. And don’t forget that VB Migration Partner is the only VB6 conversion software that supports Null values and Null propagation easily and automatically.

When you hear other vendors claiming that “our tool uses advanced artificial-intelligence-based techniques to ensure functional equivalence with the original VB6 code”, just ask them how it deals with Null values. Smile



All the white papers in one place

clock February 22, 2009 03:57

We just put online a new page that gathers all the whitepapers we have published so far, and the ones that will be in the future.

If you need guidance when selecting a conversion tool or a migration strategy, this is the place to go.



Subtle threading issues and how to fix them (automatically) with VB Migration Partner

clock February 10, 2009 09:09

One customers brought an issue to our attention. He was using a migrated VB.NET component in a heavy multi-threaded environment (the component is called by ASP.NET pages) and found that occasionally the program crashed with an unexplainable error message. A quick look at the stack trace confirmed the initial suspect: the error was caused by two threads that initiates a call to the same method at the same time. We have fixed the problem in our library in a few minutes (the fix will appear in version 1.10.03, due in a few days), but we realized that the problem isn't confined to our library. To explain why, a short digression is in order.

VB6 components use Single-Threaded Apartment (STA) model: each thread lives in an “apartment” of its own. In plain English, this means that each thread works with a different set of global variables. For example, assume that the ActiveX DLL project contains a BAS module with the following variable declaration:

    ' ...(in the UserInfo.bas file)
    Public UserName As String


Thanks to STA threading model, each client – running in a different thread – can write this variable and read it back, without worrying about another client (in another thread) overwriting the variable with a different value. As you see, STA makes multi-threading programming virtually as easy as single-thread (i.e. traditional) programming. Of course,when writing multi-threaded apps you have to take care of many other potential concurrency issues – for example, two threads working on the same temporary file or registry key – but at least you don’t need to worry about global variables.

By contrast, components written in VB.NET – and all .NET languages, for that matter – use free-threading, which means that all threads can access all variables at the same time. Therefore, the VB.NET component exposes the same UserName field to all threads, which means that any thread can overwrite the value stored there by another thread.

To simplify programming in free-threaded contests, the .NET Framework supports the ThreadStatic attribute. You can apply this attribute only to static class fields – either fields defined in modules or fields defined in classes and marked with the Shared kewword:

    <ThreadStatic()> _
    Public UserName As String


All fields marked with the ThreadStatic attribute are stored in the Thread Local Storage (TLS) area. The separation among threads is automatic, because each thread owns a different TLS.

In theory, when migrating a VB6 DLL meant to be used by free-threaded clients, you should scrutinize each and every variable in BAS modules and decide whether to tag them with the ThreadStatic attribute. To make this task as easy as possible, as well as to avoid any manual edit of the resulting VB.NET code, starting with version 1.10.03 VB Migration Partner supports the ThreadSafe pragma, which can be applied at the project-, file-, method- and variable-level scope. In most cases, therefore, all you need to do is using a single pragma that affects all the variables in the current project:

    '## project:ThreadSafe True
    Public UserName As String