Page tree
Skip to end of metadata
Go to start of metadata

April 2018.  Great Migrations is pleased to announce a major break through in software re-engineering: a .NET API for automating the gmBasic upgrade engine and accessing the semantic models produced by our unique linguistic compilation technology.

Our goal for this API is to provide a more powerful development platform for building advanced upgrade solutions. The API integrates the features of the Great Migrations Programming Language (gmPL) with Great Migrations Scripting Language (gmSL). The XML-based gmPL has been used for upgrade scripts as well as meta-language and COM interface description files. The C-like gmSL API has been used extensively for dynamic code templates, deep code analysis, and advanced transformations. gmPL and gmSL provide access to an extensive collection of gmBasic commands, events, and operations, but they lack key features of modern development platforms such as interactive debugging and intellisense. The new .NET-based gmslAPI addresses these limitations and provides greater access to the full power of the gmBasic translation engine. Of course, developers building upgrade solutions using gmslAPI can also use other .NET language and framework features allowing more sophisticated upgrade solutions integrating a wider array of information.

The API includes special purposes classes to help you integrate API-based EXE upgrade tasks with gmStudio and customize their behavior.  EXE upgrades tasks can be used in gmStudio using procedures very similar to those for gmPL script tasks. The main difference is the EXE tasks are implemented in C# (or VB.NET) using Visual Studio while gmPL script tasks are implemented in XML using your favorite code editor.

The API is still evolving rapidly so we consider this release a beta, but we have already developed a C# version of the WPF transformation logic using this API and we have used it with C# to implement several very large multi-feature upgrade solutions.  Additional documentation and samples using the API will be published soon.  Contact us directly if you are interested in being part of the beta-test or discussing how this technology can help you. 

Preview the draft .NET API documentation here.

A sample upgrade program using the API is shown here.  Notice that it use WPF Subsystem logic that is implemented in a C# assembly and available as C# source.

Sample gmslAPI Upgrade Program (beta)
using gmslLibrary;
using wpfLibrary;
using GM=gmslAPI;

namespace gmUpgrade
{
    public static class Program
    {
        [System.STAThread] // Much faster using STA, ~1.6 vs 8.6 seconds
        static void Main(string[] args)
        {
            // When started by gmStudio, TaskInfo is passed on the command line.
            // The TaskInfo XML file is generated by gmStudio.  It contains
            // details about the upgrade task and the upgrade environment.
            // For debugging or direct operation, load upgrade tasks here.
            if (args.Length == 0)
            {                
                args = new string[] {
                    @"TaskInfo=c:\Upgrades\proj\log\Upgrade-task1-exe-csh.xml",
                    @"TaskInfo=c:\Upgrades\proj\log\Upgrade-task2-exe-csh.xml",
                    @"TaskInfo=c:\Upgrades\proj\log\Upgrade-task3-exe-csh.xml",
                    @"TaskInfo=c:\Upgrades\proj\log\Upgrade-task4-exe-csh.xml"
                };
            }
            RunAllTranslations(args);
            System.Environment.Exit(0);
        }

        static void RunAllTranslations(string[] args)
        {
            GM.gmslAPI.LoadLicense(logInfo:true); // Must load gmStudio License

            string taskInfoPath = "";
            foreach (string arg in args)
            {
                if (arg.StartsWith("TaskInfo="))
                {
                    taskInfoPath = arg.Split('=')[1];
                    if (!System.IO.File.Exists(taskInfoPath))
                    {
                        System.Console.WriteLine("ERROR: TaskInfo File Not Found:" + taskInfoPath);
                        System.Environment.Exit(999);
                    }
                    else
                    {
                        Run1Translation(taskInfoPath);
                    }
                }
            }
        }

        private static void Run1Translation(string taskInfoPath)
        {
            GM.gmStudioTask task = GM.gmslAPI.Load(taskInfoPath);

            bool useWPF = task.UserDesc == "WPF";
            
            // Go to Upgrade project working folder so relative file references are correct
            System.IO.Directory.SetCurrentDirectory(task.WorkFolder);

            // Detailed translation rules are stored in a ScriptRules.xml file.
            // This format can be used by both XML-based and API-based upgrade tasks.
            // The ScriptRules class makes the rules available to API calls.
            // Rules may also be created on the fly using gmAPI calls.
            GM.ScriptRules rules = new GM.ScriptRules(@"..\usr\ScriptRules.xml");

            rules.AddRules(task, "SetOptions");
            rules.AddRules(task, "PreEdits");
            rules.AddRules(task, "msado15.dll");
            rules.AddRules(task, "scrrun.dll");
            rules.AddRules(task, "excel.exe");
            rules.AddRules(task, "AssessmentRules");
            rules.AddRules(task, "GenericCollections");

            rules.logEnable = true;
            if (rules.logEnable) FileSystem.LogMessage(rules.AllRulesReport());

            gmBasic.StartUp(@"..\usr\gmBasic.xml", null, null);
            Execute.Storage(action: "Create", identifier: task.JobId);

            Execute.gmPL(commands: rules.OptionRules);

            Execute.Compile(project: task.SrcPath, commands: rules.CompileRules);

            if (rules.PreAnalyseRules != 0)
            {
                Execute.gmPL(commands: rules.PreAnalyseRules);
            }

            Execute.Analyse();

            if (rules.PostAnalyseRules!=0)
            {
                Execute.gmPL(commands: rules.PostAnalyseRules);
            }

            int projectRoot = (useWPF ? wpfSubsystem.WPFCodeScan() : 0); // WPF
            Execute.Output(status: "New", filename: task.BndPath);
            
            if (useWPF) wpfSubsystem.WPFAuthorProject(projectRoot, rules.AuthorRules); // WPF
            else Execute.Author(commands: rules.AuthorRules);

            Execute.Storage(action: "Close");
            gmBasic.Terminate();
        }
    }
}