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 a user to specify the command, set parameters and start execution. Of course, all this should be implemented as an organic part of a XAF application, i.e. command is a function of the 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. The 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.

1
2
3
4
5
6
7
8
[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:

Xafari Security System

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

Add a new XAF Module to the solution, name it CommandModule. Since CommandModule is used exclusively for RunCmd.exe, is better to remove extra folders and files. 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 the code or use designer. If you wish to add an extra module in the code, use the following code snippet:

1
2
3
4
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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 Run Cmd utility. Otherwise, Run Cmd will not "know" about the implemented commands. Add the following code to the CommandModule:

1
2
3
4
5
6
7
8
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.

Run Cmd Example solution contains a ready-to-use config file, you can download it and examine together with the solution.

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

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

1
2
3
4
5
6
7
8
9
10
11
@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 the command line and to load from file.

dinfo.txt file contains:

1
2
3
4
5
DInfo Column:All
 
DInfo Column:Name
 
DInfo Column:Description

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

RunCmd

cinfo.txt file contains:

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

The image illustrates the result of SInfo commands.

RunCmd

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

Load solution: Run Cmd Example.

Write US