20 Mar 2020

Handle command line arguments

The commandLine property of an Activity specifies what executable should be run on the Design Automation server and what arguments should be passed to it.

It tends to include the headless server of one of our desktop products, but it could be your own executable as well - see Run additional programs inside a WorkItem
e.g. { "commandLine": "$(engine.path)\\InventorCoreConsole.exe /i $(args[InventorDoc].path) /al $(appbundles[ChangeParams].path) $(args[InventorParams].path)" }

Some of the command line parameters, such as $(appbundles[]), will be interpreted before calling the executable - see Command Lines.

The various products provide different ways of accessing additional parameters passed to the command line - e.g. Inventor provides a NameValueMap containing them in the RunWithArguments() function.

However, .NET itself provides a consistent way to see them all, including the ones processed by the core console apps:
System.Environment.CommandLine
System.Environment.GetCommandLineArgs()

Why would you need access to all the command line arguments, including the one specifying the path to the folder of the AppBundle to load?
One reason could be that you may want to load template files that are included in your AppBundle - see Store template documents in AppBundle
You could instead, of course, rely again on .NET to figure out the path to the dll of your AppBundle and work from there using System.Reflection.Assembly.GetExecutingAssembly() >> Location
Up to you ? 

If your AppBundle always expects certain files with certain names to be present (e.g. params.json) then no need for using command line arguments at all.

However, if you like the flexibility that command line arguments provide then there is a nice little helper available on nuget called System.CommandLine.
It's still in beta, but if it works for you then why not use it already?

System.CommandLine

Some things to note about its usage:

1) If you do not want to handle all the command line arguments, then just set TreatUnmatchedTokensAsErrors to false

2) In the CommandHandler function, the input parameter names need to match one of the Aliases of the Option whose value you need (it seems to be case insensitive)
e.g. in our sample to handle the /j or /jsonpath argument we need either a j, jsonpath, jsonPath, etc input parameter for the handler function - see main picture above.

public void TestCommandLine()
{
    var rootCommand = new RootCommand
    { 
        new Option<string>(new string[]{ "/jsonpath", "/j" }),
        new Option<string>(new string[]{ "/bundlepath", "/al" })
    };
    rootCommand.TreatUnmatchedTokensAsErrors = false;
            
    rootCommand.Handler =
        CommandHandler.Create<string, string>(
        (jsonPath, bundlePath) =>
        {
            Trace.TraceInformation($"Called with jsonPath = \"{jsonPath}\" and bundlePath = \"{bundlePath}\"");
        });

    rootCommand.Invoke(System.Environment.CommandLine);
}

Relevant part from the report file for the WorkItem:

[03/20/2020 14:12:53]     InventorCoreConsole.exe Information: 0 : Called with jsonPath = "T:\Aces\Jobs\ead841089d774edcbf81d039974dc9cc\input.json" and bundlePath = "T:\Aces\Applications\48c87260f0176a9edf71d5af8e5d5dd9.rGm0mO9jVSsD2yBEDk9MRtXQTwsa61y0.SampleBundle[3].package"

 

Related Article