On VB6 and Windows 7 XPM, Part Deux

7. May 2009 14:46 by Jaguilar in General  //  Tags: , ,   //   Comments (0)

Yesterday I blogged about Windows 7’s XP Compatibility Mode, and have some additional pieces of information that I consider interesting if you are considering using it in the future:

  • First of all, not all CPUs would be able to use XP compatibility mode. Take a look at this page over at Tom’s Hardware, and the post over at Ed Bott’s blog. I think the image halfway down the page on the second link speaks for itself – you probably won’t be able to know if the deployment target for your application supports XP Mode or not, which can complicate the installation experience.
  • The second bit of information I want to comment about is the fact that even though applications running under XP mode appear seamlessly alongside Windows 7 applications, they are still running on a virtual machine. From what I’ve seen the boundary is not noticeable to the end user - the application’s shortcuts appear in Windows 7’s start menu, the tray icons appear in Windows 7’s tray, etc. But apps in XP Mode run completely separate from their Win7 counterparts, and the VM itself needs to be patched with its own version of Windows Update, requires specific policies applied to it, etc. It goes without saying that all this adds overhead to managing these type of deployments, and may cause incompatibilities if an app requires interaction with other programs installed on the Windows 7 side (VB6 apps using Office’s COM API is a common example – will you require separate versions of Office, one in the XPVM, and another one on W7 for daily use?).
  • Finally, XP Mode uses Terminal Services and something similar to the RemoteApp mechanism to display applications on the Windows 7 desktop (not sure how other VMMs such as Parallels’ Coherence manage it) . Even though the integration is almost seamless, there are a few quirks here and there that make for an inconsistent experience (drag and drop files, etc), and may affect the performance and L&F of the application.

This post argues that the best solution would be to use Microsoft’s App-V technology to virtualize “XP and older” applications. I agree that would be an ideal solution. But maybe there is a reason why it works like it does – so that you won’t get too comfortable. XPM, IMHO, should be considered as an intermediate step towards moving your legacy apps to the latest technologies.

(As a side note, remember I did a lot of work on Virtualization, and think it is a good way to get the most out of your IT infrastructure resources. XPM, to me, is an excellent idea to start dropping all the legacy parts of Windows without compromising application compatibility, and a smart move at that. )

On Visual Basic 6.0 and Windows 7 XP Compatibility Mode

6. May 2009 14:19 by Jaguilar in General  //  Tags: , ,   //   Comments (0)

As you are probably well aware, along with the release of Windows 7 RC came some big news that affect Visual Basic 6.0 applications: Professional and Ultimate Editions of Windows 7 will feature a Windows XP Mode for backwards compatibility with legacy applications. This means that even if you are using components that have issues with Windows 7, you will be able to run your VB6.0 application on the new operating system, albeit within a Windows XP virtual machine.

It is important to mention that the VB team over at Microsoft was already making sure the IDE and VB6 runtime would work on Windows 7, as I commented before (second comment on that post) based on the Support Statement for Visual Basic 6.0 on Windows Vista, Windows Server 2008 and Windows 7:

The Visual Basic team is committed to “It Just Works” compatibility for Visual Basic 6.0 applications on Windows Vista, Windows Server 2008 and Windows 7.
The Visual Basic team’s goal is that Visual Basic 6.0 applications that run on Windows XP will also run on Windows Vista, Windows Server 2008 and Windows 7. The Visual Basic team is also committed to the Visual Basic 6.0 development environment running on Windows Vista, Windows Server 2008 and Windows 7.

The objective of XP Mode is clearly to move forward the Windows architecture to the latest technologies, free of all the legacy bits required to maintain compatibility of old applications (read the History posts at the The Old New Thing blog for examples), while at the same time it allows developers to smoothly upgrade their applications without the threat of the application not working in the new OS. It is basically a compromise of old vs. new. And it is very easy to draw parallels between XP Mode and the approach taken by Apple, first with Classic and then with Rosetta, to smooth the transition to new platforms. But as was the case in those scenarios, Classic was eventually phased out, and Rosetta will eventually be as well.

I personally think that this technology may end up being around for a while, and may even end up included in the next versions of Windows if there is enough customer demand for it. This has to be the same technology used in their Microsoft Enterprise Desktop Virtualization (MED-V) solution, targeted towards enterprise customers:

“Microsoft Enterprise Desktop Virtualization (MED-V) provides deployment and management of virtual Windows desktops to enable key enterprise scenarios. MED-V 1.0 helps enterprises upgrade to the latest version of Windows even when some applications are not yet compatible.”

Even in the scenario that XP Mode is supported for a long time, you still have to consider it as something that can be used for a smooth transition while you upgrade your applications to the .NET Framework, and not as an excuse for not upgrading. It can help you plan a gradual migration, were you first start migrating certain modules while leaving others in VB6, with tools like the Interop Forms Toolkit. And keep in mind that even though the application will run, the IDE is simply not supported anymore and neither are most controls that cause compatibility issues. And at the same time you will be missing the benefits of using the latest technologies and the increased productivity of the .NET Framework.

Visual Basic migratioon now faster than ever!

6. May 2009 09:44 by Fzoufaly in General  //  Tags: , , , ,   //   Comments (0)

Today ArtinSoft launched the Visual Basic Upgrade Companion 3.0 both for our Enterprise and Developer Editions.  This latest release of the best (I am biased!) Visual Basic migration tool in the world is focused on reducing the total effort of a migration project.  Together with the conversion tool release we also revamped its companion technical site http://www.vbtonet.com/ .  This site, which will be continuously updated in the following weeks, is the perfect side help to any person that needs to complete a migration project.  It contains everything from a getting started guide to how-to articles with advanced migration topics.

At ArtinSoft we are truly proud of this release and we continue to be fully committed to support our customers in their transition from VB 6 to Visual Basic .NET or C#. 

Specifically, here are the latest additions to the VBUC 3.0.  Click here to get a trial of this exciting product.

VBUC 3.0 New Features

 Source Code Conversion Features
  • Windows API and 'Declare' Support
    VBUC 3.0 introduces support for external DLL function declarations and invocations. A vast research was performed to identify the correct way of declaring and passing parameters and return types for primitives, classes, enums, structs, fixed lenght strings, arrays and combinations of these types.
  • Increased Support for Windows Common Controls Conversion
    VBUC 3.0 introduces a substantial amount of improvements for the conversion of Windows Common Controls to native .NET controls.  An extensive effort was performed to identify and resolve issues related to these components which are present in most VB6 applications. The main improvements are related (but not limited) to the following controls:  ImageList, ListView, StatusBar, Toolbar, TreeView.
  • Public Class Instantiation Models Support
    Public classes in ActiveX EXE/DLL projects may have different instantiation models (multiuse, singleuse, etc.) To achieve the same behavior in .NET a whole conversion solution was implemented and incorporated into VBUC 3.0.
  • Default Property Resolution Through Helper
    The VBUC contains a new helper class designed to resolve several late binding issues that are not solved by the typing mechanism. This solution significantly reduces compile errors and EWIs while providing higher functional equivalence.
    This solution resolves the EWIs related to late-binding and default property issues which represent around 50% of known issues from older versions.
  • Data Access Conversion Improvements
    The data access conversion to ADO.NET with System.Data.Common has been a very popular feature from the previous VBUC versions.  VBUC 3.0 introduces several improvements to this feature. It includes enhancements to the helper classes functionality as well as additional members coverage (clone, sort, getrows and many others)
  • IsMissing Support
    VBUC 3.0 introduces support for the IsMissing function. Since VS.NET doesn't include the concept of missing parameters, VBUC now generates a code pattern that produces the same behavior by taking advantage of nullable types and overloading.
  • NotUpgradedHelper for Not-Upgraded Statements and Members Handling
    A very common problem with older versions of VBUC was the handling of NotUpgraded members and statements.  They were usually generating compile or runtime errors that made the post-VBUC manual work more difficult.
    VBUC 3.0 introduces a helper class to report and handle the usages of not supported elements while avoiding compile and runtime errors.
  • Multiple improvements to existing features
    Around 450 individual improvements were implemented for VBUC 3.0.  Most of them are related to providing increased automation and enhance the resulting code quality, others are related to other areas such as robustness and graphical interface.
 Performance Improvements
  • Speed Boosting
    For VBUC 3.0 several time performance improvements were implemented to achieve a substantial improvement, reducing to 50% the required time to perform an upgrade process.  Additional time improvements could be experienced when converting large projects which used large amounts of memory.
  • Reduced Memory Requirements
    Memory usage was also significantly improved.  Based on tests over medium projects we estimate around a 30% improvement.  It is estimated that more significant improvements will be experienced with bigger projects.
 Assessment
  • Assessment Tool Integration
    The VBUC Assessment Tool functionality has been incorporated into the VBUC. Users can now execute the assessment process from the VBUC main window. One important advantage of this approach is that users can solve migration warnings before executing the assessment process, allowing the obtention of better quality information.
  • Additional Assessment Reports
    Two additional reports have been included into the integrated assessment process:
    • An advanced dependency analysis that shows internal-dependency trees per project.
    • A shared and potential-duplicate files report.  It includes the following sub reports:
      • A shared files report indicating which projects include each shared file.
      • A potential-duplicate files report indicating which projects include each presumed duplicate file.
      • A projects list sorted topologically with LOC counts for each project where shared and potential-duplicate files are counted only in the first project they occur.
 Other Features
  • Graphical Interface Status Information
    The VBUC 3.0 graphical user interface shows detailed information for each project.  It shows sizes, progress and status by project and by source file detail.
    It helps the user to understand the volume of work required for each project and its current upgrade progress as well as to identify any eventual pieces of code that may have not been fully converted.
  • EWIs and Upgrade Report Improvements
    Several modification have been implemented to the upgrade messages generated by VBUC into the generated code.
    • UpgradeReport Synchronization: for previous versions of VBUC the UpgradeReport didn't show properly all the EWIs generated into the upgraded code.  For VBUC 3.0 this report includes all the EWIs generated in the converted code plus the global EWIs that are not included into the target source code.
      In addition, the accumulated counts per section where also improved to show the correct amount of occurrences.
    • Links to Online Documentation: Hiperlinks are added for each EWI to its corresponding online documentation in the new www.vbtonet.com site.
    • Restructuring: The EWI message structure was modified to show the numeric code first.  Also some messages where improved and some EWIs were removed or merged.
  • Increased Robustness and Logging
    Several actions were taken to handle and recover from unexpected situations.  In the event that any exceptional situation may arise, an window is displayed explaining the issue and providing the user with options to generate debugging information that can be sent to ArtinSoft support for diagnosis and recommendations.
 Products, Versions and License Types Formalization
  • Developer and Enterprise Editions
    The second version of VBUC Developer Edition is released with VBUC 3.0.  The development process has been formalized to syncronize the maintenance and releases of both versions.  The Developer Edition includes an improved activation and licensing model as well as an easier on-line sale mechanism.
  • Trial Licenses
    Both Developer and Enterprise editions support trial licenses.  Developer trials are now available for download in the Artinsoft web site.
  • ASP Upgrade Engine Integration
    The ASP Upgrade Engine has been integrated into the VBUC 3.0.  It is now installed together with VBUC.  The license file can still restrict the use of ASP upgrade abilities though.
  kick it on DotNetKicks.com

Visual Basic Upgrade Companion 3.0 Official Release

6. May 2009 07:34 by Jaguilar in General  //  Tags: ,   //   Comments (0)

Today we formally released version 3.0 of the Visual Basic Upgrade Companion, including both the Enterprise and Developer Edition of the migration tool. This is a significant new release, which has improved the efficiency of the conversion tool by reducing the amount of work required to the the applications to functional equivalence by over 30% (and more in some cases). All migration improvements are based on the feedback from the experiences of both our clients and our own consulting team, and we are very happy the changes have such an effect. I already talked about specific new features on a previous post.

Also, today we went live with a new companion website to the VBUC at www.vbtonet.com. This repository of information should help you in all aspects of the migration, and includes both best practices for, for example, finding customization opportunities in the code, and both overall strategies and detailed examples on how to solve migration issues. This site is tightly integrated with the VBUC, and migration issues identified in the code by the tool will contain a link to latest information to help you solve the issue, like the following example:

'UPGRADE_TODO: (1067) Member MyMember is not defined in type Variant. More Information: http://www.vbtonet.com/ewis/ewi1067.aspx

This library of information will continue growing over time, so make sure you come back often during your migration project to check out the latest content.

You can read the official press release here.

Extended WebBrowser Control Series: Opening Popup in a NewWindow

In a previous post, i had published an “Extended Version” of the WebBrowser control
that gave you access to events like the NewWindow2.
This event that is not public in the common WebBrowser control allows you to intercept
the NewWindow event but gives you the posibility to setup the the ppDisp property witch sets
a pointer to the WebBrowser where the new window will be open.

So i setup a small example using this “ExtendedBrowser”.

I created a simple page (well really it was my wife, I know about transport-layer, C++, bits etc, but I never remember HTML syntax):

<html>
<body>
<H1> This is sample page to test opening a pop up in a new form </H1>
<input type="button" onclick="window.open('test0.htm')"/>
</body>
</html>

And created a simple form like in the following picture:

image

 

Instead of using a WebBrowser control i just used an ExtendedWebBrowser from my previous post.

And added code like:

        private void extendedWebBrowser1_NewWindow2(object sender, NewWindow2EventArgs e)
        {
            //Intercepting this event will allow us to create a new form in which
            //we will open the new webpage, to do that we must set the ppDisp property
            //of the NewWindow2EventArgs
            FormWithExtendedBrowser form1 = new FormWithExtendedBrowser();
            form1.Show();
            e.PPDisp = form1.extendedWebBrowser1.Application;
        }

When I run the code , it now opens the pop up in my form:

image

But test if for yourself! :) HERE IS THE CODE

VB6 Migrating MouseIcon Property

30. April 2009 13:17 by Mrojas in General  //  Tags:   //   Comments (0)

In VB6 you can have code like:

Private Sub Command1_Click()
    Dim x As StdPicture
    Set x = LoadPicture("C:\setup.ico")
    Me.MouseIcon = LoadPicture("C:\setup.ico")
    Me.MousePointer = ccCustom
End Sub

 

How can you migrate that to .NET??????

Well maybe with a helper like the following can help:

using System; 
using System.Windows.Forms; 
using VB6 = Microsoft.VisualBasic.Compatibility.VB6.Support;

namespace Project2
{
    internal partial class Form1
        : System.Windows.Forms.Form
        {
        
            private void  Command1_Click( Object eventSender,  EventArgs eventArgs)
            {
                System.Drawing.Image x;
                x = System.Drawing.Image.FromFile("C:\\setup.ico");
                this.Cursor = CursorHelper.CreateCursor(x);

        }
            [STAThread]
             static void  Main()
            {
                    Application.Run(new Form1());
            }
        }




  public class CursorHelper 
  {
      private struct IconInfo
      {
        public bool fIcon;
        public int xHotspot;
        public int yHotspot;
        public IntPtr hbmMask;
        public IntPtr hbmColor;
      }
  
    [System.Runtime.InteropServices.DllImport("user32.dll")]
    static extern IntPtr CreateIconIndirect(ref IconInfo icon);

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    [return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
    static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);

    private static Cursor CreateCursor(System.Drawing.Bitmap bmp, int xHotSpot, int yHotSpot)
    {
        IconInfo tmp = new IconInfo();
        GetIconInfo(bmp.GetHicon(), ref tmp);
        tmp.xHotspot = xHotSpot;
        tmp.yHotspot = yHotSpot;
        tmp.fIcon = false;
        return new Cursor(CreateIconIndirect(ref tmp));
    }


    public static Cursor CreateCursor(object picture)
    {
      if (picture is System.Drawing.Bitmap)
          return CreateCursor(picture as System.Drawing.Bitmap, 3, 3);
      else 
      {
          System.Drawing.Image image = null;
          IntPtr iunknown = System.Runtime.InteropServices.Marshal.GetIUnknownForObject(picture);
          if (iunknown == IntPtr.Zero)
          {
              throw new Exception("Unsupported format");
          }
          else 
          {
              Guid guidIPicture = new Guid("7BF80980-BF32-101A-8BBB-00AA00300CAB");
              Guid guidIPictureDisp = new Guid("7BF80981-BF32-101A-8BBB-00AA00300CAB");
              IntPtr testIntPtr = IntPtr.Zero;
              if (System.Runtime.InteropServices.Marshal.QueryInterface(iunknown,ref guidIPicture,out testIntPtr)==0)
              {
                  image = Microsoft.VisualBasic.Compatibility.VB6.Support.IPictureToImage(picture);
              }
              else if (System.Runtime.InteropServices.Marshal.QueryInterface(iunknown,ref guidIPictureDisp,out testIntPtr)==0)
              {
                  image = Microsoft.VisualBasic.Compatibility.VB6.Support.IPictureDispToImage(picture);
              }
              if (image == null)
              {
                  throw new Exception("Unsupported format");
              }
              using (System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(image))
              {
                  return CreateCursor(bitmap, 3, 3);
              }
          };
           
          
      }

    }

  }

}

Get the Week Number in C#

30. April 2009 10:56 by Mrojas in General  //  Tags: , , ,   //   Comments (0)

Here is some examples of how to determine the WeekNumber of a given Date

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {

        object index = DateTime.Now;
        int res = 0;
        //0    First day of year
        res = System.Globalization.CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(
        Convert.ToDateTime(index), System.Globalization.CalendarWeekRule.FirstDay, System.Globalization.DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek);

        //1    (Default) First four day week from Sunday
        res = System.Globalization.CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(
        Convert.ToDateTime(index), System.Globalization.CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Sunday);

        //2    First four day week from StartOfWeek
        res = System.Globalization.CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(
                Convert.ToDateTime(index), System.Globalization.CalendarWeekRule.FirstFourDayWeek, System.Globalization.DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek);

        //3    First full week from Sunday
        res = System.Globalization.CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(
                Convert.ToDateTime(index), System.Globalization.CalendarWeekRule.FirstFullWeek, DayOfWeek.Sunday);
        
        //4    First full week from StartOfWeek
        res = System.Globalization.CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(
                Convert.ToDateTime(index), System.Globalization.CalendarWeekRule.FirstFullWeek, System.Globalization.DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek);


        }
    }
}

Visual Basic Upgrade Companion 3.0 Release Candidate available

A couple of days ago we made available the final release candidate for version 3.0 of both the Visual Basic Upgrade Companion Enterprise Edition and Developer Edition. You can now directly download a trial of the VBUC Developer Edition on the trial download page, or request a trial of the Enterprise Edition on this page.

I need to mention an obligatory disclaimer saying this is the final Release Candidate, so, unless we find something at the last minute, it should be the same version officially released within a week or so. We need your help to verify we won’t find anything by downloading it and trying it out. :)

I already covered some of the features of this version on a previous post. There was significant improvements in several areas from version 2.2, which should help you achieve even greater productivity on your migration projects.

Coming Soon: Visual Basic Upgrade Companion Version 3.0 with Enhancements in Automation, Features and Code Quality

20. April 2009 11:52 by Jaguilar in General  //  Tags: ,   //   Comments (0)

As I blogged before, the release of the VB Upgrade Companion v3.0 is due within the next few weeks. In this version we concentrated on three major areas:

  • Automation: We analyzed the data from several million lines of code to determine the most common causes of manual intervention, and, by making some strategic changes to the way the code is generated, managed to reduce the amount of both EWIs (Error, Warning and Information messages) and compilation errors significantly on large (>1 million Lines of Code), complex applications. Also, depending on the VB6 features used, the VBUC now automates the migration of even more smaller applications and components completely!
  • New Features: The VBUC v3.0 also contains additional features, such as the migration of the IsMissing statement and increased support for additional third party components. We are also integrating the VBUC with brand new online documentation resources that should help you as you perform the migration!
  • Code Quality: The Visual Basic Upgrade Companion always tries to generate high-quality code that looks as if it was originally written in .NET. This increases the maintainability of the migrated application, and allows developers joining the project at a later date to very quickly start working on the codebase. Because of the great differences between Visual Basic 6.0 and VB.NET/C#, however, achieving this goal is not always possible. For this release we continued increasing the quality of the migrated code, including minor refactorings to control structures, and adding things like support for translating additional error handling statements to try/catch statements.

All of these was supported by some significant changes we did under the hood, which should make it easier to add new features in the future (including customer-specific customizations) and reduced the memory footprint significantly, while increasing migration speed. Watch this space for more details as the release date approaches!

VB6 AddressOf operator Migration

31. March 2009 09:14 by Mrojas in General  //  Tags:   //   Comments (0)

I was looking into ways to migrate something like the AddressOf operator in VB6. I read in some forums that I could use a delegate, but I hadn’t seen a code sample, so I started googling until I found this great post.

It provided a great example of how to pass a pointer to a function. I am attaching here the code so you can benefit from this too.

 

Remember to put the Working directory pointing to the output directory of the C DLL. In my case it is

image

The idea in general is like this:

/// <summary>
/// Simple callback function.
/// </summary>
/// <param name="a">Some integer parameter.</param>
public delegate void CBFUNC(int a);

/// <summary>
/// Demo of a simple callback.
/// </summary>
/// <param name="f">Function to call back to</param>
/// <param name="a">Parameter which will be returned through the callback</param>
[DllImport("c_test_lib.dll")]
public static extern void DoCallback(CBFUNC f, int a);

DOWNLOAD CODE

Bittable What????

As vb6 migration experts in our company we deal everyday with a lot of issues around Interop and serialization.

One important thing to note is the concept of “Bittable Types”. I’m not making up terms. Those terms actually exist. Just see this link in MSDN.

In a few words, a bittable type is a type that has the same representation in managed and unmanaged code.

Why in earth is that important at all?

Because if you are calling that great C++ DLL implemented some years ago that just works ok, you won’t be able to pass a NON-Bittable type because that DLL will expect a binary representation different from that in the .NET virtual machine.

This is also an issue in other scenarios like:

  • Serializing content to files
  • Sending messages through messaging mechanisms like named-pipes or sockets.

Well, we have just introduced the problem so now let’s think on a nice solution for this problem.

Well Bittable Types are:

The following types from the System namespace are blittable types:

 

So now let’s look at a couple of non-BITTABLE types

DateTime

To test this differences let’s make a small test in VB6 and write a Date value to a file:

 

Private Sub SaveDateToFile()
    Open "C:\test1.bin" For Binary Access Write As #1
    Dim d1 As Date
    d1 = "1/1/2009"
    Put #1, , d1
    Close #1
End Sub

Now let’s make a quick program in Vb.NET

 

Sub Main()
        Dim f As System.IO.FileStream = System.IO.File.Open("C:\test2.bin", IO.FileMode.Create, IO.FileAccess.Write)
        Dim fw As New System.IO.BinaryWriter(f)
        Dim d As Date
        d = Convert.ToDateTime("1/1/2009")
        Dim val As Long = d.ToBinary()
        fw.Write(val)
        fw.Close()
        Main2()
    End Sub

 

If we compare these files we will have:

image

So the values are obviously different. This is because VB6 Date are stores with the OLE Automation DateFormat

So let’s change the C# code for something like:

 

    Sub Main2()
        Dim f As System.IO.FileStream = System.IO.File.Open("C:\test3.bin", IO.FileMode.Create, IO.FileAccess.Write)
        Dim fw As New System.IO.BinaryWriter(f)
        Dim d As Date
        d = Convert.ToDateTime("1/1/2009")
        fw.Write(d.ToOADate())
        fw.Close()
    End Sub

And now when we compare the files we will have:

image

 

So to make your Date values compatible with VB6 format you must user the DateTime method .ToOADate. Now if you are calling a DLL that expects a Date value in the same format used by VB6 then you will have to do this:

 

        Dim d As Date
        d = Convert.ToDateTime("1/1/2009")
        Dim handle As System.Runtime.InteropServices.GCHandle = System.Runtime.InteropServices.GCHandle.Alloc(d.ToOADate(), Runtime.InteropServices.GCHandleType.Pinned)
        Dim memory_address As IntPtr = handle.AddrOfPinnedObject()
        Try
            APICall(memory_address)
        Finally
            d = DateTime.FromOADate(System.Runtime.InteropServices.Marshal.ReadInt64(memory_address))
            handle.Free()
        End Try  

 

String

Most of the time you wont have to deal with String marshalling because adding marshaling tags to your API call solves most of the problems, but if you arent that luckyly then you might do something like:

IntPtr ptrToStringVar = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(strVar);
try
{
   APICall(ptrToStringVar);
}
finally
{
strVar = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(ptrToStringVar);
System.Runtime.InteropServices.Marshal.FreeHGlobal(ptrToStringVar);
}

NOTE: if you have an API that might return an string with /0 characters you must call the API with System.Runtime.InteropServices.Marshal.PtrToStringAnsi(ptrToStringVar,size), if you do that the Framework will take in consideration the size bytes at the ptrToStringVar memory address.

 

Double and Singles

At least between VB6 and VB.NET the double and single types follows the same format. Well, at least, that is the result of my tests.

Try it yourself, the following shows a simple test for double variables:

VB6

Private Sub SaveDoubleToFile()
    Open "C:\test1.bin" For Binary Access Write As #1
    Dim d1 As Double
    d1 = 1.123
    Put #1, , d1
    Close #1
End Sub

Sub Main()
    SaveDoubleToFile
End Sub

 

.NET

Module Module1

    Sub Main()
        Dim f As System.IO.FileStream = System.IO.File.Open("C:\test2.bin", IO.FileMode.Create, IO.FileAccess.Write)
        Dim fw As New System.IO.BinaryWriter(f)
        Dim d As Double
        d = 1.123
        fw.Write(d)
        fw.Close()
    End Sub


End Module
 

So you could make an api call in those cases with something like:

Dim handle As System.Runtime.InteropServices.GCHandle = System.Runtime.InteropServices.GCHandle.Alloc(d, System.Runtime.InteropServices.GCHandleType.Pinned)
Dim ptr As System.IntPtr = handle.AddrOfPinnedObject()
Try
    APICall(ptr)
Finally
    handle.Free()
End Try

Upcoming features in the Visual Basic Upgrade Companion version 3.0

We are currently wrapping up all development effort to focus on the final testing and stabilization of the next version of the Visual Basic Upgrade Companion, both Enterprise and Developer Editions, version 3.0. For this version we focused more on architecture improvements, preparing the code base for more significant upgrades in the future. We still we managed to add some great features such as:

  • Enhanced resolution of default properties: By both improving the typing engine of the VBUC and generating additional code for runtime resolution of default properties, we were able to reduce the total amount of EWIs present in the code by 30%!
  • Improved support for API Calls: Most API calls should now work correctly. There are still a couple of issues, but they should be sorted out by the final release
  • IsMissing migration: We now correctly support the migration of the IsMissing statement.
  • Enhanced support for the migration of common controls, such as Imagelist, Listview, Statusbar, Toolbar and Treeview, to native .NET components. We now correctly convert most functionality of these controls to .NET
  • A greatly enhanced Assessment Mode to better estimate the effort required to perform a migration project
  • Significant performance improvements and memory footprint
  • Over 150 code generation improvements based on feedback from projects we’ve done, our clients and partners

We are currently conducting a limited Beta program for the VBUC Developer Edition v3.0. If you are interested in participating, drop me a line and I’ll get back to you with further instructions.

Edit: The upcoming version of the VBUC will be version 3.0 - this release represents a leap in the level of automation and additional features we managed to squeeze in, and thus deserved a new major version number. I will post additional details on the different features as the final release date approaches.

Change CreateObject during Migration

One of our clients wanted to change the CreateObject function migration for a function of their own. So they wanted all cases like:

Dim x As Object
Set x = CreateObject("Excel.Application")

 

To be migrated to something like:

Excel.Application x = (Excel.Application) Utils.MyCreateObject("Excel.Application", "");

Our migratio vb6migration tool provides a new cool feature called CustomMaps. This feature allows you to provide some simple but useful changes to the way things get migrated.

For this case follow these steps:

1. Open the Visual Basic Upgrade Companion.

2. In the Tools Menu choose:

image

3. Create a new CustomMaps File and an an entry like the following:

 

image

Notice the Source name is VBA.Interaction.CreateObject. To find out this name you can look in your VB6 IDE, right click on the CreateObject and select goto Definition.
image 
 
image 
and for the target name just put the implementation that you what, for example you can write a function like:
class Utils
        {
            public static object MyCreateObject(string className,params object[] ignoreRestParams)
            {
                return Activator.CreateInstance(Type.GetType(className));
            }
        }

and set the SourceName to Utils.MyCreateObject (or NameSpace.Utils.MyCreateObject to use the fully qualified name). You just need to set the New Reference Name column because we will not change the definition of the function.

.NET Calculate week number of a date

20. March 2009 06:32 by Mrojas in General  //  Tags: , , ,   //   Comments (0)
This post shows a way to calculate the number of weeks.
Remember that this calculation is culture-dependant
For example the GetWeekOfYear methods requires a criteria to determine 
how to determine the first week and which day to consider as FirstDayOfWeek for more info see here:

CalendarWeekRule.FirstDay

Supported by the .NET Compact Framework.

Indicates that the first week of the year starts on the first day of the year and ends before the following designated first day of the week. The value is 0.

CalendarWeekRule.FirstFourDayWeek

Indicates that the first week of the year is the first week with four or more days before the designated first day of the week. The value is 2.

CalendarWeekRule.FirstFullWeek

Indicates that the first week of the year begins on the first occurrence of the designated first day of the week on or after the first day of the year. The value is 1.

 

 

Sample Code

        Dim x As Date
        Dim currentCulture As System.Globalization.CultureInfo
        currentCulture = CultureInfo.CurrentCulture
        Dim weekNum = currentCulture.Calendar.GetWeekOfYear(x, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday)

Learn about low-cost and low-risk migration options with Avanade and ArtinSoft

18. March 2009 04:48 by Fzoufaly in General  //  Tags: , , , , ,   //   Comments (0)

On Wednesday April 15th 2009 Avanade and ArtinSoft will host a webinar on how to quickly and cost effectively renew your Visual Basic 6 applications.

Here’s an excerpt from the invitation:

“Don’t miss this chance to learn more about VBUC and other cost effective migration options, including:
• Which migration strategy works best for you (complete, partial,
  coexistent, partial development)
• How to reduce project risk, costs, and time to market
• How to guarantee business continuity by preserving knowledge
  invested in legacy applications“

You can RSVP and make sure you don’t forget to attend.

Get path of ASP.NET web application that is running

If you have your ASP.NET application for example in c:\inetpub\wwwroot\WebApplication1 and you want to programmatically get that path just use something like:

 

string AppPath = Request.PhysicalApplicationPath;

Large Companies, Successful VB6 Migrations

11. March 2009 11:51 by Fzoufaly in General  //  Tags: , , , , ,   //   Comments (0)

Here is a summary of some recent case studies that we have produced with our customers. 

The message is common: Visual Basic 6 to C# migrations are an excellent alternative that saves time and money when you need to move your application to .NET.

HSI

This Texas-based company provides geo-navigation solutions for the horizontal drilling industry, and when the end of official support for the VB6 development environment was announced, they turned to ArtinSoft to migrate their LatNav application from VB6 to C# on a turn-key basis, using a slightly customized version of the Visual Basic Upgrade Companion.

“Utilizing the Visual Basic Upgrade Companion saved us about one year of development and $160,000. This conversion will allow us to leapfrog well in front of our competition” -- Ken Bowdon - HSI founder

Read the full HSI case study.

MDA

After discarding a manual rewrite and the Upgrade Wizard, MDA –a software services provider for the real estate sector– settled for ArtinSoft’s Visual Basic Upgrade Companion tool, with which RDO was transformed to ADO.NET, third party controls were converted to native .NET controls, Component One’s True DB grid was upgraded to the latest version of that component, and coding standards that were common place when developing in Visual Basic 6.0 were also migrated to equivalents in VB.NET.

“We looked at different options, like a rewrite and the Upgrade Wizard. The UW couldn’t cater for our needs, especially since we were going from RDO to ADO.NET. A rewrite would have been about a five-year project for us, and possibly in the region of US$500,000. Using the Visual Basic Upgrade Companion represented an estimated saving for the project of about 3 years and US$300,000”. -- Rodger Beadle – Technical Director, MDA

Read the full MDA case study.

Vertex

Vertex, a leading global BPO and customer management outsourcing company, managed to ensure compliance and business continuity by upgrading not one, but two mission-critical applications from VB to .NET using a customized version of the Visual Basic Upgrade Companion (VBUC). These case studies underscore the joint efforts made by both companies, which proved to be decisive to accomplish the goal of having both migrated applications up and running within some serious time constrains.

"ArtinSoft has been an excellent company to work with. They have been responsive to requests from Vertex to change their processes in order to accommodate the way in which we work. They have provided us with daily updates throughout the migration life cycle and have worked in partnership with Vertex to resolve any issues that have arisen in a pragmatic and expedient manner." -- Sue Craig - Senior Project Manager, Vertex

Read the full Vertex Omiga Case Study.

Read the full Vertex Supervisor Case Study.

Banamex / Citigroup

Learn how Banamex, one of the most widely recognized financial institutions in Latin America and purchased by Citigroup in 2001, was able to migrate over 5 million lines of code from VB6 and ASP to C# and ASP.NET using ArtinSoft’s Visual Basic Upgrade Companion, in compliance with Citigroup’s corporate policies for quality assurance and information security. The project also included the creation of an effective collaboration environment and the implementation of highly advanced security tactics in order to guarantee full confidentiality in data handling.

Read the full Banamex/Citigroup Case Study.

I've decided to move away from VB6. Now What?

At some point in time companies decide they want to leave a certain platform.  Let’s not focus on the reasons why they decide to move but on HOW to move instead. Companies reach the decision to move on their own timetable.

Once you have decided that you want to move away from VB6 then ArtinSoft comes into play.  The purpose of my blog is to show that there is a way out that is good, fast and cost-effective.  Compared to what? You might ask, let’s see.

Once you decide to move (let me be clear, you made the decision to move, then the rest of the discussion applies) you have to assess your applications and make a decision on HOW to move them one by one. 

There are three axes along which we recommend our customers to make the analysis:

  • How unique is the functionality to your business? For example, if you have a general ledger that does not have any particular features for your business, if you have a “me too” app that does not give you an advantage over your competitors, well, you should consider just buying a package and replace it.
  • How good is the technical quality of your source code? Have you followed best practices in VB?  Is your code maintainable by a third party? (Can they understand it?) If the answer is no then migrating it to a new language is not going to improve this situation.  Consider a rewrite.
  • How fast is the functionality changing to meet business goals? Is the business process it supports fixed?  Do you anticipate that very minimal changes will happen before retirement?  Then you should just leave it as is (one caveat here, in some industries because of regulatory issues you might still make sure you are on a fully supported platform even if the application does not change).

Now, if you have an application that provides you a business advantage, that is of good technical quality and that needs to adapt to new business challenges, then you have a good candidate for a migration.

For applications with the above characteristics, why is a migration better than a rewrite?

  • Cost: when we look at cost there are several dimensions.
    • Cost of the actual migration process: An automatic migration to functional equivalence can be done with about 20% of the cost of a rewrite.  Most of that cost is testing and fine tuning of the application to the new platform.
    • Training of end users: Since the application is functionally equivalent it is not necessary to retrain end-users.  With a rewrite, chances are that the output is not going to be functionally equivalent unless you follow an algorithmic approach just like an automatic migration and therefore end users need a retraining.  In addition to the actual retraining cost (which can be enormous – e.g. we worked with a customer whose system required a 6 weeks training time, for 3000 users.  An application replacement or rewrite would have started with that hole in front of them) but the opportunity cost.  New software, new mistakes, how does that impact the business continuity?
  • Time: An automatic migration process can also be done in about 20% of a rewrite.  This means that you can free up resources much faster to actually build new functionality that the business requires instead of attempting to replicate functionality that already works.
  • Quality: An automatic migration does not fundamentally change the architecture of the original application (even if certain aspects like data access and some pieces of GUI architecture do change). The question is: do you really need to change the architecture for the whole application? Probably not. You might need to change the architecture for certain processes.  The code that is generated by ArtinSoft is completely ready for evolution.  No strange variable names, all comments preservation, no restructuring of the code, etc.  Even if in the worst case scenario you need to rewrite a certain piece of the application it is always a fraction of the total cost.

Comments?

Resizing Forms in C#

In the VB6 world it was very common to use “Resizer” OCXs that you just put on your forms and that they handle all the proportional resizing needed if you changed your form.

It was very simple and easy.

However when I started looking for something like that in .NET it was quite hard to find. So finally I got to ComponentSource and found some alternatives and I evaluated them:

 

Component Vendor Pricing URL
Component One Sizer For .NET Component ONE I think you have to buy the Component One Studio. That’s $800 ($1000 with more support)
and I think is one license per developer, runtime-free
http://www.componentone.com/SuperProducts/StudioWinForms/
.NET Forms Resize Softgroup 380$ per developer
from ComponentSource
if you buy directly from them you can get the component for 180$

Each copy is licensed on a per developer basis. A developer may use the license on multiple CPUs as long as they are not used concurrently nor used by another developer. Run-time royalty free.
http://www.soft-group.it/net/index.php?c=3a&id=11
Resize OCX/.NET Larcom and Young 95$-100$ per license

one license per developer, runtime-free
http://www.lyoung.com/

 

All of them seem to work. So it really up to your company preferences, budget and the level of support you desire. I haven't made tests like how it behaves if you have thirdparty components or activex ??? maybe I'll review that later.

Calling .NET from PowerBuilder

3. March 2009 08:14 by Mrojas in General  //  Tags: , , , , ,   //   Comments (0)

Most of our clients come from a medium-size to a big enterprise level. In these scenarios is very common to have different department using different technologies to solve their business needs.

These different technologies can be on a very homogeneous platform like .NET where you can easily interact between your VB.NET and C# assemblies, or they could be on differente technologies like ASP, Classic VB, C++, or Powerbuilder.

This post is about PowerBuilder, and in order to interact with PowerBuilder I think the easiest way is to expose your assemblies thru COM Interop.

So if there is some .NET functionality that you want to expose to PowerBuilder you just need to expose that functionality with a class in a ClassLibrary project with COM attributes.

Let’s begin with a simple program to show how to comunicate Powerbuilder with C#.

NOTE:  If you don’t have Powerbuilder you can get a trial version from: http://www.sybase.com/detail?id=1052162

  1. Open Microsoft Visual Studio
  2. On the File Menu, choose the New option, and in the File submenu choose Project….

Visual Studio File Menu

Figure 1. Visual Studio File Menu. Choosing the option for a new project

  1. When you choose that option a dialog window will shown with the available options for new projects. In the option for C# Projects choose “Class Library”

image

Figure 2. New Project dialog window

You must introduce the new project name, location and solution name. Type something like ClassLibrary1, D:\PowerBuilder, ClassLibrary1.

1. When you finish creating your project you will have a code file called Class1.cs.

2. Change that code for something like :

using System;
using System.Collections.Generic;
using System.Text;

namespace SimpleClass
{
    public class Class1
    {
        public int AddTenToParameter(int param1)
        {
            return param1 + 10;
        }

        public void SayHi()
        {
            System.Windows.Forms.MessageBox.Show("Hello World!");
        }

        public String GiveMeDate()
        {
            return DateTime.Now.ToLongDateString();
        }
    }
}

This will allow to test things like parameter passing, using different return types like strings or integers. But Before you continue you must add a reference to System.Windows.Forms to be able to use the MessageBox.

 

Context Menu to add a reference

Figure 3. Adding a reference

 

Dialog with References

Figure 3. Reference to System.Windows.Forms

3. Right click on the solution file and select properties:

Project properties

Figure 4. Option to change project properties

4. Select the Register for COM Interop  checkbox

Register for COM

Figure 5. Project properties window

5. Return to Class1.cs code file

6. Add an using statement after the existing using lines on Class1.cs file:

using System.Runtime.InteropServices;

7. Add the following attributes to the class:

[ComVisible(true)]

[ClassInterface(ClassInterfaceType.AutoDual)]

[ProgId("ClassLibrary1.Class1")]

Note: the ProgId is very important, because these value will be use in PB to comunicate with the this code

8. Now you must edit the AssemblyInfo.cs

AssemblyInfo file

Figure 6. AssemblyInfo.cs File

Now make sure to establish the COM settings in this file with statements like the following:

// Setting ComVisible to false makes the types in this assembly not visible

// to COM components. If you need to access a type in this assembly from

// COM, set the ComVisible attribute to true on that type.

[assembly: ComVisible(true)]

// The following GUID is for the ID of the typelib if this project is exposed to COM

[assembly: Guid("69efac5b-d887-40f4-a7e9-2721ac3c1598")]

 

The Guid is also very important, because this is used to differentiate this component and it must be unique.

To generate a new GUID you can got to the Tools Menu and choose the option Create GUID

Create GUID menu option

Figure 7. Option menu to create a GUID

In the Create Guid dialog box, choose the fourth option and press Copy to put the contents on the Clipboard. Later, copy that value in the GUID attribute but remove the “{“ y “}”.

Now we are set. You only need to build the solution and the DLL. The build process with register the COM component.

If you will use the component on another computer you need to create an instalation program.

 

Using your program from Powerbuilder

Using your program from Powerbuilder is very easy. You just need code like the following:

image

Figure 8. PB Code to call a C# class thru COM

When you execute this program you will have 3 messageboxes :

  • Hello World!
  • 30
  • Monday, March 02, 2009 (this message will change depending of the day, locale and regional settings)

 

Creating an instalation program

  1. Right click the solution and in the context menu choose Add and then new project.

Context Menu for Adding new project to solution

Figure 9. Context Menu to add a new project

On the dialog box for Add New projec, look for the Other Project Types section and the choose Setup Project.

Adding a setup project

Figure 10. Creating a setup project

In this dialog bos indicate the name and location of the setup project. For example Setup1 and D:\Powerbuilder\ClassLibrary1.

Later, add a project to the setup program. To do that rigth click on the setup project and select Add, and in the submenu choose Project Output.

 

image

Figure 11. Adding a project to the setup project.

A dialog box will be shown with a combo that allow you to select the proyects in the solution. Choose ClassLibrary1 and press OK.

Add Project Output Dialog

Figure 12. Adding project output to the setup project.

When you build this instalation program two files will be produced:

Release

D:\PowerBuilder\ClassLibrary1\Setup1\Release\Setup.exe

D:\PowerBuilder\ClassLibrary1\Setup1\Release\Setup1.msi

Debug

D:\PowerBuilder\ClassLibrary1\Setup1\Debug\Setup.exe

D:\PowerBuilder\ClassLibrary1\Setup1\Debug\Setup1.msi

When you run the instalation program, this program will handle the instalation of the .NET component and the COM registration.

Categories