ArtinSoft's Blogs

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

Mauricio Rojas Blog

  • ActiveX Controls in .NET and the Enabled bug

    We found and interesting bug during a migration. The issue was that when there was an iteration through the controls in the forms, and you set the Enabled property, the property didn't get set.

    After some research my friend Olman found this workaroung

     

    foreach(Control c in Controls)

      ctrl.Enabled = true;
      if (ctrl is AxHost) ((AxHost)ctrl).Enabled = true;
    }

  • Install Assembly in GAC with C#

     

    Do you want to create a program to install your assembly in the GAC using C#. Well if you had that requirement or you are just curious, here is how.

    I read these three articles:

    Demystifying the .NET Global Assembly Cache

    GAC API Interface 

    Undocumented Fusion

    What I wanted just a straight answer of how to do it. Well here is how:

     

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.GAC;
    //// Artinsoft
    //// Author: Mauricio Rojas orellabac@gmail.com mrojas@artinsoft.com
    //// This program uses the undocumented GAC API to perform a simple install of an assembly in the GAC
    namespace AddAssemblyToGAC
    {
        class Program
        {
            static void Main(string[] args)
            {
                // Create an FUSION_INSTALL_REFERENCE struct and fill it with data
                FUSION_INSTALL_REFERENCE[] installReference = new FUSION_INSTALL_REFERENCE[1];
                installReference[0].dwFlags = 0;
                // Using opaque scheme here
                installReference[0].guidScheme = System.GAC.AssemblyCache.FUSION_REFCOUNT_OPAQUE_STRING_GUID;
                installReference[0].szIdentifier = "My Pretty Aplication Identifier";
                installReference[0].szNonCannonicalData= "My other info";
     
                // Get an IAssemblyCache interface
     
                IAssemblyCache pCache = AssemblyCache.CreateAssemblyCache();
                String AssemblyFilePath = args[0];
     
                if (!System.IO.File.Exists(AssemblyFilePath))
                {
                    Console.WriteLine("Hey! Please use a valid path to an assembly, assembly was not found!");
                }
                int result = pCache.InstallAssembly(0, AssemblyFilePath,installReference);
     
                Console.WriteLine("Process returned " + result);
                Console.WriteLine("Done!");
     
            }
     
        }
    }

    And here's the complete source code for this application: DOWNLOAD SOURCE CODE AND BINARIES

  • Useful MSBuild Custom Tasks

    I present here the implementation of some useful tasks
    In Artinsoft we perform massive migrations of VB6 code to VB.Net
    and C#.

    And sometimes after migration there are customizations to be
    performed on the code, to add new functionality or to set certain new
    properties.

     The idea was to provide a couple of very simple and puntual MSBuildTask
     to illustrate how easy it is to create custom tasks and to provide a starting
     point to create new one.

     You can freely use this code, just keep this comments and remember this is just
     a sample code. There are not warranties. ;) And i made it a rush I know it could have
     been written better

     Artinsoft
     mrojas@artinsoft.com
     

    The implemented tasks are:

    RemoveCOMReference 
     Removes COMReferences from your project. COM references are for when you are using things thru Interop
    FixOutputPath 
     Resets the output paths to bin\Release and bin\Debug
    AddProjectReference Add a reference to another project. A nice feature is that it generates RelativePaths the way Visual Studio does
    AddSimpleReference Add a reference to a very simple references like the ones you add when you click Add Reference and add System.EnterpriseServices
    ChangeCurrentBuildSetting This can be used for a lot of things.

    For example to turn on or off the RegisterForComInterop setting

    To set conditional compilation variables

    To set debug info to pdbonly

    The sky is the limit jeje

    The following is a sample project file

    <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <!-- make sure that the Assembly is in a place where msbuild can find it, a simple way is just to put it 
    in the same directory of your .proj file -->
    <UsingTask TaskName="SomeUsefulTasks.MSBuild.RemoveCOMReference"    
      AssemblyFile="SomeUsefulTasks.dll"/> 
    <UsingTask TaskName="SomeUsefulTasks.MSBuild.FixOutputPath"         
      AssemblyFile="SomeUsefulTasks.dll"/> 
    <UsingTask TaskName="SomeUsefulTasks.MSBuild.AddProjectReference"   
      AssemblyFile="SomeUsefulTasks.dll"/> 
    <UsingTask TaskName="SomeUsefulTasks.MSBuild.AddSimpleReference"    
      AssemblyFile="SomeUsefulTasks.dll"/> 
    <UsingTask TaskName="SomeUsefulTasks.MSBuild.ChangeProjectBuildSetting"    
      AssemblyFile="SomeUsefulTasks.dll"/> 
     
       <ItemGroup>
        <VSProjects Include="$(Start)\**\*.*proj" />
      </ItemGroup>
     
    <!--
    Run with 
    MSBUILD SampleProject.proj /target:COMReference /p:Start="C:\MyCode"
    -->
      <Target Name="COMReference">
        <RemoveCOMReference SourceFiles="@(VSProjects)" ComReferenceName="MSXML2" />
      </Target> 
      
      
    <!-- 
    Adds a project reference  
    Run with 
    MSBUILD SampleProject.proj /target:AddProjectReference /p:Start="C:\MyCode" /p:ProjectPath="C:\MyCode\MyNewSuperProject\Project1.csproj"
    -->
       <Target Name="AddProjectReference">
          <AddProjectReference SourceFiles="@(VSProjects)"  AbsolutePathToProject="$(ProjectPath)"/>
       </Target> 
       
       
    <!-- 
    Adds a reference to a standard assembly 
    Run with 
    MSBUILD SampleProject.proj /target:AddSimpleReference /p:Start="C:\MyCode" /p:Reference="System.EnterpriseServices"   
    -->
    <Target Name="AddSimpleReference">
          <AddSimpleReference SourceFiles="@(VSProjects)" Reference="$(Reference)" />
    </Target> 
     
      
    <!-- 
    Resets the OutputPaths to .\bin\Debug and .\bin\Release 
    Run with 
    MSBUILD SampleProject.proj /target:FixOutput /p:Start="C:\MyCode" /p:Reference="System.EnterpriseServices"   
    -->
    <Target Name="FixOutput">
        <FixOutputPath SourceFiles="@(VSProjects)"  />
    </Target> 
      
    <!-- 
    Adds a reference to a standard assembly 
    There are several options here for example to set the project debug info to pdb-only do this:
    Run with 
    MSBUILD SampleProject.proj /target:ChangeSettingToPDBOnly /p:Start="C:\MyCode" 
    Or run with 
    MSBUILD SampleProject.proj /target:ChangeSettingAddAConstant /p:Start="C:\MyCode" 
    Or run with 
    MSBUILD SampleProject.proj /target:SettingComInterop /p:Start="C:\MyCode" 
    -->
     
    <Target Name="ChangeSettingToPDBOnly">
          <ChangeProjectBuildSetting 
              SourceFiles="@(VSProjects)" 
              ConfigurationType="All" 
              Setting="DebugType" 
              NewValue="pdbonly" />
    </Target> 
       
    <Target Name="ChangeSettingAddAConstant">
          <ChangeProjectBuildSetting 
              SourceFiles="@(VSProjects)" 
              ConfigurationType="All" 
              Setting="DefineConstants" 
              NewValue="MYNEWVAL" 
              Add="True"/>
    </Target> 
     
     
    <Target Name="SettingComInterop">
          <ChangeProjectBuildSetting 
              SourceFiles="@(VSProjects)" 
              ConfigurationType="All" 
              Setting="RegisterForComInterop" 
             NewValue="true" />
    </Target> 
     
      
    </Project>

    DOWNLOAD CODE AND BINARIES

  • Get Relative Path

    I had the requirement of creating a MSBuild custom task that opens a .csproj
    adds a reference to another project.

    The problem I faced is that references in VisualStudio are generated as relative paths,
    so I needed something to help me generate relative paths.

    After some Googleing I finally found this code. It was in a long forum discussion
    and was posted by a guy named something like Marcin Grzabski. And here it is for posterity.

            private static string EvaluateRelativePath(string mainDirPath, string absoluteFilePath)
            {
                string[]
                firstPathParts = 
                 mainDirPath.Trim(Path.DirectorySeparatorChar).Split(Path.DirectorySeparatorChar);
                string[]
                secondPathParts = 
                 absoluteFilePath.Trim(Path.DirectorySeparatorChar).Split(Path.DirectorySeparatorChar);
     
                int sameCounter = 0;
                for (int i = 0; i < Math.Min(firstPathParts.Length,secondPathParts.Length); i++)
                {
                    if (
                    !firstPathParts[i].ToLower().Equals(secondPathParts[i].ToLower()))
                    {
                        break;
                    }
                    sameCounter++;
                }
     
                if (sameCounter == 0)
                {
                    return absoluteFilePath;
                }
     
                string newPath = String.Empty;
                for (int i = sameCounter; i < firstPathParts.Length; i++)
                {
                    if (i > sameCounter)
                    {
                        newPath += Path.DirectorySeparatorChar;
                    }
                    newPath += "..";
                }
                if (newPath.Length == 0)
                {
                    newPath = ".";
                }
                for (int i = sameCounter; i < secondPathParts.Length; i++)
                {
                    newPath += Path.DirectorySeparatorChar;
                    newPath += secondPathParts[i];
                }
                return newPath;
            }

    And to use is just do somelines like:

     

                String test = EvaluateRelativePath(@"E:\Source_Code\Code\ProjectsGroup1\Project1", @"E:\Source_Code\Code\ProjecstGroup2\Project2");
     
    //This will genearate something like ..\..\ProjectGroup2\Project2
  • Pretty Printers / Format Code / for C# VB.NET

    In my past life I spent a few eons writing Java code. And it wasn't bad. We had nice tools like Jalopy! that allowed us to have
    code in a very standard way.

    And I missed that. I've been looking around for something similar but I havent found anything like that :(

    Until I found a great post from Chris Eargle, he improved the original solution from Kelvinpinch

    Well here's the code.

    Public Sub FormatSolution()
    Dim sol As Solution = DTE.Solution
    For i As Integer = 1 To sol.Projects.Count
    FormatProject(sol.Projects.Item(i))
    Next
    End Sub 
    Private Sub FormatProject(ByVal proj as Project)
         For i As Integer = 1 To proj.ProjectItems.Count
    FormatProjectItem(proj.ProjectItems.Item(i))
    Next
    End Sub
     
    Private Sub FormatProjectItem(ByVal projectItem As ProjectItem)
         If projectItem.Kind = Constants.vsProjectItemKindPhysicalFile Then
              If projectItem.Name.LastIndexOf(".cs") = projectItem.Name.Length - 3 Then
    Dim window As Window = projectItem.Open(Constants.vsViewKindCode)
    window.Activate()
    projectItem.Document.DTE.ExecuteCommand("Edit.FormatDocument")
    window.Close(vsSaveChanges.vsSaveChangesYes)
    End If
    End If
    'Be sure to format all of the ProjectItems.
    If Not projectItem.ProjectItems Is Nothing Then
    For i As Integer = 1 To projectItem.ProjectItems.Count
    FormatProjectItem(projectItem.ProjectItems.Item(i))
    Next
    End If
    'Format the SubProject if it exists.
         If Not projectItem.SubProject Is Nothing Then
    FormatProject(projectItem.SubProject)
    End If
    End Sub

    To use it perform the following steps:

    •  Go to the VS IDE Tools Option
    • Then Select the Macros option and select Macros IDE...
    • This will open the macros IDE
    • In the Macros IDE navigate to the Module1, and Insert the code

    To run the Macro go to Tools\Macros\Macro Explorer

    And select FormatAll :)

    And last but not least if you want to runit from the command line just do:

    devenv /command "Macros.MyMacros.Module1.FormalAll" MyProject.csproj or

    devenv /command "Macros.MyMacros.Module1.FormalAll" MySol.sln or


     

  • ActiveX exceptions when running in .NET

    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 :)

     

  • IsMissing migration in VB.NET or C#

    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 ;)

     

  • Internet Explorer Runtime Error Do you Wish to Debug?

    Hi, for several months I lived with an extremely unconfortable bug.
    On some pages IE will display an alert dialog indicating 

    Error
    A Runtime Error has occurred.
    Do you wish to Debug?
    Line: blablabla
    Error: blablalba

     Well finally I looked in google and found this: http://support.microsoft.com/kb/822521

    So if anybody had to live with this bug like me, I hope this helps him

     

  • Debugging AJAX

    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
  • MSBuild and Visual Studio

    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
  • Case Sensitive SQL Server

    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) )

     

  • Track Changes in VSS (Visual Source Safe)

    MS VSS (Visual SourceSafe) is not really my preferred Source Control application, but
    sometimes in your company that is what is available and you need to used it to have
    at least some versioning of the code.

    But haven't you had a situation where last week everything worked and
    now everything is broken. And now is up to you to determine what went
    wrong? I have it all the time.
     

    VSS have some search tools but I really do not enjoy using them.
    The Code Project Site provides an excellent tool called VssReporter

    Sample Image - VssReporter.jpg

    Do take a look at it, it makes it more easy to track changes. :)

     

  • Get GUIDs/CLSIDs from Exe, dll, ocx, tlb, etc

    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");
                }

     

     

  • cfgrid or ext grid change column align

    If you are using Coldfusion MX 8 cfgrid or the excelent Ext library and
    you want to change the aligment for the column then a simple way
    to do that is:

    Add an style block like

     .x-grid-col-0 {text-align:center}
     .x-grid-col-1 {text-align:left}
     .x-grid-col-2 {text-align:right}

    And that's all just remember to change  .x-grid-col-n change the n for the column you want to modify.

    Posted Oct 23 2007, 10:42 AM by Mrojas with no comments
    Filed under:
  • Clean Up your Coldfusion application

    Currently I'm working in some tools to clean
    your code, whether it is VB, ASP or Coldfusion.

    Mostly simple tools, but for now if you are a
    ColdFusion Developer I want to recommend a nice
    application called CF Project Cleaner
    This tools lends you a hand so you can
    get rid of unused files. The tool is not perfect. But it is always handy
    to review your code.
More Posts Next page »
Powered by Community Server (Non-Commercial Edition), by Telligent Systems