Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

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 also available as C# source .

...

languagec#
titleSample gmslAPI Upgrade Program (beta)
linenumberstrue
collapsetrue

...

from Great Migrations.  The example also shows how to load source and edit the source in memory prior to translation.  To use this, API you need to reference gmslAPI.dll from the gmStudio distribution and also make sure you choose Platform Target x86 since the gmBasic engine is presently a 32bit technology.  Contact Great Migrations if you are interested in a 64bit build.

Code Block
languagec#
titleSample gmslAPI Upgrade Program (beta)
linenumberstrue
collapsetrue
using System.Collections.Generic;
using System.Linq;
using gmslLibrary.Services;
using gmslLibrary.Model;
using gmslLibrary.Enums;
using GM = gmslAPI;

namespace gmUpgrade
{
    public static class Program
    {
        const string taskArg = "TaskInfo=";
        const string startupArg = "startup=";

        [System.STAThread] // faster using STA
        static void Main(string[] args)
        {

            string cmlStartup = System.Array.Find(args, str => str.StartsWith(startupArg));
            string startupPath = null;
            if (cmlStartup == null)
            {
                // default startup file path
                startupPath = gmslAPI.Common.DefaultStartUpFile;
            }
            else
            {
                // parse startup path from the command line, and remove it from the list of arguments
                int i = 0;
                foreach (string arg in args)
                {
                    if (arg.StartsWith(startupArg))
                    {
                        args[i] = "";
                        startupPath = arg.Split('=')[1];
                    }
                    i++;
                }
            }

            // When started by gmStudio, TaskInfo argument 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.
            // Note: you can redirect the output of this to the log file for 
            // debugging (> log) in project properties, but doing so will block 
            // gmStudio from running the EXE running when VS is open. 
            string cmlTask = System.Array.Find(args, str => str.StartsWith(taskArg));
            List<string> taskList = new List<string>();
            if (cmlTask == null)
            {
                // batch
                taskList.Add(taskArg + @"C:\gmSpec\Util\APITest\proj\log\APITest-APITest-exe-csh.TRAN.Xml");
            }
            else
            {
                // parse taskarg item from the command line
                int i = 0;
                foreach (string arg in args)
                {
                    if (arg.StartsWith(taskArg))
                    {
                        args[i] = "";
                        taskList.Add(arg);
                    }
                    i++;
                }
            }
            if (taskList.Count == 0)
            {
                System.Console.Write("USAGE: " + args[0] + " " + taskArg + " TaskInfoFilePath");
                System.Environment.Exit(1);
            }

            RunAllTranslations(taskList, startupPath, args);
            System.Environment.Exit(0);
        }

        static void RunAllTranslations(List<string> taskList, string startupPath, string[] args)
        {
            GM.Common.LoadLicense(logInfo: true);

            string taskInfoPath = "";
            foreach (string arg in taskList)
            {
                if (arg.StartsWith(taskArg))
                {
                    taskInfoPath = arg.Split('=')[1];
                    if (!System.IO.File.Exists(taskInfoPath))
                    {
                        System.Console.WriteLine("ERROR: TaskInfo File Not Found:" + taskInfoPath);
                        System.Environment.Exit(999);
                    }
                    else
                    {
                        repair(taskInfoPath);
                        GM.gmStudioTask task = GM.Common.Load(taskInfoPath);
                        RunUpgrade(task, startupPath, args);
                    }
                }
            }
        }
        private static void RunUpgrade(gmslAPI.gmStudioTask task, string startupPath, string[] args)
        {
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            sw.Start();

            // Go to Upgrade project working folder so relative file references are correct
            System.IO.Directory.SetCurrentDirectory(task.WorkFolder);

            System.Console.WriteLine("Loaded task:" + task.JobId);

            string projectStartup = @"C:\Program Files (x86)\GreatMigrations\gmStudio\support\tools\gmBasic.xml";
            if (!System.IO.File.Exists(projectStartup)) projectStartup = null;

            gmBasic.StartUp(projectStartup, null, args);

            // Detailed translation rules are stored in a ScriptRules.xml
            // This format can be used by both XML-based and API-based upgrade tasks
            // The ScriptRules class makes these rules available to API calls.
            GM.ScriptRules rules = new GM.ScriptRules(@"..\usr\ScriptRules.xml");

            rules.AddRules(task, "BasicRules");

            rules.logEnable = true;
            log(rules.logEnable, rules.AllRulesReport());

            log(rules.logEnable, "Startup(ms):" + sw.ElapsedMilliseconds);
            Execute.Storage(action: "Create", identifier: task.JobId);

            if (rules.OptionRules != 0)
            {
                Execute.gmPL(commands: rules.OptionRules);
                log(rules.logEnable, "Options(ms):" + sw.ElapsedMilliseconds);
            }

            bool useWPF = Select.SubSystem == Dialects.wpf;

            log(rules.logEnable, "GUI: " + (useWPF ? "WPF" : "WinForms"));

            Execute.Load(project: task.SrcPath, sourcecode: "on");
            AddCommentOnErrorHandlers();

            Execute.Compile(resx: task.ResxFolder, commands: rules.CompileRules);
            //Execute.Compile(project: task.SrcPath, resx: task.ResxFolder, commands: rules.CompileRules);
            log(rules.logEnable, "Compile(ms):" + sw.ElapsedMilliseconds);

            if (rules.PreAnalyseRules != 0)
            {
                Execute.gmPL(commands: rules.PreAnalyseRules);
       [System.STAThread] // Much faster using STA, ~1.6  vs 8.6 seconds
 log(rules.logEnable, "PreAnalyse(ms):" + sw.ElapsedMilliseconds);
      static void Main(string[] args)   }

    {        Execute.Analyse();
    // When started by gmStudio, TaskInfo is passed on the command line. log(rules.logEnable, "Analyze(ms):" + sw.ElapsedMilliseconds);

           // The TaskInfo XML file is generated by gmStudio.  It containsif (rules.PostAnalyseRules != 0)
            {
// details about the upgrade task and the upgrade environment.       Execute.gmPL(commands: rules.PostAnalyseRules);
    // For debugging or direct operation, load upgrade tasks here.   log(rules.logEnable, "PostAnalyse(ms):" + sw.ElapsedMilliseconds);
      if (args.Length == 0)   }

        {    Execute.Output(status: "New", filename: task.BndPath);

            Execute.Author(commands: rules.AuthorRules);
          args = new string[] {
 log(rules.logEnable, "Author(ms):" + sw.ElapsedMilliseconds);
            Execute.Output(status: "Close");

    @"TaskInfo=c:\Upgrades\proj\log\Upgrade-task1-exe-csh.xml",        if (rules.PostAuthorRules != 0)
         @"TaskInfo=c:\Upgrades\proj\log\Upgrade-task2-exe-csh.xml",   {
                 @"TaskInfo=c:\Upgrades\proj\log\Upgrade-task3-exe-csh.xml",
  Execute.gmPL(commands: rules.PostAuthorRules);
                log(rules.logEnable, @"TaskInfo=c:\Upgrades\proj\log\Upgrade-task4-exe-csh.xml"
 "PostAuthor(ms):" + sw.ElapsedMilliseconds);
            }

};             }Execute.Storage(action: "Close");
            RunAllTranslationsgmBasic.Terminate(args);
            log(rules.logEnable, "Total(ms):" + System.Environment.Exit(0sw.ElapsedMilliseconds);
        }
        private static void RunAllTranslationslog(bool doLog, string[] argsmsg)
        {
            if GM.gmslAPI.LoadLicense(logInfo:true); // Must load gmStudio License

        (doLog) System.Console.WriteLine(msg);
   string taskInfoPath = "";  }
        private static foreachvoid repair(string argtaskInfoPath)
in args)       {
     {       string data = System.IO.File.ReadAllText(taskInfoPath);
       if (arg.StartsWith("TaskInfo="))    data = data.Replace("UsrCm nt=", "UsrCmnt= ");
       {     data = data.Replace("UsrDes c=", "UsrDesc= ");
          taskInfoPath = arg.Split('=')[1]System.IO.File.WriteAllText(taskInfoPath, data);
        }

        private static if (!System.IO.File.Exists(taskInfoPath)void AddCommentOnErrorHandlers()
        {
           {
          int[] levels = new int[19];
            int  System.Console.WriteLine("ERROR: TaskInfo File Not Found:" + taskInfoPath);iRoot;
            tInfoFile formFile;
            Text textStream;
   System.Environment.Exit(999);         int nRecord;
          }  int curRecord;
            int length = 0;
 else           int rai =  0;
     {       string record;

            for (iRoot = Run1Translation(taskInfoPathStore.FindFirstChild(levels, 0); iRoot != 0; iRoot = Store.FindNextChild(levels))
            {
  }              if (Store.GetObjectType(iRoot)  }
!= ObjectType.FormFile) continue;
           }     string name =  }Symbol.FullName(iRoot, 0);
         private static void Run1Translation(string taskInfoPath)   FileSystem.LogMessage("name=" + name);

  {             GM.gmStudioTask taskformFile = GM.gmslAPI.Load(taskInfoPath new tInfoFile(iRoot);
              bool useWPF =if task(formFile.UserDesctextBase == "WPF";
           0) continue;
              // Go to Upgrade project working folder so relative file references are correct FileSystem.LogMessage("formFile.textBase=" + formFile.textBase);

                textStream =  System.IO.Directory.SetCurrentDirectory(task.WorkFolder);new Text(formFile.textBase);
              // Detailed translation rules are stored in a ScriptRules.xml file. FileSystem.LogMessage("textStream=" + textStream);

                // Thissample formatcode canchanges belines usedending bywith both XML-based and API-based upgrade tasks.
":" to lines ending with ": 'TEST"
           // The ScriptRules class makes thenRecord rules available to API calls.= textStream.Maximum();
               // RulescurRecord may= also0;
be created on the fly using gmAPI calls.         while (curRecord < nRecord)
GM.ScriptRules rules = new GM.ScriptRules(@"..\usr\ScriptRules.xml");            {
 rules.AddRules(task, "SetOptions");             rules.AddRules(task, "PreEdits");    curRecord = curRecord + 1;
     rules.AddRules(task, "msado15.dll");               rulestextStream.AddRules(task, "scrrun.dll");Position(curRecord);
               rules.AddRules(task, "excel.exe");    record = textStream.Access(ref length, ref rai);

  rules.AddRules(task, "AssessmentRules");             rules.AddRules(task, "GenericCollections");   if (length < 2) continue;
      rules.logEnable = true;            string if (rules.logEnable) FileSystem.LogMessage(rules.AllRulesReport());

 last = Character.Substr(record, length - 1, 1);
          gmBasic.StartUp(@"..\usr\gmBasic.xml", null, null);        if (last == ":")
 Execute.Storage(action: "Create", identifier: task.JobId);              Execute.gmPL(commands: rules.OptionRules); {
            Execute.Compile(project: task.SrcPath, commands: rules.CompileRules);         // Inserts a record after if (rules.PreAnalyseRules != 0)
    the current record and sets Position to new record
       {                 ExecutetextStream.gmPL(commands: rules.PreAnalyseRules);Insert(record + " ' TEST");
               }         // reset position to  Execute.Analyse();original record
             if (rules.PostAnalyseRules!=0)          textStream.Position(curRecord);
  {                 Execute.gmPL(commands: rules.PostAnalyseRules);    // delete original record
     }              int projectRoot = (useWPF ? wpfSubsystemtextStream.WPFCodeScanDelete() :;
0); // WPF             Execute.Output(status: "New", filename: task.BndPath);         continue;
                    if}
(useWPF) wpfSubsystem.WPFAuthorProject(projectRoot, rules.AuthorRules); // WPF            }
else Execute.Author(commands: rules.AuthorRules);              ExecutetextStream.Storage(action: "Close"Close();
            gmBasic.Terminate();}
        }
    }
}