[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 3243
  • Last Modified:

parsing commandline arguments of WinMain

Hi all,

I wanted a simple, failsafe way to get command line arguments from:

int PASCAL WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR  lpCmdLine,
    int nCmdShow );

The arguments are 2 absolute file-paths and spaces(blanks) can be part of the file-paths. So, I cann't just search for blank space to find out the next token :)

thanks,
Vikram


0
Vikram_B
Asked:
Vikram_B
1 Solution
 
AlexFMCommented:
If argument contains blanks, client must use "" for such argument:

yourProgram "C:\Program Files\Dir\File1.txt" "C:\Program Files\Dir\File2.txt"

This is general rule for all command parsers. Without this there is no way to detect number of parameters.
0
 
Infinity08Commented:
The norm is to enclose the file paths with "" - for example :

    command "/path/to first/file 1" "/path/to second/file 2"

Those will be passed as :

    argument 1 : /path/to first/file 1
    argument 2 : /path/to second/file 2
0
 
Vikram_BAuthor Commented:
thanks Infinity08,

But, how to parse argument1 and argument2? can I use some string manipulation function?
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
Infinity08Commented:
You can use whatever you want, but this is the basic idea :

    char *cmdLine = (char*) lpCmdLine;
    char args[128][128] = { 0 };
    int i = 0;
    while (*cmdLine) {
      if (*cmdLine == ' ') {
        cmdLine++;
      }
      else {
        char *end = 0;
        if (*cmdLine == '\"') {
          cmdLine++;
          end = strchr(cmdLine, '\"');
        }
        else {
          end = strchr(cmdLine, ' ');
        }
        if (end) {
          strncpy(args[i], cmdLine, end - cmdLine);
          args[i][end - cmdLine] = '\0';
          cmdLine = end + 1;
          i++;
        }
        else {
          /* ERROR - treat it !! */
        }
      }
    }

Note that this is just for you to get an idea of how you COULD do it. This is ny no means complete code !!!
If more than 128 args are passed or if one arg is more than 127 characters long, this code will create problems !!
The above code is not validated, and is just written off the top of my head, so there might still be other problems with it !
0
 
Infinity08Commented:
0
 
itsmeandnobodyelseCommented:
Maybe you want that (it is tested):

#include <string>
#include <vector>
using namespace std;

int parseCmdLine(const char* szcmdline, vector<string> arguments)
{
    string cmdline = szcmdline;
    cmdline += ' ';   // add a final space for easier parsing
    bool bQuotes = false;
    int lpos = 0;
    int i = 0;
    for (i = 0; i < cmdline.length(); ++i)
    {
          char c = cmdline[i];
          switch(c)
          {
          case '"':   // note it is  '  "  '
                bQuotes = !bQuotes;   break;
          case ' ':
                if (bQuotes)
                     break;   // ignore space if within quotes
                if (i > lpos)
                     arguments.push_back(cmdline.substr(lpos, i - lpos));
                lpos = i+1;
          }
    }
    return arguments.size();
}

You can use it in your WinMain like

    vector<string> arguments;
    int nArgs = parseCmdLine( lpCmdLine, arguments );

    for (int i = 0; i < nArgs; ++i)
          cout << arguments[i] <<  endl;

Regards, Alex



0
 
waysideCommented:
What might be easier if you are using the Microsoft compiler, is that argc and argv are available as globals. The globals are __argc and __argv (that's two underscore characters in front).

Then you don't have to parse at all:

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
  char buffer[500];
  for (int i=0; i<__argc; i++) {
    sprintf(buffer, "arg %ld = %s", i, __argv[i]);
    MessageBox(NULL, buffer, "cmdline", MB_OK);
  }
}

0
 
Vikram_BAuthor Commented:
thanks everyone!
 sorry, i cudnt reply in time. i donno why, but i am not receiving notifications from ee for the new comments posted!
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now