We find out how to work backwards, and migrate code you no longer have
What do you do when you need to modify your application but cannot find the code?
Peter Altman contacted me about a Visual Basic 3.0 puzzle which he wanted to run on his Windows Mobile PDA. All he had was the compiled code, written for him by a friend who had died. VB 3.0 is 16-bit software that is fifteen years old.
The best chance, short of a full rewrite, was to port the application to Visual Basic .Net, which runs on Windows Mobile under the Compact Framework runtime, but for that the source was required. This kind of scenario can be a critical problem when it happens with a business application. It should never happen, but small businesses can be disorganised, and developers can be protective of their code.
16-bit code is an interesting case. The move to 64-bit Windows is in its early stages, but will gather pace over the next few years, and 16-bit applications do not run on 64-bit Windows. Virtual PC or the like is one answer, since it lets you run a different operating system within Windows, but even that does not help you if you need to modify the code or port it to another platform.
Decompilation
If you have an executable for which the source is not available, then you can
resort to a technique called decompilation. The aim is to start with the binary
file and work backwards to the original code. Decompilation has many challenges.
It may be illegal; many licence agreements forbid it. Some code is deliberately
obfuscated to make decompilation more difficult.
Another factor is what type of compiled executable you are dealing with. Native code binaries such as those produced by C, C++ or Delphi are more difficult to decompile than the intermediate code in Java, .Net or early versions of Visual Basic. A lot of Java and .Net code is trivial to decompile with a suitable utility, unless the programmers have taken deliberate steps or used a tool to obscure it.
Here’s how we decompiled Peter Altman’s code.Visual Basic 3.0 uses an intermediate language. Many years ago a programmer c alled Hans-Peter Diettrich, also known as ‘Dodi’, created a decompiler, which is still probably the best tool for this. You need to have VB 3.0 installed. Microsoft can no longer supply it, but fortunately I still have a copy.
Windows XP or earlier is recommended, as Vista’s User Account Control introduces complications. Diettrich told me that he uses Windows 98 in a Virtual PC. I found it necessary to check the vb.ini file in the Windows directory, which should have a vbpath entry, in the Visual Basic section, pointing to where VB 3.0 is installed. Once everything is set up, run vbdis3.exe, which is the decompiler.
Choose File Open and select the compiled VB 3.0 executable, which in this case is called counter.exe. Next, you are prompted for a location for the decompiled project. Click OK, and all being well the decompiler invokes VB 3.0 to complete the process. It’s not perfect and may trip up over some VBX controls. You will also find that variables and function names have auto-generated values.
It is a good idea to try renaming these to something meaningful, if you can figure it out. Nevertheless, it is a huge head start (see attached picture). Diettrich kindly provided a working demo version of his decompiler for PCW readers. A professional version is also available, with extra features for handling tricky problems like third-party VBX controls.
Porting to .Net
This is only the beginning of the porting process. How do you port a VB 3.0
application to VB .Net? One idea is to try Microsoft’s automatic project
conversion. The first snag is that VB is fussy about what it will import. Visual
Basic .Net will not look at a VB 3.0 project, but fortunately VB 6.0 is more
tolerant.
Peter Altman’s simple application imported smoothly into VB 6.0, needing only the adjustment of a couple of API calls to 32-bit. It even ran correctly. The next step was to go from VB 6.0 to VB .Net. This is inherently difficult, because it is really a different platform, but Microsoft has put huge effort into it because it is a common scenario. I used Visual Studio 2008, and chose Convert from the Open menu.
The import seemed to go well, but the application did not run correctly. The problem is that VB 6.0 and earlier has all sorts of quirks which cause problems when you try and port the code. In this case, the original programmer used VB’s Scaletop and Scaleleft properties to set up a custom coordinate system, and the converter had no idea how to cope with this.
Another issue was that a VB 6.0 control array got converted to a compatibility object called a PictureBoxArray. Objects such as this live in the Microsoft.VisualBasic. Compatibility.VB6 namespace and, although it helps to get code running quickly, it won’t work in the Compact Framework. I converted the code to use a standard ImageList control. At this point the mangled variable names were a nuisance.
Here is a sample of decompiled code:
Function fn00C2(ByVal p007C As4 String, ByVal p007E As String,4 p0080 As String)
As String
Dim l0082 As Integer
Dim l0084 As Integer
Dim l0086 As String
Dim l0088 As String
l0084 = Len(p007E)
l0086 = “”: l0088 = p0080
l0082 = InStr(l0088, p007E)
Fixing the problem with Scaletop and Scaleleft meant going through the code, figuring out what the variables meant and renaming them accordingly. Would it be quicker to rewrite from scratch? In many cases it would. Even so, the decompiled code could be useful as a guide to how the original application worked.
Converting an entire project from VB 6.0 is often not the best approach, because it results in a sub-optimal application that needs a lot of manual tweaking. Another idea is to create a new .Net project, but paste code from the old VB 6.0 project. Visual Studio has a handy tool called Upgrade Visual Basic 6.0 code, which gets you started with porting a block of code.
From desktop to mobile
The final stage was to port the desktop VB.Net project to the Compact Framework.
Create a new Smart Device project, making sure that you target the right kind of
device. Next, copy any non-visual code to the new project. Forms are more
challenging, but you can sometimes save time by copying controls from the old
project to the new, using the clipboard.
Inevitably, the user interface will need to be redesigned for a small screen. The Smartphone format does not have a mouse or a stylus, and there is no such thing as a button control. Anything involving database access will need rethinking, though fortunately Peter Altman’s simple puzzle had none. In this case the main challenge was doing without a mouse.
Developing for the Compact Framework with Visual Studio 2008 is a joy. The latest emulators work smoothly. One thing to note is that closing an application on Windows Mobile does not remove it from memory. If you are debugging, this means that Visual Studio continues in debug mode. The solution is to open the Memory applet on the emulator and terminate the application instance.
Deploying to Windows Mobile
First, your users will need to install the Compact Framework runtime. The latest
version is 3.5, though version 2.0 is smaller and may be all that you need. This
can be downloaded as a Windows Installer setup. Run the setup with the device
connected, and it will be installed automatically.
To create a CAB file for your application, add a Smart Device CAB Project to your Compact Framework solution, and add the primary output from the application to the CAB project. Right-click the primary output in the Application Folder and choose Create Shortcut to add a shortcut for the device. Now build the CAB. Users can install by copying both the CAB and the generated .inf file to their device and running it.
Resources
A
demo
version of the VB3.0 decompiler can be downloaded.
Deploying .Net Compact Framework applications with .cab and .msi files.