• Welcome to Valhalla Legends Archive.
 

C++ - Question on Parsing Command line args..

Started by LordVader, September 02, 2004, 07:03 AM

Previous topic - Next topic

LordVader

Searched the forum only found one thread close was for java and not quite what im looking for..

Basically I want to create a switch that can fire when the program is started if an argument is passed via command (thru a shortcut to the program).. basically the same as you can do in Onlyers D2Loader..

Im assuming:
*Read the comments

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{

   WNDCLASSEX wc;
   HWND hwnd;
   MSG Msg;
   
   hWndInst = hInstance;

   // ---- Registering the Window Class
   wc.cbSize        = sizeof(WNDCLASSEX);
   wc.style         = 0;
   wc.lpfnWndProc   = WndProc;
   wc.cbClsExtra    = 0;
   wc.cbWndExtra    = 0;
   wc.hInstance     = hInstance;
   wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
   wc.hbrBackground = g_hbrBackground;
   wc.lpszClassName = g_szClassMainWnd;
   wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MAINMENU);
   wc.hIcon  = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MAIN_ICON));
   wc.hIconSm  = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MAIN_ICON), IMAGE_ICON, 16, 16, 0);
   
   if(!RegisterClassEx(&wc))
   {
       MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
       return 0;
   }

/******
Put a switch here to check for a -nogui switch to jump to:
an init main function to bypass window creation
Jump to a function to check if the switch was passed and use that as the switch
*******/

int argResults = FindIntMainArgs();

switch(argResults)
   {
   case NoGui:
       //Jump to a basic winmain init function
       break;
   default:
       {
        // Create the Window if no args were sent
        hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, g_szClassMainWnd, "Opbot Testing Console", WS_OVERLAPPEDWINDOW, 0, 0, 450, 200, NULL, NULL, hInstance, NULL);
       if(hwnd == NULL)
       {
           MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
       return 0;
       }
       break;
   }

   ShowWindow(hwnd, nCmdShow);
   UpdateWindow(hwnd);

   // ---- The Message Loop
   while(GetMessage(&Msg, NULL, 0, 0) > 0)
   {
   TranslateMessage(&Msg);
   DispatchMessage(&Msg);
   }
   return Msg.wParam;
}


Basically:
1. Is that in theory a correct/logical way to go about this?

2. What are the functions in C++ that can catch/interprit arg's passed via command line and maybe a small example.. or link..

Thanks in advanced and hope that code makes since..
Not using dialogs in this instance cause im try'n to learn the api i'm new to C++  :P

Kp

The command line is available in the parameter lpCmdLine, or you can use GetCommandLineW() / CommandLineToArgvW() to get the system to break it down into component parts for you.  CLTAW returns an array of strings, parsed in a manner similar to the argv[] array you should be used to handling.  Then it's just a matter of scanning for a trigger string in the array.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

LordVader

Thank's ill play with and do some research on that!

LordVader

Just noticed lpCmdLine in:

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)


+1 Duh for Vader, I didn't even equate it to actually being the actual windows command line heh.

See I am new to C++ =P
But im learning heh.

Thx again for the reply Kp.

LordVader

Reference on LPSTR lpCmdLine for future readers:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getcommandline.asp

When I get a small sample working ill post that for reference also.

K

If you need to do more involved parsing (ie, checking for multiple conditions, having positional arguments), my new favorite toy is the boost::program_options library.  Unfortunantly program_options hasn't been rolled into a stable boost release yet, but you can check out the latest cvs version to use it.

Here's a small example (this may not compile with the newest cvs version - they're working on changing the syntax before its added to boost.)


   string in_file_str;
   string out_file_str;
   int line_len;

   options_description desc("Options");
   // interpret first position arg as input file
   // interpret second position arg as output file
   positional_options_description p;
   p.add("input",1);
   p.add("output", 1);


   // --help   = -h
   // --input  = -i
   // --output = -o
   // --width  = -w
   // --number = -n

   desc.add_options()
      ("help,h", "shows this message")
      ("input,i", value<string>(&in_file_str), "set input filename")
      ("output,o", value<string>(&out_file_str)->default_value("out.txt"), "set output filename")
      ("width,w", value<int>(&line_len)->default_value(16), "set line width of output (in characters)")
      ("number,n", "write line offsets to output file");


   variables_map vm;

   try
   {
      store(command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
      notify(vm);    
   }
   catch(exception& ex)
   {
      cout << ex.what() << endl << endl
          << desc << endl;
      return 1;
   }
   // display help
   if (vm.count("help") != 0)
   {
      cout << desc << endl;
      return 0;
   }

   // no input file specified
   if (vm.count("input") == 0)
   {
      cout << "you must specify a file to read." << endl
          << desc << endl;
      return 0;
   }

// ....

LordVader


LordVader

#7
Small function for reference that get's command line arguments built from the msdn CommandLineToArgvW reference ..


void CheckCmdLine()
{
LPWSTR *szArgList;
int nArgs;

// stores the command line includes the following:
// program path/name, and "ALL" command arguments and the total number of arguments is stored into nArgs
szArgList = CommandLineToArgvW(GetCommandLineW(), &nArgs);

//If the command line fails szArgList is empty/null
if(NULL == szArgList)
{
//throw an exception or error here something went wrong.
}

//look for arguments don't include the patch/exe name which is nArgs == 1,
else if(nArgs >=2)
{
//Just an example to catch -gui sent thru the command line
if(!strstr((char *)szArgList," -gui"))
{
// Do stuff for the switch\trigger -gui
}
}
LocalFree(szArgList);
}

usage:

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int mdShow)
{
CheckCmdLine();
return 0;
}

*Note this is for win32 applications not thru a console program.

R.a.B.B.i.T

int main(int argc, char **argv)Isn't that all he needs?

Kp

Quote from: LordVader on September 08, 2005, 12:59 PM
Small function for reference that get's command line arguments built from the msdn CommandLineToArgvW reference ..


void CheckCmdLine()
{
LPWSTR *szArgList;
int nArgs;

// stores the command line includes the following:
// program path/name, and "ALL" command arguments and the total number of arguments is stored into nArgs
szArgList = CommandLineToArgvW(GetCommandLineW(), &nArgs);

//If the command line fails szArgList is empty/null
if(NULL == szArgList)
{
//throw an exception or error here something went wrong.
}

//look for arguments don't include the patch/exe name which is nArgs == 1,
else if(nArgs >=2)
{
//Just an example to catch -gui sent thru the command line
if(!strstr((char *)szArgList," -gui"))
{
// Do stuff for the switch\trigger -gui
}
}
LocalFree(szArgList);
}

usage:

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int mdShow)
{
CheckCmdLine();
return 0;
}

*Note this is for win32 applications not thru a console program.

Have you tested this?  I can't see that it would work, since you're checking for an ANSI string inside the pointer to your Unicode argument.  Hint: don't just blindly throw in typecasts when you get a compiler warning.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

Blaze

Quote from: rabbit on September 08, 2005, 06:58 PM
int main(int argc, char **argv)Isn't that all he needs?
Its not a console application hes working on.
Quote
Mitosis: Haha, Im great arent I!
hismajesty[yL]: No

R.a.B.B.i.T

Well then change it to the entry point for whatever he's working on.  I don't see why you would want to grab the command line from a program not running from the command line, it just doesn't make sense.

Mangix


R.a.B.B.i.T

Parameters can be issued run-time from a shortcut or command prompt, and are passed to the program in the same exact way, so changing the entry point to a whatever type of program you're making and keeping the argument declarations should work.

dxoigmn

Quote from: rabbit on September 09, 2005, 05:34 PM
Parameters can be issued run-time from a shortcut or command prompt, and are passed to the program in the same exact way, so changing the entry point to a whatever type of program you're making and keeping the argument declarations should work.

What are you talking about? He is creating a Windows application therefore he needs to use WinMain, not main. main != WinMain.