Porting Application from iOS to WP7C#. Some toughts migration of Objective-C to C#

29. April 2011 12:07 by Mrojas in   //  Tags: , , , , , , , , , , , , ,   //   Comments (0)

Windows Phone 7 (WP7) is out! and it’s a great platform for developing new Apps. After being involved with Silverlight for a while
I am glad to have now the option to deploy apps to Windows Phone 7.

But we have to recognize that there are tons of great Apps for iPhone already. You might even have some of them.
So it’s porting time. Here at Artinsoft we love to upgrade/port application to all platforms.
So I will provide here some basic thoughts to help you upgrade your code.

For this post let’s discuss a little about applications written for XCode.

XCode applications are written in Objetive-C.Let’s map some examples:

In Objective-C your class will be usually

#import <Foundation/NSObject.h>
#import <Foundation/NSObject.h>

@interface Fraction: NSObject {
    int numerator;
    int denominator;
}

-(void) print;
-(void) setNumerator: (int) n;
-(void) setDenominator: (int) d;
-(int) numerator;
-(int) denominator;
@end
How you should understand that? Well this is just the list of methods in your class something like:
using System;
public class Fraction {    
    int _numerator;    
    int _denominator;    
    public void print() { /* TODO*/}     
    public int numerator   { get { /* TODO */ } set { /*TODO*/} }    
    public int denominator { get { /* TODO */ } set { /*TODO*/} }
}
The code for these methods will be in the .m file.
#import "Fraction.h"
#import <stdio.h>

@implementation Fraction
-(void) print {
    printf( "%i/%i", numerator, denominator );
}

-(void) setNumerator: (int) n {
    numerator = n;
}

-(void) setDenominator: (int) d {
    denominator = d;
}

-(int) denominator {
    return denominator;
}

-(int) numerator {
    return numerator;
}
@end
So that will complement your class implementation for something like:
using System;
public class Fraction 
{    
    int _numerator;    
    int _denominator;    
    public void print() 
    { 
        Console.Write("{0}/{1}" ,numerator,denominator);
    }     
    public int numerator     
    {         
        get { return _numerator; }        
        set { _numerator = value; }    
    }    
    public int denominator     
    {        
        get { return _denominator; }       
        set { _denominator = value; }    
    }
}
Ok An now let’s look at the Objective-C main.m:
#import <stdio.h>
#import "Fraction.h"

int main( int argc, const char *argv[] ) {
    // create a new instance
    Fraction *frac = [[Fraction alloc] init];
    Fraction *frac2 = [[Fraction alloc] init];

    // set the values
    [frac setNumerator: 1];
    [frac setDenominator: 3];

    // combined set
    [frac2 setNumerator: 1 andDenominator: 5];

    // print it
    printf( "The fraction is: " );
    [frac print];
    printf( "\n" );

    // print it
    printf( "Fraction 2 is: " );
    [frac2 print];
    printf( "\n" );

    // free memory
    [frac release];
    [frac2 release];

    return 0;
}
 
Which can be rewritten in C# as:
 
using System;
static class ProgramMain{static int Main(string[] argv) {
    // create a new instance
    Fraction frac = new Fraction();
    // set the values frac.Numerator = 1; frac.Denominator = 3;
    // print it
    Console.Write( "The fraction is: " );
    frac.print();    Console.Write( "\n" );
    // free memory frac = null;
    return 0;
}}
Well this is just for warming up. In following posts we will be looking 
at more Objective-C \ XCode concept mapping to C#.
I recommend looking at the site http://wp7mapping.interoperabilitybridges.com/ 
that provides a lot about mapping iOS API
 

Windows Azure Migration: Database Migration, Post 1

2. April 2011 18:14 by Mrojas in   //  Tags: , , , , , , , , , ,   //   Comments (0)

WheWhen you are doing an azure migration, one of the first thing you must do is
collect all the information you can about your database.
Also at some point in your migration process you might consider between migration to
SQL Azure or Azure Storage or Azure Tables.

Do do all the appropriate decisions you need to collect at least basic data like:

  • Database Size
  • Table Size
  • Row Size
  • User Defined Types or any other code that depends on the CLR
  • Extended Properties

Database Size

You can use a script like this to collect some general information:

create table #spaceused(
databasename varchar(255),
size varchar(255),
owner varchar(255),
dbid int,
created varchar(255),
status varchar(255),
level int)

insert #spaceused (databasename , size,owner,dbid,created,status, level)  exec sp_helpdb

select * from #spaceused for xml raw
drop table  #spaceused
 

When you run this script you will get an XML like:

<row databasename="master" 
size=" 33.69 MB" 
owner="sa" 
dbid="1" 
created="Apr 8 2003" 
status="Status=ONLINE, ..." 
level="90"/>
<row databasename="msdb" 
size=" 50.50 MB" 
owner="sa" 
dbid="4" 
created="Oct 14 2005" 
status="Status=ONLINE, ..." 
level="90"/>
<row databasename="mycooldb" 
size=" 180.94 MB" 
owner="sa" 
dbid="89" 
created="Apr 22 2010" 
status="Status=ONLINE, ..." 
level="90"/>
<row databasename="cooldb" 
size=" 10.49 MB" 
owner="sa" 
dbid="53" 
created="Jul 22 2010" 
status="Status=ONLINE, ..." 
level="90"/>
<row databasename="tempdb" 
size=" 398.44 MB" 
owner="sa" dbid="2" 
created="Feb 16 2011" 
status="Status=ONLINE, ..." 
level="90"/>

And yes I know there are several other scripts that can give you more detailed information about your database
but this one answers simple questions like

Does my database fits in SQL Azure?
Which is an appropriate SQL Azure DB Size?

Also remember that SQL Azure is based on SQL Server 2008 (level 100).

80 = SQL Server 2000

90 = SQL Server 2005

100 = SQL Server 2008


If you are migrating from an older database (level 80 or 90) it might be necessary to upgrade first.

This post might be helpful: http://blog.scalabilityexperts.com/2008/01/28/upgrade-sql-server-2000-to-2005-or-2008/

Table Size

Table size is also important.There great script for that:

http://vyaskn.tripod.com/sp_show_biggest_tables.htm

If you plan to migrate to Azure Storage there are certain constraints. For example consider looking at the number of columns:

You can use these scripts: http://www.novicksoftware.com/udfofweek/vol2/t-sql-udf-vol-2-num-27-udf_tbl_colcounttab.htm (I just had to change the alter for create)

Row Size

I found this on a forum (thanks to Lee Dice and Michael Lee)

DECLARE @sql        VARCHAR (8000)
        , @tablename  VARCHAR (255)
        , @delim      VARCHAR (3)
        , @q          CHAR (1)

  SELECT @tablename = '{table name}'
       , @q         = CHAR (39)

  SELECT @delim = ''
       , @sql   = 'SELECT '

  SELECT @sql   = @sql
                + @delim
                + 'ISNULL(DATALENGTH ([' + name + ']),0)'
       , @delim = ' + '
  FROM   syscolumns
  WHERE  id = OBJECT_ID (@tablename)
  ORDER BY colid

  SELECT @sql = @sql + ' rowlength'
              + ' FROM [' + @tablename + ']'
       , @sql =  'SELECT MAX (rowlength)'
              + ' FROM (' + @sql + ') rowlengths'
  PRINT @sql
  EXEC (@sql)

Remember to change the {table name} for the name of the table you need

User Defined Types or any other code that depends on the CLR

Just look at your db scripts at determine if there are any CREATE TYPE statements with the assembly keyword.
Also determine if CLR is enabled with a query like:

select * from sys.configurations where name = 'clr enabled'

If this query has a column value = 1 then it is enabled.

Extended Properties

Look for calls to sp_addextendedproperty dropextendedproperty OBJECTPROPERTY and sys.extended_properties  in your scripts.

Silverlight and what to do with Application or User Settings or INI files

Some people ofter forget about this (even me Confused smile ) So that;’s why I’m posting about this.

In my work (at Artinsoft) we are currently performing a lot of Winforms and VB6 
migration to Silverlight. And a common problem is “What can I do with the user settings!!!”.

In VB6 you had your INI files and in Winforms you probably used something like the App settings.
But when you move to Silverlight what can you do!.
You need a set of initial values and you probably wont want to “burn” those inicial values in your XAP file.
It would be nicer if those values can just be set in the Web.Config file.

So a common way to solve this, is develop a simple helper class. This helper class will use a service that will
collect your initial ini files or appsettings values and store them in your Isolated Storage.
You can even use some kind of basic cryptography if you feel that your date is sensitive.

And then you can use the helpful IsolatedStorageSettings class. For example see this code,
that I borrowed from this post: http://wildermuth.com/2008/10/21/Using_Isolated_Storage_Settings_in_Silverlight_2

const string FAVCOLORNAME = "favoriteColor";
public Color? FavoriteColor
{
  get
  {
    if (IsolatedStorageSettings.ApplicationSettings[FAVCOLORNAME] != null)
    {
      Color? colorSetting =         IsolatedStorageSettings.ApplicationSettings[FAVCOLORNAME] as Color?;
      if (colorSetting != null) return colorSetting;
    }

    // If we can't find a favorite color, return a null color
    return new Color?();
  }
  set
  {
    IsolatedStorageSettings.ApplicationSettings[FAVCOLORNAME] = value;
  }
}

As you can see is very easy to save and recover simple settings from the Silverlight Isolated Storage

Azure Migration: ASP.NET Site with Classic Pipeline mode

Recently while we were performing the migration of a blog engine in ASP.NET to Azure we had to deal with some issues with
the differences between IIS6 and IIS7.

Windows Azure Web Roles, use IIS7, with Integrated Pipeline mode and that is a breaking change for some ASP.NET sites.

The are at least two main changes:

 

First  is for HTTP modules and handlers.(This info was taken from: http://arcware.net/use-a-single-web-config-for-iis6-and-iis7/)

" For IIS6, they were configured in the <system.web> section, as such:

 

        <httpModules>
            <add name="..." type="..." />
            <add name="..." type="..." />
            <add name="..." type="..." />
        </httpModules>

        <httpHandlers>
                 <add  verb="..." path="..." type="..." />
                 <add  verb="..." path="..." type="..." />
        </httpHandlers>

However, to get these to work in IIS7 you must *move them* from the <system.web> section to the new <system.webServer> section, which is what IIS7 requires when running in Integrated Pipeline mode (it’s not needed for Classic Pipeline mode)

 

So instead of the above you have this instead:

<system.webServer>
    </modules>
        <add name="..." type="..." />
    </modules>
    <handlers accessPolicy="Read, Write, Script, Execute">
        <add verb="...." name="..." path="..." type="..." />

</handlers>
</system.webServer>

Notice there are a couple slight changes, which means you can;t just copy and paste
these as-is from <system.web> into <system.webServer>:

<httpModules> and <httpHandlers> have been renamed to <modules> and <handlers>, respectively.

Each handler in IIS7 requires a name attribute. If you don;t specify it, you'll get an error message.

The handlers node has an optional, but good-to-define accessPolicy attribute.
This value depends on your handlers, so use the ones that are right for you."

Second
There are some restrictions in IIS7 when you are running in Integrated mode.
For example you cannot do calls to the request property of an HttpContext object.
All calls to HttpContext.Current.Request will have a problem because Request will be null.

You can see more details here:

http://mvolo.com/blogs/serverside/archive/2007/11/10/Integrated-mode-Request-is-not-available-in-this-context-in-Application_5F00_Start.aspx

 

Restoring simple lookup capabilities to Silverlight ListBox

27. January 2011 04:09 by Mrojas in General  //  Tags: , , , , , , ,   //   Comments (0)

VB6 and WinForms ListBox has the built in capability to provide a simple data look up. But the Silverlight ListBox does not.
So if you have a list with items:

Apple 
Airplane 
Blueberry 
Bee 
Car 
Zoo 
Animal Planet

And your current item is Apple when you press A the next current item will be Airplane

Apple 
Airplane 
Blueberry 
Bee 
Car 
Zoo 
Animal Planet

And the next time you press A the next current item will be Animal Planet

Apple 
Airplane 
Blueberry 
Bee 
Car 
Zoo 
Animal Planet

And the next time you press A the next current item will be Apple again

Ok to do in Silverlight you need to add a event handler. You can create a user control and this event handler and replace your listbox for your custom listbox or just add this event handler for the listboxes that need it. The code you need is the following:

void listbox1_KeyDown(object sender, KeyEventArgs e)
{
    String selectedText = this.listbox1.SelectedItem.ToString();
    String keyAsString = e.Key.ToString();
    int maxItems = listbox1.Items.Count;
    if (!String.IsNullOrEmpty(selectedText) && 
        !String.IsNullOrEmpty(keyAsString) && keyAsString.Length == 1 && 
         maxItems > 1)
    {   
        
        int currentIndex = this.listbox1.SelectedIndex;
        int nextIndex    = (currentIndex + 1) % maxItems;
        while (currentIndex != nextIndex)
        {
            if (this.listbox1.Items[nextIndex].ToString().ToUpper().StartsWith(keyAsString))
            {
                this.listbox1.SelectedIndex = nextIndex;
                return;
            }   
            nextIndex    = (nextIndex + 1) % maxItems;   
        }
        //NOTE: theres is a slight different behaviour because for example in 
        //winforms if your only had an item that started with A and press A the selectionIndex
        //will not change but a SelectedIndexChanged event (equivalent to SelectionChanged in Silverlight)
        //and this is not the Silverlight behaviour
    }
    
}

Upgrading Applications Written in Earlier versions of Visual Basic for example VB4, VB5

21. December 2010 05:01 by Mrojas in   //  Tags: , , , , , , , , , ,   //   Comments (0)

Some time ago Artinsoft participated in the development of a book called “Upgrading Visual Basic 6.0 Applications”.

I quote from that book:

“The upgrade wizard is designed to upgrade Visual Basic 6.0 applications. For
projects written in Visual Basic versions 1.0 through 5.0, it is necessary that you first
upgrade them to Visual Basic 6.0 before upgrading to Visual Basic .NET. To upgrade
a project that was developed in a version earlier than Visual Basic 6.0, simply open
the project in the Visual Basic 6.0 IDE and save it. If Visual Basic 6.0 prompts you to
upgrade controls to Visual Basic 6.0, choose Yes. If the project contains Visual Basic
5.0 ActiveX controls, it is often best to replace these controls with Visual Basic 6.0
versions. This is because these controls use a different threading model than models
used by Visual Basic 6.0 controls. The earlier threading model is not supported in
Windows Forms.
For 16-bit projects written in Visual Basic versions 1.0 through 4.0, you may need to
make extra modifications to the application to convert it to Visual Basic 6.0.
VBX controls will not be automatically converted. You will also have to replace
Win16 Windows APIs with their Win32® counterparts.
Visual Basic versions 2.0 and 3.0 often require an extra step. Visual Basic 6.0 can only
open files in text format, whereas Visual Basic versions 2.0 and 3.0 support two file
formats: binary and text. Before upgrading these projects, ensure the entire applica-
tion is saved in text format by using the following procedure.

To convert Visual Basic 1.0 and 2.0 files to text format
1. On the File menu, click Save As.
2. In the Save dialog box, select the Save As Text check box.
Because Visual Basic 1.0 can only save files in binary format, all of these projects will
first need to be opened in Visual Basic 2.0 or 3.0 and then saved as text before they
can be converted to Visual Basic 6.0. After converting the project to Visual Basic 6.0,
you can begin the process of upgrading it to Visual Basic .NET.”

This book is available for free
from the MSDN

Migrate JSP to ASP.NET MVC

14. December 2010 06:19 by Mrojas in General  //  Tags: , , , , ,   //   Comments (0)

ASP.NET has gone a long way. And it might be the right time to start moving your sites to ASP.NET.

But what happens if you have a big investment in JSP. Will I lose all my JSP skills?

Well ASP.NET is not the same as JSP but the MVC view engine concept can help you retain some of the JSP flavor.

A good MVC View Engine project is SharpTiles this project provides a partial implementation of JSTL and Tiles.

Just take a look at the the SharpTiles. Just as they say SharpTiles if for you if “You are a Java Developer and you don’t like .aspx”

Custom tool warning: Cannot import wsdl:portType

25. November 2010 05:04 by Mrojas in General  //  Tags: , , ,   //   Comments (0)

During a Silverlight migration project from VB6 I was trying to add a WCF reference,
everything seemed to work in the wizard but no code was generated.

After reviewing the Warning messages, i found that some said:

Custom tool warning: Cannot import wsdl:portType

What I did to solve this issue?

1. Right click on your service reference

2. Select Configure Service reference

3. Uncheck the option that says Reuse types in referenced assemblies.

image

4. Press OK

After that VS generated the code and I could use the WCF service.

Lightswitch Experiences: Migrating Access to Microsoft Lightswitch

25. November 2010 03:07 by Mrojas in General  //  Tags: , , , ,   //   Comments (0)

 

 

Microsoft Access was (and is still) very used for simple data entry applications.
But Microsoft Access despite all its good is kind of an old technology and there was
no clear alternative for a simple mortal development environment… until Microsoft Lightswitch.

This series of posts illustrates the experiences of migrating Microsoft Access applications to LigthSwitch.

This post shows the result of migrating all Northwind Access example tables:

The following is Microsoft LightSwitch Solution explorer showing all Tables

image

 

And these are some of the Northwind tables in LIghtswitch

 

image

image

 

image

image

 

image

 

image

 

The migration process is straightforward. Text and Memo fields can be migrated to string, Numbers can be migrated to Int32 or Int64, Currency is map to Money. Yes\No can be mapped to boolean with a Value List.

There is support for specifying a caption (Display ID in Lightswitch), Description, and validation rules.

I will keep posting about Query migration, form migration and also  report migration. Stay tuned.

Starting a Project for the Cloud

27. October 2010 08:43 by Mrojas in General  //  Tags: , , , , ,   //   Comments (0)

 

If you dont have Windows Azure Tools installed

1. Open Visual Studio 2010

2. On the File Menu, Click new, and then click Project. This opens the New Project dialog

3. In the New Project dialog under Installed Templates, expand the Visual C# node

4. In project type click Cloud. A project that says Enable Windows Azure Tools appears

5. In Name type for example EnableTools and click OK

6. A project with a web page will appear. Click the Download Windows Azure Tools button. Close Visual Studio. Download and installed them.

image

Once you have Windows Azure Toolsl installed

 

1. Open Visual Studio 2010

2. On the File Menu, Click new, and then click Project. This opens the New Project dialog

3. In the New Project dialog under Installed Templates, expand the Visual C# node

4. In project type click Cloud. A project that says Windows Azure Cloud Service appears

image

5. In Name Type for example Phonebook  and click ok. The New Cloud Service Project is shown

 

If you are developing a Silverlight application with some services select the WCF Service Web Role. Rename it to something appropriate. In this example will be Phonebook.Web and Press OK

image

Your solution explorer will look like this:

image

Now you can developing your application. We already have an Silverlight application (that was migrated from VB6 to Silverlight) and some existing Silverlight Class libraries and Server Class Libraries (Class Libraries compiled with the full 4.0 Framework that will be used in the Server Project Phonebook.Web).

To add your Silverlight app. Right Click your server project (Phonebook.Web), then Properties and in Properties go to Silverlight Application and add Phonebook_Silverlight

When everything compiles Go to the Visual Studio Menu Bar, then Debug and then Start Without Debugging. That starts the local development environment on your computer.

image

You can now start testing and finish development of your application.

There is something you myst notice. Everytime you start the Cloud Service, the Azure test environment starts. By default it will start in http:\\localhost:81 but there was a previous Development Fabric it will start in http:\\localhost:81. This is important for Silverlight applications because you must configure your service end point to a particular port. Make sure that your ServiceReferences.ClientConfig file is in sync with the port that your DevelopmentFabric is using

Notes for Azure development:

Sometimes during development it might happen that you get more than one instance of the Development Fabric. This will affect your silverlight apps that rely on WFC services because each new instance starts on a new port. You can use the CSRun tool to stop all instances.

If you have installed the Windows® Azure™ SDK to the default location, the CSRun tool can be found at C:\Program Files\Windows Azure SDK\v1.0\bin\csrun.exe.Then run C:\Program Files\Windows Azure SDK\v1.2\bin\csrun.exe /devfabric:shutdown

 

Publishing your Application

1. Navigate to Azure : https://windows.azure.com/Cloud/Provisioning/Default.aspx

2. On the page that says My Projects. When you are starting you will only see one project line. Click on it

image

3. Click on New Service

image

4. Click on Hosted Services

image

5. In the Create Service page, specify the service properties. In this example we will use Phonebook.Web for service label and a short description and press next.

image

6. Now your hosted service needs a public url. You must check availability. In this example we will use phonebook. Hosted Affinity tries to group your services and storages in the same area. We have a SQL Azure database that is hosted in North Central US, so we will create a new AffinityGroup and call it PhonebookGroup. Press Create

image

7. After Creation your Service is ready, and you can start the deployment.

image

 

8. In Visual Studio 2010 Right click your Cloud Service. And Select Publish…

image

 

9. The Publish Cloud Service Dialog appears. From the Credentials drop down list select <Add>

image

10. From the Create or select an existing certificate select <Create>.
10.1 In our example we will enter a FriendlyName for the new certificate of PhoneBook.

image


10.2 Click the “Copy the full path” link in the dialog. Then Open your browser and navigate to https://windows.azure.com/cloud/provisioning/ and click on your project

 

image

10.3 Now click on account.And in the Account page click on Manage My API Certificates

image

10.4 Click the Choose file and paste the full path you had copied before and then click upload

image

the installed certificate will be shown below.

image

10.5 Now navigate to AppFabric by clicking AppFabric on the left hand side. This will show your subscription ID. Select it and copy it. You have to pasted on the dialog box in Visual Studio on the textbox that says above it “Copy the subscription ID”

image

and name those Credentials PhonebookAccount and press  OK

 

 

 

 

 

 

 

 

 

11 You need a storage account. If you have not created one. Then you have to follow these steps:

11.1 Open your browser and navigate to https://windows.azure.com/cloud/provisioning/ and click on your project.

 

image

11.2 Now click on New Service

image

11.3 Now click on Storage Account

image

11.4 The Create Service Page is show. Enter a Service label and Description and Click Next

image

 

 

 

11.5 Select a name for the public URL, check its availability. And select Affinity.And press Create

image

12. Press OK on the Publish Cloud Service Dialog

 

image

13. Visual studio will upload your application to the cloud

image

While your application is in staging the only problem might be that the published URL changed and that might be conflictive for your ServiceReferences.ClientConfig.

Once your application is on Staging you can switch it to Production and your are ready for business.

Exposing C# Classes thru Interop

23. June 2010 05:38 by Mrojas in General  //  Tags: , , , , , , , , ,   //   Comments (0)

Either if you migrate your application from VB6 to C# or if you develop a new application in C# something you end up with cases where you need to use your classes in legacy apps. Some of them could have been written in VB6 or could even be VBA macros in Excel applications.

Exposing your .NET classes can be sometimes very easy (you can think is just a matter of putting a ComVisible tag) but in other occasions is not that simple. Specially if your legacy application is using a lot of Late Bound calls like in VBA, so you must make sure that the COM information that you are exposing for your class is exactly what you really want and need.

OK. So I will provide some guidelines or some steps you should follow to provide a consistent COM interface for your .NET Code.

1. First you have to add the [ComVisible(true)]  attribute. Don’t think that’s all. Even if in some cases that is enough is better if you take an strict control of want is being generated for your class. Ok Let’s use the following class as an example:

using System;
using System.Runtime.InteropServices;

namespace InteropExamples
{
    [ComVisible(true)]
    public class MyVerySimpleClass 
    {
        public Class2 CreateANewClass()
        {  return new Class2()     }

        public int GetMyLuckyNumber() { return 15; }
    }
public class Class2 { 
  }
}

// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: <could not determine filename>
[
  uuid(370E4AD4-073B-4984-8C7D-5ED027F7B1CA),
  version(1.0)
]
library ClassLibrary1
{
    // TLib :     // TLib : mscorlib.dll : {BED7F4EA-1A96-11D2-8F08-00A0C9A6186D}
    importlib("mscorlib.tlb");
    // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
    importlib("stdole2.tlb");

    // Forward declare all types defined in this typelib
    interface _MyVerySimpleClass;

    [
      uuid(E03CCE68-2D55-3576-9DB6-019AAA667A5D),
      version(1.0),
        custom({0F21F359-AB84-41E8-9A78-36D110E6D2F9}, "InteropExamples.MyVerySimpleClass")
    ]
    coclass MyVerySimpleClass {
        [default] interface _MyVerySimpleClass;
        interface _Object;
    };

    [
      odl,
      uuid(D18BEEE1-4425-3AC7-891E-807EC2283731),
      hidden,
      dual,
      oleautomation,
        custom({0F21F359-AB84-41E8-9A78-36D110E6D2F9}, "InteropExamples.MyVerySimpleClass")   

    ]
    interface _MyVerySimpleClass : IDispatch {
    };
};

In this case your class will be expose using all defaults. That is, a progId that will be the <AssemblyName>.ClassName an interface _<ClassName> is generated and the class is exposed only for IDispatch, which would not provide class information if you add the tlb reference to a VB6 or VBA project.

And if you run this code in VB6 you will have a problem like type mismatch when you try to use the method x.CreateAClass because it is returning an object that is not exposed thru COM.

Private Sub Command1_Click()
    Dim x As Object
    Set x = CreateObject("InteropExamples.MyVerySimpleClass")
    MsgBox x.GetMyLuckyNumber
    MsgBox x.CreateAClass
End Sub

So my recommendation is to make explicit what you want to expose. Maybe you only need some of the methods to be exposed. Well that is step two.

2. Define a public, ComVisible(true) interface that will define the methods that you want to be exposed thru COM. Sometimes it is better to implement the interface explicitly. I even recommend using partial classes so you isolate the COM stuff from your normal class. If you class is very simple you can leave all COM stuff there.

    //It is better to have an interface, because
    //you are completely sure what you are exposing or not
    [ComVisible(true)]
    public interface _MyVerySimpleClass
    {
        int GetMyLuckyNumber();
    }

3. (Recommedation) This is not an obligatory step but I recommend using partial classes.

    //Using partial classes allow you to separate all the
    //COM plumbing and leave your .NET implementation simple
    public partial class MyVerySimpleClass 
    {
        public Class2 CreateAClass()
        {
            return new Class2();
        }

        public int GetMyLuckyNumber() { return 15; }
    }

3. Make sure your partial class has the following attributes:

[ComVisible(true)] <—This is obvious because you want to use your class in COM

[ClassInterface(ClassInterfaceType.None)] <—This is because your want to take charge or what will be generated in your Typelib (tlb)

[ComDefaultInterface(typeof(_MyVerySimpleClass))] <—This is to indicate the interface that holds your COM visible methods.

[ProgId("InteropExamples.MyVerySimpleClass")] <—To establish which will be the progId not have a generated one
[Guid("{029D468C-8BE6-498f-8A57-3B4B0306BA41}")] <—this is important specially if you are trying to accomplish binary compatibility

Optionally add this attribute [IDispatchImpl(IDispatchImplType.CompatibleImpl)] this is currently marked as an obsolete attribute but it still works and I have found scenarios, specially in some VBA applications where you need this attribute in order to make some late bound calls.

4. And Explicitly implement the interface methods. This is important because some of the return values or arguments might need convertions. For example what can you do if your method returns a DataSet and your Excel VBA script is expecting something like a Recordset (more on this on other posts).

So now you will have a class like:

    //Using partial classes allow you to separate all the
    //COM plumbing and leave your .NET implementation simple
    public partial class MyVerySimpleClass
    {
        public Class2 CreateAClass()
        {
            return new Class2();
        }

        public int GetMyLuckyNumber() { return 15; }
    }

    //It is better to have an interface, because
    //you are completely sure what you are exposing or not
    [ComVisible(true)]
    public interface _MyVerySimpleClass
    {
        int GetMyLuckyNumber();
    }

    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)] //This is to make sure that no automatic generation of COM methods is done
    [ComDefaultInterface(typeof(_MyVerySimpleClass))] //This to explicitly establish which is the default interface
    [ProgId("InteropExamples.MyVerySimpleClass")]
    [Guid("{029D468C-8BE6-498f-8A57-3B4B0306BA41}")]
    [IDispatchImpl(IDispatchImplType.CompatibleImpl)]
    partial class MyVerySimpleClass : _MyVerySimpleClass
    {
    
        #region _MyVerySimpleClass Members
        //Explicit implementation is better because it avoids messing your .NET
        //class specification. Sometimes when you expose thru COM you can have problem with
        //methods overloads. For example you have to have the same method name but differente 
        //return type. Or you have a collition with an existing member.
        int _MyVerySimpleClass.GetMyLuckyNumber()
        {
            return GetMyLuckyNumber();
        }

        #endregion
    }

And your TLB is now explicit and exposes ONLY what you really really want.

// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: <could not determine filename>

[
  uuid(370E4AD4-073B-4984-8C7D-5ED027F7B1CA),
  version(1.0)
]

library ClassLibrary1
{
   // TLib :     // TLib : mscorlib.dll : {BED7F4EA-1A96-11D2-8F08-00A0C9A6186D}
    importlib("mscorlib.tlb");
   // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
    importlib("stdole2.tlb");

    // Forward declare all types defined in this typelib
    interface _MyVerySimpleClass;

    [
      odl,
      uuid(80D00C45-EE10-3D65-A5FF-42AB7D8F8A71),
      version(1.0),
      dual,
      oleautomation,
        custom({0F21F359-AB84-41E8-9A78-36D110E6D2F9}, "InteropExamples._MyVerySimpleClass")   

    ]
    interface _MyVerySimpleClass : IDispatch {
        [id(0x60020000)]
        HRESULT GetMyLuckyNumber([out, retval] long* pRetVal);
    };

    [
      uuid(029D468C-8BE6-498F-8A57-3B4B0306BA41),
      version(1.0),
        custom({0F21F359-AB84-41E8-9A78-36D110E6D2F9}, "InteropExamples.MyVerySimpleClass")
    ]

    coclass MyVerySimpleClass {
        interface _Object;
        [default] interface _MyVerySimpleClass;
    };
};

For more info about BinaryCompatibility see my other posts on Interop.

AutoCAD VBA Migration to VB.NET or C#

AutoCAD 2010 will not be supporting VBA.

Quoting

“If you utilize VBA macros in your work environment, they will no longer work unless the VBA module is installed on your system. “
“When you run a command that requires VBA, a message dialog box will be displayed stating that VBA is no longer installed with AutoCAD and directing you to a website where you can download the VBA module. “

And also you can see that Autodesk states: “Autodesk is evaluating how long VBA will be supported in Autodesk products in the future. Though supported in the AutoCAD 2010-based products, it may or may not be supported in future releases. Therefore, it is strongly recommended that VB developers develop all new code using VB .NET.

VBA does not support 64bit systems in a native way.

But If you want some advice from the VB migration experts or help on your migration project from VBA to VB.NET or C# you can us contact Artinsoft Migration Services.

We build the VB Upgrade Wizard that shipped with Visual Studio and have been doing VB migrations for years.

DataGridView does not show Horizontal scrollbar

16. February 2010 10:25 by Mrojas in General  //  Tags: , , , ,   //   Comments (0)

During a migration from a FlexGrid to a DataGridView, we encountered a situation where the HorizontalScrollBar did not show.

I found many suggestions like setting a MinimumColWidth value for all columns, etc.

But it wasn’t until my friend Jesus added a line like:

 

mygrid.DockStyle = DockStyle.Fill

that the HorizontalScrollBar appear.

It might just be that the grid was too big for form but just for the record this is a possible solution.

Escape characters for SQLLoader

9. February 2010 18:49 by Mrojas in General  //  Tags: , , , ,   //   Comments (0)

 

The LINC/EAE migration tool can automatically generate reports that can be used to extract your data from DMSII to your target database, for example Oracle.
In this scenarios the Oracle SQL Loader tool is used. However you might problems loading the data because the string values can contain the same characters you are using to enclose them.

Let’s see an example, taken from an oracle forum:

C:\ora>type buyer.ctl
LOAD DATA
INFILE 'buyer.data'
truncate into table BUYER
FIELDS TERMINATED BY ',' optionally enclosed by '"' TRAILING NULLCOLS
(
buyer_code,
BUYER_NAME
)
 

And suppose you have data like:

1,"XYZ IND"
2,"ABC"
3,"XYZ ABC"
4,"Your "offspring""
5,"ATUL"

How can you “escape” the enclosing characters. Well I found the answer in another forum:

If two delimiter characters are encountered next to each other, a single occurrence of the delimiter character is used in the data value. For example, 'DON''T' is stored as DON'T. However, if the field consists of just two delimiter characters, its value is null.

So just use something like:

 

1,"XYZ IND"
2,"ABC"
3,"XYZ ABC"
4,"Your ""offspring"""
5,"ATUL"

Easy way to see the Explain Plan in Oracle

3. February 2010 13:07 by Mrojas in   //  Tags: , , , ,   //   Comments (0)

 

Linc\EAE used profiles for their queries. Well the profile information is used by our migration tool to generate indexes.
In Java is easy to intercept all SQL statements used by the translated application and analyze them.

To analyse how a query is executed you have to study its explain plan. For go here an excellent guide on EXPLAIN PLAN.

After you read that page, you will find useful the following function, that will shorten the lines that you have to type to see the explain plan:

create OR REPLACE function  ShowPlan return sys_refcursor
  as
      c_test sys_refcursor;
BEGIN
  open c_test for select 
  substr (lpad(' ', level-1) || operation || ' (' || options || ')',1,30 ) "Operation", 
  object_name "Object"
  from 
  sys.plan_table$ start with id = 0 connect by prior id=parent_id;
  return c_test;
END;
SQL>
explain plan for select * from MY_TABLE
SQL> variable rc refcursor
SQL> exec :rc := testfunc()

PL/SQL procedure successfully completed.

SQL> print rc
Operation                      Object
------------------------------ ------------------------------
SELECT STATEMENT ()
 TABLE ACCESS (FULL)           MY_TABLE

Get Table Owner in Oracle

3. February 2010 12:40 by Mrojas in General  //  Tags: , , , , ,   //   Comments (0)

 

When we migrate from LINC/EAE to Oracle, the migration tool generates an schema an tables form the original ISPECS.
I came across with the problem that I had been playing around with a test database and I didn’t know who was the owner of the table.

Well just as a reminder this is what is needed:

select owner, table_name, tablespace_name   from dba_tables   where table_name='YOUR_TABLE';
This will return something as:
 

OWNER                    TABLE_NAME  TABLESPACE_NAME
------------------------------ ------------------------ ------------------------------
THE_OWNER               MY_TABLE       USERS

Get Exact Text Width C#

15. December 2009 08:13 by Mrojas in   //  Tags: , , , , , , , , ,   //   Comments (0)

 I was recently trying to get the exact width of a string. And I found that the Graphics.MeasureString does not give an exact result.

I finally found Pierre Arnaud

post in Code Project, which gave me a good explaination and solution of what was happening.

You can see in the image Pierre put in his post:

 That Graphics.measurestring will return a size that might be bigger that the actual drawn size, this is due some GDI+ details that he explains in that post.

I really like the second proposed solution:

static public int MeasureDisplayStringWidth(Graphics graphics, string text,Font font)
{
    System.Drawing.StringFormat format  = new System.Drawing.StringFormat ();
    System.Drawing.RectangleF   rect    = new System.Drawing.RectangleF(0, 0,1000, 1000);
    System.Drawing.CharacterRange[] ranges  = { new System.Drawing.CharacterRange(0, text.Length) };
    System.Drawing.Region[]         regions = new System.Drawing.Region[1];

    format.SetMeasurableCharacterRanges (ranges);
    regions = graphics.MeasureCharacterRanges (text, font, rect, format);
    rect    = regions[0].GetBounds (graphics);

    return (int)(rect.Right + 1.0f);
}

 

 

ActiveX Server Migration to .NET

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

 In VB6 ActiveX-EXEs or ActiveX OLE Server where used for several reasons. Sometimes it was performance (because it allowed you to run your code in another process) and sometimes as way to share resources between several applications, like connection information, database connections, mainframe info, etc.

During migration some of this ActiveX-Exes can be migrated as simple Assembly DLLs, but other require more attention. Specially if they have global variables that hold state shared by several programs.

In that is your case what are your options then?

1. Convert those ActiveX-Exes to Windows Services.

This option is simple. You modify your migrated assembly to work as a Windows Service. The easier way to do that is:

a) Start Microsoft Visual Studio 2005\2008

b) Go to File\New…\Project… and Select Windows Service

That will generated code like:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
namespace WindowsService1
{
   public partial class Service1 : ServiceBase
   {
      public Service1()    InitializeComponent();    }
     
protected override void OnStart(string[] args)    {   }
     
protected override void OnStop()    {   }
   }
}

c) Add a reference to the Remoting Assemblies: System.Runtime.Remoting;

d) Modify the previous code:

Add two using statements like:

using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting;

Add a simple event log for tracing:

 

private static EventLog evt = new EventLog(“Application”);
private static string SVC_NAME = “ActiveX Server Example Svc”;

 And modify the OnStart and OnStop methods to look like:

  protected override void OnStart(string[] args)
{
    HttpChannel chnl = new HttpChannel(1234);
   
ChannelServices.RegisterChannel(chnl,true );
   
RemotingConfiguration.RegisterWellKnownServiceType(typeof(MyClass), “MyClass.soap”, WellKnownObjectMode.Singleton);
   evt.WriteEntry(SVC_NAME + ” Started”);

}

protected override void OnStop() { evt.WriteEntry(SVC_NAME +” Stoppped”); }

Also make sure that MyClass extends MarshalByRefClass

2. Convert those ActiveX-Exes using the Artinsoft ActiveX migration helpers.

 Sometimes, you need your migrated application to replicate some of the original ActiveX EXE \OLE DLL VB6 characteristics. For example you need your ActiveX-EXE to start just when the first instance is created and to resemble the VB6 logic for Process creation\destruction.

For that purpose Artinsoft has created some helpers that our migration tool is able to automatically use in the generated code if it detects that this functionality is needed.

The code will then be changed from:

Dim myInstance As New MyProject.MyClass

To the following Helper method:

myInstance = MyProjectFactory.Create< MyProject.MyClass>(myInstance);

 And destroy calls can be changed to the following Helper method:

 myInstance= MyProjectFactory.Dispose<MyProject.MyClass >( myInstance); 

The migration tool will modify your ActiveX-EXEs or OLE Servers to be Windows EXE and the helper will then locate the assembly that contains the desired Class, create an instance and initilize a Remoting channel to the desired classes. Settings as SingleUse and MultiUse are also taken care by the helpers.

3. Other possible alternatives are using WFC and COM+ that I will comment in another post.

 

 

 

 

Continuous Migration VBUC-MS Team System 2005: Configure MS Visual Studio 2005 to use Team System

22. September 2009 08:57 by Mrojas in General  //  Tags: , , , , , , ,   //   Comments (0)

This post will show you the necessary steps to configure Microsoft Visual Studio 2005 to use a Team System Project. In this example we will use a Team Project created to illustrate Continuous Migration with VBUC and MS Team System 2005, called MergeExample.

1. Start Microsoft Visual Studio 2005

2.  Go to the File Menu\Open\Team Project…

image

3. Dialog is presented, where you can choose your Team Foundation Server, and the Team Project to use. For these Continuous Migration example we’ll assume a project called MergeExample.

image

4. The Team Explorer is shown, with your selected project.
Expand the elements for the Team Project you previously selected.

image

5.  We now have to map our local directories to bind them to the
source control system. On the expanded tree, double click on the
Source Control Node

image

6. The Source Code Explorer is shown:

image

7.  Go to the Workspaces dropdown box and select Workspaces…

image

8.  The Manage workspace dialog is shown.
Select the appropiate workspace and click Edit…

image 

9. On the Edit Workspace dialog type a description for your source control and select the source control Folder we had created (for this example it is $/MergeExample) and the directory for your code (for this example it is C:\MergeExample).

image 

 

 

 

 

 

NOTE: if a message box about a pending update is shown, just click ok.

 

Now you have successfully mapped your directories, and you can start setting up your VB6 code for continuous migration

Migration from .NET Framework 1.1

13. August 2009 18:07 by Mrojas in General  //  Tags: , , , , , ,   //   Comments (0)

.NET has been around for quite a while. According Wikipedia it has been around since on 3 April 2003
So now there exist applications developed for .NET Framework 1.0 or 1.1 and people
need to migrate them to Framework 2.0 or Framework 3.5.

It is the general impression that there is not a direct path to 3.5.
As Zain Naboulsi explains in his blog you can go from 1.1 to 2.0 then from 2.0 to 3.5.
And From 2.0 to 3.5 the migration is a no-brainer because, both, 3.0 and 3.5 are based on 2.0.

A good reference also is the post of Peter Laudati on migration from 1.1 to 2.0.
Note: Peter’s post seem to have a broken link to the microsoft document about breaking changes in 2.0.
The correct link is this.

A more recent post by The Moth provides more links to breaking changes documents:

- Design time Breaking Changes in .NET Framework 2.0
- Runtime Breaking Changes in .NET Framework 2.0
- Microsoft .NET Framework 1.1 and 2.0 Compatibility
- Compatibility Testing Scenarios

Going from 1.1 to 2.0 or 3.5 can be just as simple as opening the solution in VS and compile
or it can take a lot of effort. Web Projects then to be more difficult due to several changes in ASP.NET.

So good luck.

Tools?

Well there a lot of static analyisis tools we have used
(some internal, some from Third Parties. I particulary like Understand and NDepend)

Categories