During migration to C# or .NET it is easier to keep the same ActiveX.
The VBCompanion does a great work in migrating the ActiveX control using the .NET ActiveX wrappings and fixing all method calls.
Sadly sometimes those ActiveX do not work properly in .NET.
Well we have good news.
Recently my friend Jose David (who we keep bothering because he is now
a Project Manager and now he only programs in MS Excel and MS Project, I added the MS by his request :P) fixed a curious bug
we had with an aplication we migrated from VB6 to C#.
The thing is that the aplication had an ActiveX control with a strange runtime behaviour.
We migrated the application keeping the ActiveX control and in most ocasions it worked ok.
But randomly it started throwing exceptions.
During the testing he discovered that if he repeated the steps slowly the bug did not reproduced.
So his idea was that it was due a garbage collection issue. And SURPRINSINLY he was right :P
He added this:
System.GC.Collect();
System.
GC.WaitForPendingFinalizers();
And the application started to work.
It seems like some of the COM objects needed a little more time for releasing all references :)
Recently we added some support for migrating the IsMissing function to VB.NEt or C#
The thing is. In VB6 the IsMissing Function is TRUE only if you have something like:
Public Sub Foo(Optional str)
Where you dont specify the variable type, or if you have
Public Sub Foo(Optional str as Variant)
And is IsMissing is FALSE for any other case. Including Optional variables whose definition type is not Variant.
So let's see some examples to illustrate the idea:
Example 1:
Public Sub Foo(str, a As Integer, b As Integer, Optional c As Integer)
MsgBox (str & "Foo Is missing a " & IsMissing(a))
MsgBox (str & "Foo Is missing b " & IsMissing(b))
MsgBox (str & "Foo Is missing c " & IsMissing(c))
End Sub
It occurs that IsMissing is really FALSE in all cases. So it is equivalent to:
Public Sub Foo(str, a As Integer, b As Integer, Optional c As Integer)
MsgBox (str & "Foo Is missing a " & false)
MsgBox (str & "Foo Is missing b " & false)
MsgBox (str & "Foo Is missing c " & false)
End Sub
Example 2:
Public Sub Goo(str, a As Integer, b As Integer, Optional c As Object, Optional d As Byte, Optional e)
MsgBox (str & "Goo Is missing a" & IsMissing(a))
MsgBox (str & "Goo Is missing b" & IsMissing(b))
MsgBox (str & "Goo Is missing c" & IsMissing(c))
MsgBox (str & "Goo Is missing d" & IsMissing(d))
MsgBox (str & "Goo Is missing e" & IsMissing(e))
End Sub
All cases EXCEPT "e" are equivalent to FALSE
Public Sub Goo(str, a As Integer, b As Integer, Optional c As Object, Optional d As Byte, Optional e)
MsgBox (str & "Goo Is missing a" & false)
MsgBox (str & "Goo Is missing b" & false)
MsgBox (str & "Goo Is missing c" &false)
MsgBox (str & "Goo Is missing d" & false)
MsgBox (str & "Goo Is missing e" & IsMissing(e))
End Sub
So if you are migrating your VB6 Code to C# put attention to these little details it can save you a lot of time.And remember that this is just one feature of VBCompanion tool ;)
AJAX applications are great
Their coolness factor is high, and your clients
will be trilled by the new interactivity of your pages
But as a developer when you have a problem with
AJAX it could be hard to track. Because there is
a lot going on behind the scenes
Some of our costumers migrate their ASP applications to
to ASP.NET and it's natural that they want
some AJAX in it.
So I found a GREAT GREAT application for AJAX debugging
It's called fiddler. I cannot describe it all for you so go its site and watch the videos
The tool is just amazing :)
It really can see everything that the browser
receives and sends and more.
A definitive must
Fiddler
One of my purposes for this year was to start
using more the MSBuild
Saldly I'm still not as good on it as I expected
This link provided some interetings points
MS Build and VS
Recently a friend at work had a problem querying a SQL server that indicated
that the column name was wrong.
The only thing wrong was the the case. For example he had COLUMN1 instead of
Column1. I had never seen that problem in SQLServer.
I had seed that in Sybase but not in SQLServer. He solved that by changing the
database collating sequence to something like this:
alter database database1 collate
SQL_Latin1_General_CP1_CI_AI
the CI in the collating indicates Case Insensitive
For more information on SQL Server collations check:
http://msdn2.microsoft.com/en-us/library/aa258233(SQL.80).aspx
And you determine your current database collation use a code like this:
USE
yourdb>
GO
print
'My
database ['
+
db_name()
+
']
collation is: '
+
cast(
DATABASEPROPERTYEX
(
db_name(),
N'Collation'
)
as
varchar(128)
)
print
'My tempdb
database collation is: '
+
cast(
DATABASEPROPERTYEX
(
'tempdb',
N'Collation'
)
as
varchar(128)
)
A simple way of getting the GUID from an exe, dll, ocx, tlb is using the
TLBINF32.dll
This file is in the system path and it must be registered
(Remember to use regsvr32 if you haven't registered).
TLI.
TLIApplicationClass
a = new TLI.TLIApplicationClass();
try
{
TLI.TypeLibInfo
inf = a.TypeLibInfoFromFile(@"c:\windows\system32\MSHFLXGD.OCX");
MessageBox.Show(
"TypeLibrary Name " +
inf.Name + "\r\n" +
//name of (Type Library)
"Tlb ID " + inf.GUID
+ "\r\n" + // GUID
for Library
"LCID " + inf.LCID +
"\r\n" + //
Language / Country
"Major Version "+
inf.MajorVersion + "\r\n" +
// Major Version
"Minor Version "+
inf.MinorVersion); // Minor Version
for (short
i = 1; i < inf.TypeInfoCount; i++)
{
TLI.TypeInfo inf2 = inf.TypeInfos[i];
MessageBox.Show("CLSID
" + inf2.Name + " - " + inf2.GUID,i +
" of " +
inf.TypeInfoCount);
}
}
catch (Exception
ee)
{
MessageBox.Show("No
guid");
}
Microsoft recently published the
MTPS Content Service
In brief, the MTPS Content Services are a set of
web services for exposing the content in
Microsoft/TechNet Publishing System (MTPS).
And Craig Andera, has develop a swift nice tool
called
msdnman that you use from the command line to
get information from the MSDN
Also I recommend you to see this
cool video of a Human LCD that Hugo sent me
I was trying to compile a C++ Project in Visual Studio
and this project has a post-build step that executes
some batch statements.
And succendly from one day to the other the project failed
and the only message I had was
The input line is too long
After some googling I found that this error is displayed
when the command line in the command prompt
exceeds the maximum number of characters.
(Something quite obvious jeje)
The bottom line was that recenlty I had installed
some software and my PATH variable became TOO long
I fixed it by creating a new environment variable
called EXTRA_PATH where I put some references to
Some big paths and then changed my PATH variable
replacing all those long variables for
%EXTRA_PATH%.
And problem solved!
If you ever had any problems while migrating from VB6 Printer Object or the
PrintForm functionality
we have goods news for you the Microsoft Visual Basic 2005 Power Pack 2.0.
Our version of the Visual Basic Companion already provides and extended
migration of the Printer Object,
and we're now updating it to use this new implementation. This Printer
Compatibility Library makes it a
breeze to migrate Printer Functionality.
This is the description of the PowerPack:
"The new Line and Shape controls included in this version of the Visual
Basic 2005 Power Packs are
a set of three graphical controls that enable you to draw lines, ovals, and
rectangles on forms and
containers at design time making it much easier to enhance the look of your user
interface.
These new shape controls also provide events such as click and double-click
allowing developers
to respond and interact with end users.
The Printer Compatibility Library allows projects that used the Printer and
Printers Collection in Visual Basic 6.0
to be upgraded without having to re-write your printing logic. By simply
adding a reference to the library, declaring a
Printer and making a few minor syntax changes, your project will be able to
print using the Printers collection
and Printer object as it did in Visual Basic 6.0. This version adds a new Write
method to the Printer object which
allows you to print text without a forced carriage return similar to the
semicolon syntax used by Print method in Visual Basic 6.0.
The PrintForm component is designed to bring back the ability to easily print a
Windows Form.
With this the new PrintForm component you can once again layout the Windows Form
exactly as
you want it and allow your users to print the form as a quick report."
You can download the PowerPack from
here
NOTE: there's is another link that only includes the Printer Library but MS
recommends to download the PowerPack
because minor upgrades and fixes will be done on the PowerPack distribution
Every SERIOUS VB6 application, ended up requiring
that you import some functionality from the windows API or another DLL.
However if you were looking for a .NET equivalent and
google did not take you to the right page,
there is a document (a little old I might say)
called
Microsoft Win32 to Microsoft .NET Framework API Map
I remember a couple of other pages that were even more complete,
but right know I can only remember
http://pinvoke.net that gives some info about APIs
In the VB world previous to .NET a concept you probably had to deal with was
TWIPS.
What were Twips? Well if you do not remember those happy VB6 times, let me
refresh your memory:
Twips are screen-independent units to ensure that the proportion of screen
elements are the same on all display systems.
A twip is defined as being 1/1440 of an inch.
A Pixel is a screen-dependent unit, standing for 'picture element'.
A pixel is a dot that represents the smallest graphical measurement on a screen.
In .NET everything is pixels. So if you migrated something from VB6 using the
Upgrade Wizard you might found several expressions like:
VB6.TwipsToPixelsX(ctrl.Left)
or VB6.PixelsToTwipsY(ctrl.Height)
There is an X and a Y version of this function, because the conversion factor
is not the same for both axis.
Sadly you can even found some expressions like:
VB6.TwipsToPixelsX(VB6.PixelsToTwipsX(ctrl.Left))
In a strict sense there could be minor differences because of the conversion
factors. But in it seams that things like that can be removed because all
controls Bound properties like Left, Top, Bottom, Right are in pixels. So why
will you convert your pixels units to Twips units to then convert them back to
Pixels if they where already in Pixels????
Also you can find something like:
VB6.TwipsToPixelsX(ctrl.Left + ctrl.Width + 30)
which should be something
like:
ctrl.Left + ctrl.Width + VB6.TwipsToPixelsX(30)
If you have an application migrated with the Upgrade Wizard you can use some
regular expressions to improve those expressions. If the conversion is something
like:
VB6.TwipsToPixelsY(VB6.PixelsToTwipsX(ctrl.Left))
then be careful because
conversion factor might produce a different value, due to the change of axis.
jeje Or you can uset the VBCompanion, the extensible version of the Upgrade
Wizard!!!
.NET has a more strict typing than VB6
So you must check in some circumstances if your object implements an interface
or not.
So I had used the as and is operators in C# but I did not know
how to do that.
I did I little research and I discovered some things about casting operators for
VB.NET
Operator |
Example |
Observations |
CType |
Dim testNumber
As Long
= 1000
' The following line of code sets testNewType
to 1000.0.
Dim testNewType
As Single
= CType(testNumber, Single)
|
Throws InvalidCastException or OverflowException It could
be less eficient due to VB.Net helper routines.
This is a Narrowing and Widening operator.
It can be overloaded
Public
Structure digit
Private dig
As Byte
Public
Sub New(ByVal
b As Byte)
If
(b OrElse b > 9)
Then Throw
New _
System.ArgumentException("Argument outside
range for Byte")
Me.dig
= b
End
Sub
Public
Shared Widening Operator CType(ByVal
d As digit)
As Byte
Return
d.dig
End Operator
Public
Shared Narrowing Operator CType(ByVal
b As Byte)
As digit
Return
New digit(b)
End Operator
End Structure
|
DirectCast |
Dim f
As New
System.Windows.Forms.Form
Dim c As
System.Windows.Forms.Control
' The following conversion succeeds.
c = DirectCast(f,
System.Windows.Forms.Control)
|
Throws InvalidCastException. Is more
efficient than CType because it does not depend on the Visual
Basic helper runtime functions. It can even detect some errors as
invalid casts during compile time
However it requires a relationship of inheritance of implementation
For example:
Dim q As
Object = 2.37
Dim i As
Integer = CType(q,
Integer)
' The following conversion fails at run time
Dim j As
Integer =
DirectCast(q, Integer)
The run-time type of q is Double. CType
succeeds because Double can be converted to Integer.
However, the first DirectCast fails at run time because the
run-time type of Double has no inheritance relationship with
Integer, even though a conversion exists
|
TryCast |
Dim
obj As MyType = TryCast(obj, MyType)
If obj
Is Nothing
Then
' Object could not be cast
Else
' Object was casted
End If |
Throws no exceptions. |
All this information has been taken from the MSDN site. This is just a quick
summary. For more information see:
Type Conversion Functions
Conversion Functions (Visual Basic)
Widening and Narrowing Conversions
Implicit and Explicit Conversions
This is a nostalgic note. Someone asked me, "hey, how do you make a fixed len
string in VB6?"
As the computer geek that I am, that the kind of questions I like to be able to
answer.
These are important questions like all those questions from the 80's rally:
The name of all the original thundercats...
The planet where Luck Skywalker went to learn with Yoda...
Which Star Trek character appear in ALL the episodes (yes it is Spock, Kirk is
not in all of them)
Well, the thing is to define a fixed len string in VB6 you do something like:
Dim aString As String * 10
If you do something like:
aString = "Mau" ' aString ==> "Mau "
That's all
Fixed length strings are automatically filled with spaces to pad them to their
fixed-length. How do you get rid of the extra spaces? Duh!!! with RTrim$ don't
you remember
When a variable like aString is declared, it will be filled with Null characters
until it is used.
And yes functions (RTrim$, LTrim$, and Mid$) will not trim Null characters, so
be sure to assign it with an empty string "" immediately.
Ahh! and by the way when you translate that to .NET, .NET does not have a fixed
len string so the easiest thing to do is use:
Microsoft.VisualBasic.Compatibility.VB6.FixedLengthString.
[C#]
using Microsoft.VisualBasic.Compatibility;
...
void foo()
{
VB6.FixedLengthString aString = VB6.FixedLengthString(10, "Mau");
}
As any geek I live frustrated by the lack of good tools in Windows.
Notepad, and Paint are just a couple of examples.
I was just dreaming for a nice, light replacement for those applications.
Well, recently somebody wrote a nice page with amazing freeware that you can use:
Amazing Tools
Localize a VB6 application can be cumbersome, specially if it was not even originally planned to be localized.
Nowadays is common that you're clients might demand support for different languages.
While a localization task is still difficult, we have found excellent results performing it during a VB Migration.
Our tools allow us to easily externalize all your strings. After that the traslation task becomes easy, and you can even use the help
of nice projets like
Automatically Translate your .NET resource files with Google Translate
These project extends the VB and C# languages with query,
set and transforms operations. It adds a native syntax for those operations.
The idea of the LINQ project is to make data manipulation
part of the language constructs. Lets see these VB examples for LINQ:
The following examples
associates the Customer class to the Customer table. Just adding the Column Tag
before a field, maps it to a table column.
<Table(Name:="Customers")>
_
Public Class Customer
<Column(Id:=True)>
_
Public
CustomerID As String
…
<Column()> _
Public City As String
…
End Class
To
access the database you do something like:
'
DataContext takes a connection string
Dim db As
DataContext = _
New
DataContext("c:\...\northwnd.mdf")
'Get a typed table to
run queries
Dim Customers As
Table(Of Customer) = db.GetTable(Of Customer)()
'Query for customers from London
Dim q = _
From
c In Customers _
Where
c.City = "London" _
Select c
For Each cust In q
Console.WriteLine("id=" & Customer.CustomerID
& _
",
City=" & Customer.City)
Next
You just create a
DataContext and create typed object that will relate dot the relational tables.
I think this is awesome!!
It is even nicer if you
create a strongly typed DataContext
Partial Public Class Northwind
Inherits DataContext
Public
Customers As Table(Of
Customer)
Public
Orders as Table(Of
Order)
Public Sub New(connection As String)
MyBase.New(connection)
Your
code gets cleaner like the following:
Dim db As New
Northwind("c:\...\northwnd.mdf")
Dim q = _
From c In db.Customers _
Where
c.City = "London" _
Select
c
For Each cust In q
Console.WriteLine("id=" & Customer.CustomerID
& _
",
City=" & Customer.City)
Next
These project will start a
lot of exciting posibilities. I recommed you have a look at’: http://msdn.microsoft.com/data/ref/linq/
Ok enough theory. To start using the internationalization
stuff lets start with a simple Form.
Open the Visual
Studio IDE. And Start a Windows Forms project. And then create a simple Form.
Add some labels and buttons and set their captions. Once you do that and finish
the initial creation of the form, go to the properties pane and change the
Localizable property to true and
assign the desired value in the Language property. The Visual Studio designer
will save the changes in additional resource files whose names will look like
<FormName>.<culture>.resx
Once you finish the texts, sizes, positions for the first
culture and save it. The IDE creates the resource file for that culture. If you
want to create a resource file for another language just change the Form
property and assign the text for this new language.
You can not only assign personalized translations for each
region but also the position and size of components. This is useful because in
some languages the buttons might need to be bigger because the labels could be
bigger.
All this work is supported by the .NET resource managers. System.Resources.ResourceManager class.
I recommend you also using String Resource Tools like the
ones at: http://www.codeplex.com/ResourceRefactoring
These tools makes it even easier the task of moving all your
strings to resource files:
Recently I was asked by some fellows some help to make a new
version of their VB6 application in Spanish, but at the end we end up migrating
the application to VB.Net and taking advantage of the .NET internationalization
features.
VB6 did not provided and out-of-box support for multiple
cultures, but the .NET framework provides the developer with utilities to
create applications that allow users in multiple regions use their applications
according to their “Culture”.
The .Net Framework is able to handle different cultures.
These “cultures” are used to localize certain aspects of the application for
particular geographic zones.
When an application is not created with any cultural
considerations it is said to use a Neutral
Culture. It implies that independent of the machine configuration it will
behave and display components in the same way.
The Culture is assigned automactically using the machine
settings or it can be altered programmatically. You can use the property
System.Globalization.CultureInfo.CurrentUICulture for that purpose.
Cultures have two elements: language and region. For example
for Argentina where Spanish
is spoken la culture will be es-AR (es is for Spanish: ESpañol and AR for Argentina)
If no information is found at all for an language then the
neutral culture is used.
The information for user display is handler in assemblies
usually called “satellite assemblies” which are loaded depending on the culture
of the environment where the application is executed.
This is a very controversial topic. Recently I have seen several blogs that state that the VB6 Programmers are moving to other platforms like PHP or Java instead of VB.NET
For example see:
Number of VB
Developerts Declining in US
By
Steve Graegert
“They’re also leaving VB.NET; which is down by 26%. This means Java
now holds the market penetration lead at 45% (with developers using Java during
some portion of their time), followed by C/C++ at 40%, and C# at 32%.”
I also remember an Article I read in 2005 in JDJ (Java Developers Journal) that expressed that C# was a language created similar to C++ to aid the C++ programmers move to the .NET Framework, argument that I do not share.
I have no evidence but I do not feel that it is that way. I'm am a Java Developer too. And both platforms have their merits. C# is a nice language, very similar to Java and C++ no doubt but it deserves its own place. Visual Studio has still a path to follow. But VS2005 provides some useful refactorings and the incredibly awaited feature that allows you to edit the code that you're running :)
Maybe the 1.0 and 1.1 frameworks were not enterprise ready, but 2.0 and 3.0 frameworks are an excellent improvent.
Java as well had to go thru a lot of JDK releases. They have just released the 1.6 and what about the J2EE releases, the Java Enterprise Beans fiasco. You can confirm that by looking at the rise of POJO (Plain Old Java Object) frameworks like spring.
In general everything requires time to grow. I think that Java has been more time in the market and it has finally provided mechanisms that allow the development of enterprise services "easier" and it is giving it momentum.
.NET components industry is common, there are lots of components and somethings are easier. So I'll wait some time, maybe a couple of year to really find out which is the hotter platform.