ArtinSoft's Blogs

Software Migration Experts
Welcome to ArtinSoft's Blogs Sign in | Join | Help
in Search

Mauricio Rojas Blog

June 2009 - Posts

  • ColdFusion 8 and JRockIt

    JRockIt is an interesting Java Virtual Machine. I really admire the technology used in it. Well following Mike’s post about Memory Leaks in Coldfusion http://www.schierberl.com/cfblog/index.cfm/2006/10/12/ColdFusion_memoryLeak_profiler I was trying to configure the JRockit JVM to do some profiling on an important application.

    But alas. Time just flies and things have change a lot since Mike wrote that post. So this is basically an update:

    1) JRockit must be downloaded from: http://www.oracle.com/technology/software/products/jrockit/index.html You must accept the license and also have an OTN Account (this is a free process). Download the right version for your platform. I tried the x86 version on my 64 bit server and it didn;t work, so use the version that fits better to your platform. However there is no 64 bit client version of Memory Leak and all the other nice client tools. But dont worry. Download both version 64 and 32 bits versions. You will use the 64 version for your server and the 32 bit version for monitoring.

    2) Stop coldfusion server

    3) Modify the jvm.config file. In my case it was in: C:\ColdFusion8\runtime\bin\jvm.config

    comment out old java.home and add a new line like:
    java.home=C:/Program Files/Java/jrmc-3.1.0-1.6.0/jre

    In the java.args setting, remove parameter –Xbatch (dont know why, it just didnt work)

    add a parameter like:
    -Xmanagement:ssl=false,authenticate=false,autodiscovery=true

    *In my case I also had to disable security in C:\Program files\Java\jrmc-3.1.0-1.6.0\jre\management\management.properties with a line like:

    com.sun.management.jmxremote.authenticate=false

    4) Re start coldfusion

  • DDE in .NET

    Someone recently made me remind an old technology called DDE.

    “Dynamic Data Exchange (DDE) is a technology for communication between multiple applications under Microsoft Windows or OS/2

     

    “The primary function of DDE is to allow Windows applications to share data. For example, a cell in Microsoft Excel could be linked to a value in another application and when the value changed, it would be automatically updated in the Excel spreadsheet. The data communication was established by a simple, three-segment model. Each program was known to DDE by its "application" name. Each application could further organize information by groups known as "topic" and each topic could serve up individual pieces of data as an "item". For example, if a user wanted to pull a value from Microsoft Excel which was contained in a spreadsheet called "Sheet1" in the cell in the first row and first column, the application would be "Excel", the topic "Sheet1" and the item "r1c1".

    Note: In DDE, the application, topic and item are not case-sensitive.”

     

    So in VB6 you can have something like:

     

    Private Sub Form_Load()
    Text1.LinkMode = 0
    Text1.LinkTopic = "Excel|Sheet1"
    Text1.LinkItem = "R1C1"
    Text1.LinkMode = 1
    End Sub

     

     

    How can you do that in .NET. Is it possible in C#? Well I started looking around and found several forums explaining about all the API calls and I was just about to write my own solution when I found NDDE. This project hosted in CodePlex “provides a convenient and easy way to integrate .NET applications with legacy applications that use Dynamic Data Exchange (DDE)” :)

     

    So this is a  nice example of how to do the previous lines in C#:

            //This class provides the infraestructure for DDE comunication
            NDde.Client.DdeClient ddeClient_TextBox1 = null;
    
            private void Form1_Load(object sender, EventArgs e)
            {
                //I initialize the DDEClient object. Application is Excel and Topic is Sheet1. I'm using the 
                //the TextBox as the syncronization object
                ddeClient_TextBox1 = new NDde.Client.DdeClient("Excel", "Sheet1", textBox1);
                //Connect to the DDE Server
                ddeClient_TextBox1.Connect();
                //Start the Advise Loop
                ddeClient_TextBox1.StartAdvise("R1C1", 1, true, 60000);
                //Setup the Advise Method
                ddeClient_TextBox1.Advise += new EventHandler<NDde.Client.DdeAdviseEventArgs>(ddeClient_TextBox1_Advise);
                //Setup a method to Poke the Server for TextBox cahnges
                textBox1.TextChanged += new EventHandler(textBox1_TextChanged);
    
            }
            
            void textBox1_TextChanged(object sender, EventArgs e)
            {
                //Syncronous Poking the server
                ddeClient_TextBox1.Poke("R1C1", textBox1.Text + "\0", 4000);
            }
    
            const string DDE_postFix = "\r\n\0";
            void ddeClient_TextBox1_Advise(object sender, NDde.Client.DdeAdviseEventArgs e)
            {
                //Advise only if needed
                if (e.Text.Length >=DDE_postFix.Length && textBox1.Text + DDE_postFix != e.Text)
                    textBox1.Text = e.Text.Substring(0,e.Text.Length-3);
            }
    NOTE: Remember that you need to download NDDE and add a reference to this library

    This is very good library, you can also set up a lot of Async calls to even improve performance. I have even thought of making an extender as the ToolTip control to add LinkTopic, LinkMode and LinkItem properties for Winforms controls or provide extensions methods to make all the syntax easier, but that is for a future post. Good Luck.

  • VB6 Migration of Property Pages

    How can I migrate property pages? Well that is a common question when migrating VB6 Activex controls.

    Property Pages where commonly used in VB6 to provide a mechanism for your user controls to edit values.

    .NET provides even more mechanisms for editing your control properties.  You can provide an editor for each one of your component properties or you can provide a ComponentEditor for all the component, this is very similar to the VB6 concept.

    In .NET the ComponentEditor can be actived in the designer selecting Properties from the context menu when you right click over the control.

    This is from the MSDN documentation:

    “A component editor is used to edit a component as a whole and can be used to implement a
    user interface similar to that of the property pages. You associate a component editor with a
    component by using the
    EditorAttribute attribute.” From: ComponentEditor Class

    The VBUC does not process out of the box, your PropertyPages, but I developed a tool that can be
    used so the VBUC can help you migrate those property pages. This tool will modify your VB6 project,
    and VB6 PropertyPages source code to make those VB6 PropertyPages look like VB6 UserControls.
    This will allow  the VBUC migration tool to recover some of the VB6 PropertyPages code and appearance
    and with some manual changes you can get your property pages to work again.

    Use the following link to downlaod the tool: DOWNLOAD TOOL

    So these are the steps to migrate a VB6 Project that has Property Pages with the VB6.

    1) Make a backup copy of your source code.

    2) Run the TOOL with your project file. For example if your project file is Project1.vbp then run the tool like this:

    FixPropertyPages Project1.vbp

    This will generate a new VB6 Project file called ModifiedProject1.vbp

    3) Open the VBUC, and migrate the new project file ModifiedProject1.vbp

    4) Open the migrated solution in Visual Studio.

    5) All your property pages will be migrated to .NET UserControls. You might need to go thru some changes to make them completely functional. Remeber to add the [ToolboxItem(false)] to these property pages because they do not need to be visible in your toolbox.

    6) Now, to associate those property pages with your UserControl do this:

    6.1) Add a new code file to your migrated solution. We are going to create a ComponentEditor, that will hold all the pages and associate that to the migrated control. Lets say the control is named Control1 and the property pages are PropertyPage1 and PropertyPage2.
    We will call the ComponentEditor ComponentEditorToAssociatePagesForMyControl.
    In this ComponentEditor we will add an internal class for each PropertyPage. This class will inherit from ComponentEditorPage. We will call this internal classes Page1, and Page2. And we will associate those classes with the ComponentEditorToAssociatePagesForMyControl in the GetComponentEditorPages().
     

    The resulting code will be like:

    C#
    using System.Windows.Forms.Design;
    using WindowsFormsApplication1;
    using System.Drawing;
    using System.ComponentModel;
    [ToolboxItem(false)] 
    public class ComponentEditorToAssociatePagesForMyControl : WindowsFormsComponentEditor
    {
        // Methods
        public override bool EditComponent(ITypeDescriptorContext context, object component)
        {
            return false;
        }
    
        class Page1 : ComponentEditorPage
        {
            // Methods
            public Page1()
            {
                PropertyPage1ForControl1 page1 = new PropertyPage1ForControl1();
                Size mysize = new Size(400, 250);
                this.Size = mysize;
                this.Text = "Page 1 for Control1";
                this.Controls.Add(page1);
            }
            protected override void LoadComponent() { }
            protected override void SaveComponent() { }
        }
    
        class Page2 : ComponentEditorPage
        {
            // Methods
            public Page2()
            {
                PropertyPage2ForControl1 page2 = new PropertyPage2ForControl1();
                Size mysize = new Size(400, 250);
                this.Size = mysize;
                this.Text = "Page 2 for Control1";
                this.Controls.Add(page2);
            }
            protected override void LoadComponent() { }
            protected override void SaveComponent() { }
        }
    
        protected override System.Type[] GetComponentEditorPages()
        {
            return new System.Type[] { typeof(Page1),typeof(Page2) };
        }
    
        protected override int GetInitialComponentEditorPageIndex()
        {
            return 0;
        }
    }

    VB.NET

    <ToolboxItem(False)> _
    Public Class ComponentEditorToAssociatePagesForMyControl
        Inherits WindowsFormsComponentEditor
        ' Methods
        Public Overrides Function EditComponent(ByVal context As ITypeDescriptorContext, ByVal component As Object) As Boolean
            Return False
        End Function
    
        Protected Overrides Function GetComponentEditorPages() As Type()
            Return New Type() { GetType(Page1), GetType(Page2) }
        End Function
    
        Protected Overrides Function GetInitialComponentEditorPageIndex() As Integer
            Return 0
        End Function
    
    
        ' Nested Types
        Private Class Page1
            Inherits ComponentEditorPage
            ' Methods
            Public Sub New()
                Dim page1 As New PropertyPage1ForControl1
                Dim mysize As New Size(400, 250)
                MyBase.Size = mysize
                Me.Text = "Page 1 for Control1"
                MyBase.Controls.Add(page1)
            End Sub
    
            Protected Overrides Sub LoadComponent()
            End Sub
    
            Protected Overrides Sub SaveComponent()
            End Sub
    
        End Class
    
        Private Class Page2
            Inherits ComponentEditorPage
            ' Methods
            Public Sub New()
                Dim page2 As New PropertyPage2ForControl1
                Dim mysize As New Size(400, 250)
                MyBase.Size = mysize
                Me.Text = "Page 2 for Control1"
                MyBase.Controls.Add(page2)
            End Sub
    
            Protected Overrides Sub LoadComponent()
            End Sub
    
            Protected Overrides Sub SaveComponent()
            End Sub
    
        End Class
    End Class
    
     
    

    7) After creating the ComponentEditor you must associate the component Editor to your new component editors. This can be done with something like:

    C# 

    [Editor(typeof(ComponentEditorToAssociatePagesForMyControl), typeof(ComponentEditor))]
    public class Control1 : UserControl
    

    VB.NET

    <Editor(GetType(ComponentEditorToAssociatePagesForMyControl), GetType(ComponentEditor))> _
    Public Class Control1
    
    8)  Now to use this property pages, go to the designer screen and open the context menu and select properties. And editor with your properties pages will appear :)

    9) You still need to write some code for saving the property values that is something you have to add to the LoadComponent and SaveComponent methods of the internal classes in your ComponentEditor (ComponentEditorToAssociatePagesForMyControl in our previous example).

    I hope this helps to get your code faster in .NET. I'm attaching a C# sample if you want to try it out.

  • VB6 TabIndex and C#

    Some time ago Jose Aguilar had blogged about the Interesting Behavior of TabIndex in Migrated Applications. As he explained at the time there are functional differences between the TabIndex behaviour in VB6

     

    If you look at Figure1.

    image

    Figure 1. This image show a VB6 form, the TabIndex values and the way the form navigates when you press Tab.

    If you migrate that form with the VBUC and activate the TabOrder option in View\TabOrder you will see something like:

    image

    As you can see by the 0.1 and 0.3 and 5.4 and 5.2 values. TabOrder in .NET is hierarquical. When you press tab you will navigate to the next control in the container, and when you get to the last in that container then you will switch to the next one in the following container. This is different from the VB6 world when you would have switched from 0.1 to 5.2.

    How can we fix this without a lot of manual corrections. Well you can override the ProcessTabKey method to navigate controls following the tabIndex without taking into account the containers.

    The code you will need to add is:

            /// <summary>
    /// holds a list of controls for tab navigation
    /// </summary>
    List<Control> controls = new List<Control>();
    /// <summary>
    /// Populates the list used for tab navigation
    /// </summary>
    /// <param name="c">Control to use to populate list</param>
    protected void BuildOrder(Control c)
    {
    if (c.TabStop)
    controls.Add(c);
    if (c.Controls.Count > 0)
    {
    foreach (Control child in c.Controls)
    BuildOrder(child);
    }
    }
    /// <summary>
    /// Transversers all form controls to populate a list ordered by TabIndex
    /// that will be used to follow tabindex ignoring containers
    /// </summary>
    protected void BuildOrder()
    {
    if (controls.Count == 0)
    {

    foreach (Control c in this.Controls)
    {
    BuildOrder(c);
    }
    controls.Sort(
    delegate(Control c1, Control c2) { return c1.TabIndex.CompareTo(c2.TabIndex); });
    }
    }
    /// <summary>
    /// Overrides default tabIndex behaviour
    /// </summary>
    /// <param name="forward"></param>
    /// <returns></returns>
    protected override bool ProcessTabKey(bool forward)
    {
    BuildOrder();
    if (ActiveControl != null)
    {
    int index = controls.IndexOf(ActiveControl);
    if (index != -1)
    {
    if (forward)
    controls[(index + 1) % controls.Count].Select();
    else
    controls[index==0?controls.Count-1:index-1].Select();

    return true;
    }

    else
    return false;
    }
    else
    return base.ProcessTabKey(forward);
    }

    After adding this code just run your project and it will fix the tabIndex issues.

  • A Better Visual Studio!

    Recently I discovered in MSDN a great addition, a must to for all C# developers. CodeRush Express.

    This product was build by DevExpress and it just make it perfect your experience with Visual Studio.

     

    For example finding symbols or files, tabbing between references, and more than 20 differente refactorings!!!!

    Take at look at this new extension! It’s a absolutely a must.

This Blog

Syndication

Powered by Community Server (Non-Commercial Edition), by Telligent Systems