An example of using command-line utility RunCmd - Xafari Framework

There are some tasks (commands) that require maximum automation and minimum user interaction. In general, such conditions are satisfied by a console application that allows user to specify the command, set parameters and start execution. Of course, all this should be implemented as an organic part of XAF-application. I.e. command is a function of application, it is coded in the XAF-module. Xafari framework proposes an architecture to implement commands and supplies RunCmd.exe console application to execute commands. Framework provides a number of implemented commands: to import (export) data, to create report etc.

This post describes how to apply this mechanism.

Create XAF WindowsFormApplication, name it RunCmdExample. Add BO business class to the RunCmdExample Module project. The following code demonstrates this.

[DefaultClassOptions]
public class BO : BaseObject
{
    public BO(Session session) : base(session) { }
 
    public string Name { get; set; }
    public string Description { get; set; }
}

Set Security System as you can see in the application screenshots:

Set LogonParametersType to the “DevExpress.ExpressApp.Security.ChangePasswordOnLogonParameters“.

Add new Xaf Module to the solution, name it CommandModule. Since CommandModule used exclusively for RunCmd.exe, the extra folders and files is best to remove. In this example, the commands are implemented in a separate module, but it is not necessary and you can implement command in any application module.

Add RunCmdExample Module to the CommandModule. You can do it in code or using designer. If you wish to add an extra module in code, use following code snippet:

private void InitializeComponent()
{
    this.RequiredModuleTypes.Add(typeof(RunCmdExample.Module.RunCmdExampleModule));
}

Add reference to the Xafari.dll assembly and set CopyLocal property to “True“.

Now we can implement two commands. Add two command classes to CommandModule: it is SecurityInformation and DataInformation. SecurityInformation command will display a list of users or roles. SecurityInformation command will display determined columns of BO type from the database.

The following code snippet defines SecurityInformation and DataInformation classes:

public class SecurityInformation : CommandExtIOBase
{
    public override string Description
    {
        get { return "SInfo command shows information about Roles and Users from DataBase"; }
    }
 
    protected override void ExecuteCore(IDictionary parameters)
    {
        var parameterValue = parameters["Param"].ToString();
        if (parameterValue.Equals("Users", StringComparison.OrdinalIgnoreCase))
            DisplayUsers();
        else if (parameterValue.Equals("Roles", StringComparison.OrdinalIgnoreCase))
            DisplayRoles();
        else
            Out.WriteLine("Invalid parameter value!");
    }
 
    private void DisplayRoles()
    {
        Out.WriteLine("\nRoles:");
        var roles = Application.CreateObjectSpace().GetObjects();
 
        foreach (var role in roles)
            Out.WriteLine("  {0}", role.Name);
    }
 
    private void DisplayUsers()
    {
        Out.WriteLine("\nUsers:");
        var users = Application.CreateObjectSpace().GetObjects();
 
        foreach (var user in users)
            Out.WriteLine("  {0}", user.UserName);
    }       
 
    public override string Name
    {
        get { return "SInfo"; }
    }
 
    public override IEnumerable ParametersDescription
    {
        get
        {
            yield return new CommandParameterDescription("Param", ", ", "Show information about Roles and Users from DB.");
        }
    }
 
    public override void ValidateParameters(IDictionary parameters)
    {
        base.ValidateParameters(parameters);
 
        var tableName = parameters["param"].ToString();
        if (!tableName.Equals("Users", StringComparison.OrdinalIgnoreCase) &&
            !tableName.Equals("Roles", StringComparison.OrdinalIgnoreCase))
        {
            throw new ArgumentException(string.Format("Недопустимое значение параметра Param:\"{0}\"", tableName));
        }
    }
 
    private IObjectSpace objectSpace { get; set; }
}
 
 
public class DataInformation : CommandExtIOBase
{
    public override string Description
    {
        get { return "DInfo command shows information about BO object from DataBase"; }
    }
 
    protected override void ExecuteCore(IDictionary parameters)
    {
        var parameterValue = parameters["Column"].ToString();
        if (parameterValue.Equals("Name", StringComparison.OrdinalIgnoreCase))
            DisplayNameColumn();
        else if (parameterValue.Equals("Description", StringComparison.OrdinalIgnoreCase))
            DisplayDescriptionColumn();
        else if (parameterValue.Equals("All", StringComparison.OrdinalIgnoreCase))
            DisplayAllColumns();
        else
            Out.WriteLine("Invalid parameter value!");
    }
 
    private void DisplayAllColumns()
    {
        if (objectSpace == null)
            objectSpace = Application.CreateObjectSpace();
        var businesObject = objectSpace.GetObjects();
        Out.WriteLine("\n{0,-20} {1}", "Name:", "Description:");
        foreach (var obj in businesObject)
            Out.WriteLine(" {0,-20} {1}", obj.Name, obj.Description);
    }
 
    private void DisplayDescriptionColumn()
    {
        if (objectSpace == null)
            objectSpace = Application.CreateObjectSpace();
        var businesObject = objectSpace.GetObjects();
        Out.WriteLine("\nDescription:");
        foreach (var obj in businesObject)
            Out.WriteLine(obj.Description);
    }
 
    private void DisplayNameColumn()
    {
        if (objectSpace == null)
            objectSpace = Application.CreateObjectSpace();
        var businesObject = objectSpace.GetObjects();
        Out.WriteLine("\nName:");
        foreach (var obj in businesObject)
            Out.WriteLine(obj.Name);
    }
 
    public override string Name
    {
        get { return "DInfo"; }
    }
 
    public override IEnumerable ParametersDescription
    {
        get 
        {
            yield return new CommandParameterDescription("Column", ", , ", "Show content of BO object current column from DB.");
        }
    }
 
    public override void ValidateParameters(IDictionary parameters)
    {
        base.ValidateParameters(parameters);
 
        var tableName = parameters["Column"].ToString();
        if (!tableName.Equals("Name", StringComparison.OrdinalIgnoreCase) &&
            !tableName.Equals("Description", StringComparison.OrdinalIgnoreCase) &&
            !tableName.Equals("All", StringComparison.OrdinalIgnoreCase))
        {
            throw new ArgumentException(string.Format("Недопустимое значение параметра Column:\"{0}\"", tableName));
        }
    }
 
    private IObjectSpace objectSpace { get; set; } 
}

The CommandModule must support ICommandEnumerator interface to specify commands for the RunCmd utility. Otherwise RunCmd will not “know” about the implemented commands. Add the following code to the CommandModule.

public IEnumerable Commands
{
    get 
    { 
        yield return new SecurityInformation(); 
        yield return new DataInformation(); 
    }
}

For ease of use in the future, add RunCmd.exe and RunCmd.exe.config files to the CommandModule project directory. Xafari installer places these files in the “…\Xafari Framework \Tools\RunCmd\” directory.
RunCmd.exe.config settings must match the settings of the global application.

RunCmdExample solution contains ready to use config-file, you can download it and examine together with the solution.

The presence of the <system.diagnostics> block allows to log the execution process.

When working with RunCmd, it is very convenient to use .bat-file. Add Run.bat file to the project and place following text in it:

@echo.
 
RunCmd.exe /dbupdate silent /h /cmdlist
 
@echo.
 
RunCmd.exe @sinfo.txt
 
@echo.
 
RunCmd.exe /batch dinfo.txt

The example above demonstrates different ways to set commands: to type in command line and to load from file.

dinfo.txt file contains:

DInfo Column:All
 
DInfo Column:Name
 
DInfo Column:Description

These commands retrieves information from the database at the specified column. The image illustrates the result of these commands.

cinfo.txt file contains:

/paramlist SInfo /c SInfo Param:Users /c SInfo Param:Roles

The image illustrates the result of SInfo commands.

Before running the utility, you must build CommandsModule, build and run the application to populate the database.

Load solution.

Related Posts

Leave a reply