Navigation Bar

21 June 2012

[ MFC ] - Custom CCommandLineInfo Example in VC++ to parse commandline Parameters


1. Introduction


We know that functions will sometimes take parameters and process it. Similarly, executable applications also take parameters and switches and it behaves based on the parameters passed to it. In this article, we will see how do we pass command line parameters to an MFC Dialog based applications. The approach is same for other applications like single document and multi-document applications.



2. Creating a dialog based application


First, create a dialog-based application and name it as CommandLineDlg. That is the name I had chosen but I am not restricting you keep the same name. Once the application is created, using the class view add a class to the solution. Name the class as CcommandParse.  Make this class derived from CCommandLineInfo. This class declaration is as follows:

class CCommandParse : public CCommandLineInfo



Creating the dialog based application is shown in the below video:

Video 1: Watch Here




3. The CCommandLineInfo Derived class


We have two MFC string Arrays declared in this class. One will hold command line data and another one will hold command line switches. Switches will tell how the application should behave and data is information passed for processing. The Get functions will receive reference parameters and copies the String Array values from class’s member variable.

The ParseParam function is overridden from the based class CCommandLineInfo. So in the implementation, we will get a chance to process each and every param passed from the command line.

Below is the Full Class definition:

class CCommandParse : public CCommandLineInfo
{
public:
             CCommandParse(void);
             virtual ~CCommandParse(void);

             //Sample 03: Get functions for params and switches
             void GetParams(CStringArray& params);
             void GetSwitches(CStringArray& switches);

private:
             //Sample 01: Private Members
             CStringArray m_params;
             CStringArray m_switches;

             //Sample 02: Override for Base class virtual
             void ParseParam(const TCHAR *pszParam, BOOL bFlag, BOOL bLast);
};

The ParseParam function will get called for each command line parameters (data and switches) and this function will store the command line arguments to m_params or m_switches flag, which is the second parameter to the function. Below is the overridden function:

//Sample 04: Implement the Parse Param
void CCommandParse::ParseParam(const TCHAR *pszParam, BOOL bFlag, BOOL bLast)
{
             //Sample 04_1: Collect the parameters and switches in a separate Array
             CString param_or_switch(pszParam);
             if (bFlag)
                           m_switches.Add(param_or_switch);
             else
                           m_params.Add(param_or_switch);
}

AS already told the get functions will copy the command line arguments to the passed in reference String Arrays passed in. The code is straightforward and it is given below:

//Sample 05: Get Functions.
void CCommandParse::GetParams(CStringArray& params)
{
             int size = m_params.GetCount();
             for (int i = 0; i<size; i++)
                           params.Add( m_params.GetAt(i));
}

void CCommandParse::GetSwitches(CStringArray& switches)
{
             int size = m_switches.GetCount();
             for (int i = 0; i<size; i++)
                           switches.Add( m_switches.GetAt(i));
}

That all the changes we need for the CcommandParse class. Now we will move to the Application Instance and make the necessary changes. That is we are going to use the class that we defined just now.



4. Application Instance Parsing Params & Switches


In the application class, we included our custom parser, which we discussed in the previous section. Then the function GetCommandLinePasrser is declared to receive the command line parameters by passing the references to the CStringArray instances. Finally, we declared our custom parser as the member variable. The entire header file is shown below:

//Sample 06: Include the Custom Parse
#include "CommandParse.h"

// CCmdLineDlgApp:
// See CmdLineDlg.cpp for the implementation of this class
//

class CCmdLineDlgApp : public CWinApp
{
public:
             CCmdLineDlgApp();

// Overrides
public:
             virtual BOOL InitInstance();
//Sample 07: Fill the passed in array structures.
             void GetCommandLinePasrser(CStringArray& params, CStringArray& switches);

//Sample 08: To pasrse command line arguments
private:
             CCommandParse m_cmdParse;


// Implementation

             DECLARE_MESSAGE_MAP()
};


The InitInstance function of the application class gets called when the application is initialized. In this function, we passed our custom command line parser object to the function call ParseCommandLine. Now the MFC API is aware of the extended functionality of the default command line parsing. For each command line arguments passed, MFC will now call our overridden ParseParam member function CcommandParse that we derived from the class CCommandLineInfo. Below is the piece of code:

//Sample 09: Use the Custom Command Line Parser
ParseCommandLine(m_cmdParse);
if (ProcessShellCommand(m_cmdParse))
             return FALSE;


The Application instance will make a call to the custom command line instance m_cmdParse to get the Command params and switches. The dialog class calls this member function. Below is the piece of code:

//Sample 10: The command Line parser will do the copy
void CCmdLineDlgApp::GetCommandLinePasrser(CStringArray& params, CStringArray& switches)
{
             m_cmdParse.GetParams(params);
             m_cmdParse.GetSwitches(switches);
}


5. The Dialog class


In the dialog, we just have two list boxes. The dialog template edited by IDE is shown below:



The above-displayed dialog will get the application instance and pass two string arrays by reference to the member exposed by the application instance. The application instance will make a call to the custom command line parser to get the parameters and switches. Once the dialog knows the parameters and switches, it will display it in the corresponding list boxes.

All the above said stuff is done in the InitInstance member function of the dialog. Look at the below piece of code:

//Sample 11: Add the Command Line Arguments to List controls.
CStringArray params, switches;
 ((CCmdLineDlgApp *) AfxGetApp())->GetCommandLinePasrser(params, switches);

 for (int i = 0; i<params.GetCount(); i++)
              m_lst_params.AddString(params.GetAt(i));

 for (int i = 0; i<switches.GetCount(); i++)
              m_lst_switches.AddString(switches.GetAt(i));

First, we collected the params and switches in the CString array instances by calling the application instance’s member function GetCommandLinePasrser. Once the dialog has the information, it displays it by adding it to the corresponding m_lst_params, m_lst_switches by iterating through the CStringArray instances.



6. Testing the sample


The attached sample can be tested in two different ways. The first way is going to the command prompt and executing the exe by passing the command line argument. The second way is passing the static parameters by setting the debug property of the project. The second method is useful when we want to debug the sample.

Below video shows passing the command line argument (with switches) from the command prompt.

Video 2: Watch Here


Below video shows perform debugging with command line arguments.

Video 3: Watch Here



Source Code: Download