Click here to Skip to main content
Click here to Skip to main content

A Command Line Class

By , 1 Oct 2001
 

Overview

I created this class with the idea of to get easily the parameters of command line.
This was inspired by the people of asked severeal times in the Question Forum the following:
- How Can I get the Command Line Parameters?

For this I created the CCommandLine class

The CCommandLine Class.

CCommandLine::CCommandLine

Constructs a CCommandLine object.

CCommandLine();

CCommandLine::GetFirstParameter

The GetFirstParameter returns the first flag and its parameter.

BOOL GetFirstParameter(CString& strFlag, CString& strParam);

Parameters

CString& strFlag Pointer to a buffer in which to return the Flag.

CString& strParam Pointer to a buffer in which to return the Parameter.

If the function has parameters to return, returns TRUE.

Remarks

If the command line has a parameter without flag, the strFlag variable will be empty.

See Sample


CCommandLine::GetNextParameter

The GetNextParameter returns the next flag and its parameter.

BOOL GetNextParameter(CString& strFlag, CString& strParam);

Parameters

CString& strFlag Pointer to a buffer in which to return the Flag.

CString& strParam Pointer to a buffer in which to return the Parameter.

If the function has parameters to return, returns TRUE.

Remarks

If the command line has a parameter without flag, the strFlag variable will be empty.

See Sample


CCommandLine::GetCommandLine

The GetCommandLine returns the command line string for the application that is running.

void GetCommandLine(CString& strCommand);

Parameters

CString& strCommand Pointer to a buffer in which to return the Command Line.


CCommandLine::GetAppName

The GetAppName returns the application name for the application that is running.

void GetAppName(CString& strAppName);

Parameters

CString& strAppName Pointer to a buffer in which to return the Application Name.


CCommandLine::GetAppPath

The GetAppPath returns the complete path from where the application was executed.

void GetAppPath(CString& strAppPath);

Parameters

CString& strAppPath Pointer to a buffer in which to return the Application Path.


Sample

BOOL CTestApp::InitInstance()
{
	CCommandLine pCmd;
	CString strFlag = _T("");
	CString strParam = _T("");

	BOOL bRet = pCmd.GetFirstParameter(strFlag, strParam);
	while(bRet)
	{
		DoSomethingWithTheParameter(strFlag, strParam);
		bRet = pCmd.GetNextParameter(strFlag, strParam);
	}
	.....
	.....
}

Carlos A. Antollini.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Carlos Antollini
Architect Citigroup
Argentina Argentina
Member
Carlos Antollini is a software engineer working on Object Oriented, Visual C++, MFC, COM, ATL, ADO, Internet technologies and Business Intelligence.
Carlos is originally from Argentina, he was living for several years in Fort Lauderdale, Florida, working for Citibank. Then he started his own business.
Carlos is the creator of piFive[^], a family of BI Analytic Platform software, that it deals next to, latinsys[^], his partner in businesses...
Currently he is sharing his passion for project management and BI at Citigroup.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralSpace between argumentsmemberPresu27 Oct '08 - 19:09 
when i entered in command prompt like :
C:\new folder1 d:\new folder2 arg3 arg4...
 
GetFirstParameter() returns;
 
1st argument = C:\new
2nd argument = folder1
3rd argument = d:\new
4th argument = folder 2 . This is not I want!!!!!!!! Frown | :(
 
but my requirement is ;
 
1st argument = C:\new folder1
2nd argument = d:\new folder2
3rd argument = arg3
4th argument = arg4
 
Do you have any idea on this ?Confused | :confused:
GeneralRe: Space between argumentsmemberChewsHumans22 Sep '09 - 16:49 
Try investing a modicum of time into learning how command-line arguments are supposed to be passed. There is nothing wrong with the code. You need to surround your phrases with quotes.
Generalvery helpfull stuff !!!membersani chabi yo2 Jun '05 - 6:36 
Nice job
Generalhelp!!membermonimicki13 Dec '04 - 13:35 
Help!
I added the cmdline files to my project, however, when I try to build, I get the following error:
 
cmdline.cpp(158) : fatal error C1010: unexpected end of file while looking for precompiled header directive
 
Does anyone know why and/or how to fix it?
Thanks,
Monicque.

GeneralRe: help!!memberbebenuage23 Dec '04 - 2:56 
Hello,
 
I've the same probleme as you.
I just update my Service pack to 6, before try this class, and i wondering if the class function with older SP.
 
What SP are u using please ?
GeneralRe: help!!membermonimicki23 Dec '04 - 20:31 
Hi, I have no idea what SP I am using? I've never updated them. Do you mean Windows Service Packs?
 
Anyway, I didn't end up fixing this problem, but I found a way to get the first command line parameter anyway. (I only wanted to get one parameter, but I think this method may work with more anyway.).
 
How I got the command line parameter:
 
Firstly, I wanted a program to be called only by another program. I didn't want users just clicking on this executable and it working. So I made up a parameter that probably no one would guess, or bother trying. Then in the calling program I did this:
 
SHELLEXECUTEINFO sei;
sei.cbSize = sizeof(SHELLEXECUTEINFO);
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
sei.hwnd = NULL;
sei.lpVerb = NULL;
sei.lpDirectory=strValue;
sei.lpFile = _T("my_other_executable");
sei.lpParameters = "999_weird_param";
sei.hInstApp = NULL;
sei.nShow=SW_SHOW;
ShellExecuteEx(&sei);
 

Then, in the "my_other_executable" program, I did this:
 
Insert new class, make a new class based on the CCommandLineInfo class. (You can find stuff about this in msdn library).
In the new class, have this function (it is an override):
 
void CCmdLine::ParseParam(LPCTSTR lpszParam, BOOL bSwitch, BOOL /*bLast*/)
{
m_strParameter = lpszParam;
}
 
Then, in the init instance (app class):
 
CCmdLine m_cmdInfo;
 
ParseCommandLine(m_cmdInfo);
if(m_cmdInfo.m_strParameter=="999_weird_param")
{
/// do whatever
}
else
{
AfxMessageBox("NO CAN DO!",MB_OK,0);
}
 

I hope that helps.
Monicque.
 

GeneralRe: help!!memberMikael_Segerstein1 Mar '05 - 7:41 
Hi
Maybe you've already solved this but in case you haven't. Add the following line to the top off the cmdline.cpp file.
 
#include "stdafx.h"
 
Or you can turn off the use of precompiled headers.
Hope it helps
 
0110001110011010
GeneralRe: help!! [modified]memberGilC6 Aug '09 - 0:09 
whenever you have error "unexpected end of file while looking for precompiled header directive", type following line at top of your cpp file :
#include "stdafx.h"

 
modified on Thursday, August 6, 2009 7:17 AM

GeneralDoes not work as intendedmemberDavidCrow4 Dec '03 - 8:13 
Using your class, I created a test project (dialog based) in the following folder:
 
C:\Program Files\Microsoft Visual Studio\MyProjects\cl
 
I put the following code in the dialog's InitInstance() method:
 
CCommandLine cl;
CString strPath;
cl.GetAppPath(strPath);
AfxMessageBox(strPath);
When I stepped into the code, the ParseCommandLine() method failed at the token = strtok(string, seps ) statement because of the spaces within the application's path.
 
Is this intentional?
 

Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?

GeneralRe: Does not work as intendedmemberTerry O'Nolley29 Jun '04 - 13:25 
I get the same thing.
Needs to be rewritten so that the path is removed from the command line before the parameters are parsed apart.
 


//placeholder for witty verbiage

GeneralScroll BarmemberHump227 Jan '03 - 20:47 
Confused | :confused: I have Visual C++ 6.0 on my system and have a problem viewing the full length of the active output window. When I run a program, there are no scroll bars on the side of the window. It is annoying when you execute a program and you can not see all of the output because there are not any scroll bars. I tried activating the scroll bars through the properties in the active output window, but it isn't operating. I see Scroll on the drop down window in the properties, but when I mouseclick it nothing happens. Can anyone suggest a solution to this dilema?
 
Hump2
GeneralQuestion on CCommanLine classmemberAnonymous16 May '02 - 18:03 
Hi,
 
I saw your CommandLine class in Code project.
 
I want to open my application(in VC++ 6.0) when certain file (file type
restricted to only my application) is double clicked from windows explorer.
(Just like we double click on any *.doc file, will open word along with that
file).
 
I am using GetCommandLine() to get the command line parameter. When I double
click any file with contains more than one space
between the words of the file name, GetCommandline() is truncating the extra
spaces.
 
For Example:
Hi,
 
I saw your CommandLine class in Code project.
 
I want to open my application(in VC++ 6.0) when certain file (file type
restricted to only my application) is double clicked from windows explorer.
(Just like we double click on any *.doc file, will open word along with that
file).
 
I am using GetCommandLine() to get the command line parameter. When I double
click any file with contains more than one space
between the words of the file name, GetCommandline() is truncating the extra
spaces.
 
For Example:
 
This is the original file I double click:
C:\New Folder with 2 spaces before with\Sample file 2 spaces before
file.txt
 
GetCommandLine returns:
C:\New Folder with 2 spaces before with\Sample file 2 spaces before file.txt
 
See the extra space is not there before "with" and "file" above.
 
Do you have any idea how to work around this.
 
Thanks
 
Murthy
 
This is the original file I double click:
C:\New Folder with 2 spaces before with\Sample file 2 spaces before
file.txt
 
GetCommandLine returns:
C:\New Folder with 2 spaces before with\Sample file 2 spaces before file.txt
 
See the extra space is not there before "with" and "file" above.
 
Do you have any idea how to work around this.
 
Thanks
 
Murthy

GeneralRe: Question on CCommanLine classmemberCarlos Antollini16 May '02 - 18:07 
Murthy,
Your problem is easy to solve using the function _splitpath...
you can see the following sample:
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
_splitpath("C:\\My directory is long very long\\also my filename .txt", drive, dir, fname, ext);

 
in drive you will have "C:"
the dir variable will be "\My directory is long very long\"
in fname you will have "also my filename "
and in ext ".txt"
 
I hope that that will solve your problem....
Best Regards
 

 
Carlos Antollini.
www.wanakostudios.com
Sonork ID 100.10529 cantollini
GeneralClass rewritememberB.Mayrargue8 Oct '01 - 0:03 
Here is a leak free, smaller, supporting quoted parameters and spaces in the executable path name version of CCommandLine
 
I liked the ease of use of this class,
and it's MFC style. But I ran into bugs and missing
functions. So I modified it - completely in fact !
 
The source files can be downloaded at:
http://www.softlion.com/progs/cmdline.zip
I reproduced them below.
 
//Example of use:
BOOL CMyApp::InitInstance()
{
CCommandLine pCmd;
CString strFlag,strParam;
 
for( BOOL bRet = pCmd.GetFirstParameter(strFlag, strParam); bRet; bRet = pCmd.GetNextParameter(strFlag, strParam) )
{
if( strFlag.CompareNoCase("auto") == 0 )
g_bAutoMode = TRUE;
 
else if( strFlag.CompareNoCase("d") == 0 )
g_askedDate = strParam;
 
else if( strFlag.CompareNoCase("conf") == 0 )
g_confFile = strParam;
 
else if( strFlag.CompareNoCase("out") == 0 )
g_outFile = strParam;
}
 
CMyDlg dlg;
m_pMainWnd = &dlg;
dlg.DoModal();
 
return FALSE;
}
 

 

 

 
//
// MODULE: cmdline.h
/*
2001/10/05 - Version 2.00 - Benjamin Mayrargue (http://www.softLion.com http://activex.softLion.com)
Simplifications
leaks free (malloc...)
supports quoted parameters
 
2001/09/29 - Version 1.01 - Carlos Antollini (cantollini@hotmail.com)
Original version
*/
 
#pragma once
 

class CCommandLine: public CCommandLineInfo
{
public:
CCommandLine();
~CCommandLine();
 
public:
BOOL GetFirstParameter(OUT CString& strFlag, OUT CString& strParam);
BOOL GetNextParameter(OUT CString& strFlag, OUT CString& strParam);

inline void GetCommandLine(CString& strCommand) const {strCommand = m_strCommandLine;};
inline void GetAppName(CString& strAppName) const {strAppName = m_strAppName;};
inline void GetAppPath(CString& strAppPath) const {strAppPath = m_strAppPath;};
 
protected:
void UnquoteString( OUT CString& strOut ); //Manage the quotes (").
 
CString m_strCommandLine;
CString m_strAppName;
CString m_strAppPath;
char *m_token;
char *m_string;
};
 

 

 
//
// MODULE: cmdline.h
/*
2001/10/05 - Version 2.00 - Benjamin Mayrargue (http://www.softLion.com http://activex.softLion.com)
Simplifications
leaks free (malloc...)
supports quoted parameters
 
2001/09/29 - Version 1.01 - Carlos Antollini (cantollini@hotmail.com)
Original version
*/
 
#include "stdafx.h"
#include "cmdline.h"
 

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
 

static char seps[] = " ";
 

CCommandLine::CCommandLine()
{
m_string = m_token = NULL;

m_strCommandLine = ::GetCommandLine();
m_strCommandLine.TrimLeft();
m_strCommandLine.TrimRight();
m_strAppName = AfxGetAppName();
}
 

CCommandLine::~CCommandLine()
{
if(m_string)
delete [] m_string;
}
 

BOOL CCommandLine::GetFirstParameter(CString& strFlag, CString& strParam)
{
strFlag.Empty();
strParam.Empty();

if( m_string ) delete [] m_string;
m_string = new char[m_strCommandLine.GetLength()+ 1];
memset(m_string, 0, (m_strCommandLine.GetLength()+1) * sizeof(char));
lstrcpy(m_string, m_strCommandLine);

m_token = strtok(m_string, seps );

//Forget the first param (it's the file name and it's quoted).
if( !m_token )
return FALSE;
GetNextParameter(strFlag,strParam);
 
return GetNextParameter(strFlag,strParam);
}
 

BOOL CCommandLine::GetNextParameter(CString& strFlag, CString& strParam)
{
strFlag.Empty();
strParam.Empty();

if( !m_token )
return FALSE;

 
//It's a flag
if( *m_token == '/' || *m_token == '-' )
{
m_token++;
UnquoteString(strFlag);
m_token = strtok(NULL, seps);
}
 
if( *m_token != '/' && *m_token != '-' )
{
UnquoteString(strParam); //It's a param
m_token = strtok( NULL, seps );
}
 
return TRUE;
}
 

//Manage the quotes (").
void CCommandLine::UnquoteString( OUT CString& strOut )
{
if( *m_token == '\"' )
{
LPSTR p = ++m_token;
while( m_token && *(m_token+lstrlen(m_token)-1) != '\"' )
{
*(m_token-1) = ' ';
m_token = strtok(NULL, seps);
}
*(m_token-1) = ' '; //For the last one

LPSTR last = m_token+lstrlen(m_token)-1; //Remove the last quote
if( *last == '\"' ) *last = 0;
strOut = p;
}
else
strOut = m_token;
}

 
________________________
 
http://www.sofTLion.com
________________________

GeneralRe: Class rewritememberCarlos Antollini9 Oct '01 - 3:41 
Thanks for fix my class.
I need to say you that I have a new version. check it. Because I had a memory leak, but I had a lot of problems with the update of the sources, in Code Project. But the correct version is here from October 3rd..
 
Best Regards!!! Big Grin | :-D
 
Carlos Antollini.
GeneralRe: Class rewritememberdazinith9 Oct '02 - 6:43 
i included the two source files into my project, then i compile, then i go to command prompt and type "MyApp -auto" and crash everytime.. i seem to crash anytime there is a '-' or a '/' anywhere in my command line.. any suggestions?
 
still a newb.. cut me some slack :P
-dz
GeneralSome fixes for your modificationmemberdazinith9 Oct '02 - 9:27 
Welp, i think i figured out the problem.. so here are a few changes that need to be made to avoid a crash, or invalid parameters.
 
first off in CCommandLine::GetNextParameter() it checks for the '-' or '/' to signify a flag, but if it passes if(*m_token == '/' || *m_token == '-') then it sets the m_token variable and checks it again, at this point the variable could be NULL, which causes a crash.. so the second if block needs to be an else if block, or at least check for NULL before calling the second if block..
 
fix:
BOOL CCommandLine::GetNextParameter(CString& strFlag, CString& strParam)
{
	strFlag.Empty();
	strParam.Empty();
  
	if( !m_token )
	    return FALSE;
  
	if( *m_token == '/' || *m_token == '-' ) //It's a flag
	{
		m_token++;
		UnquoteString(strFlag);
		m_token = strtok(NULL, seps);
	}
	else if( *m_token != '/' && *m_token != '-' )
	{
		UnquoteString(strParam); //It's a param
		m_token = strtok( NULL, seps );
	}
 
	return TRUE;
}
 
i also found the example pretty hard to follow, and the loop through the parameters and flags was really odd looking to me.. also if you checked each parameter or flag it found there would sometimes be blank strings("") as a parameter.. so here is an example that was more in line with what i used this code for..
	/* ========= Parse command line options =========== */
	CCommandLine pCmd;
	CString strFlag,strParam;
	
	BOOL bRet = pCmd.GetFirstParameter(strFlag, strParam); 
	if (!bRet)
	{	AfxMessageBox("No parameters were passed into the update program, this program cannot be run on its own.");
		CDialog::EndDialog(IDABORT);	}
	while (bRet)
	{
		if (strParam != "")
			AfxMessageBox(strParam); // show each item received that is a parameter

		if (strFlag.Compare("n") == 0)
			AfxMessageBox("User used the /n or -n switch");
		if (strFlag.Compare("r") == 0)
			AfxMessageBox("User used the /r or -r switch");
 
		bRet = pCmd.GetNextParameter(strFlag, strParam);
	}
the command line i use in this example is:
C:\MyAppFolder\MyApp.exe "filename1" "filename2" /n
the output for this command line is:
filename1
filename2
User used the /n or -n switch
if you run the .exe without any parameters then it tells you.. youll notice im doing if (strParam != "") because somehow blanks are getting in the parameter listing.. but i didnt look close enough to see how that all worked..
 
hope this helps some ppls! Smile | :) thanks for the code!
 
still a newb.. cut me some slack :P
-dz
GeneralRe: Some fixes for your modificationmemberSquirrel Twirler26 Apr '05 - 6:50 
Thanks for the code everyone, it works like a charm.
GeneralRe: Some fixes for your modificationmemberDimok13 May '05 - 23:24 
Your example doesn't work with one argument.
I think correct function:
 
BOOL CCommandLine::GetNextParameter(CString& strFlag, CString& strParam)
{
strFlag.Empty();
strParam.Empty();
 
if( !m_token )
return FALSE;
 

//It's a flag
if( *m_token == '/' || *m_token == '-' )
{
m_token++;
UnquoteString(strFlag);
m_token = strtok(NULL, seps);
}
 
if (m_token != NULL)
{
if( *m_token != '/' && *m_token != '-' )
{
UnquoteString(strParam); //It's a param
m_token = strtok( NULL, seps );
}
}
 
return TRUE;
}
 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 2 Oct 2001
Article Copyright 2001 by Carlos Antollini
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid