Author Topic: GetCommandLine issue  (Read 2723 times)

felipe

  • Member
  • *****
  • Posts: 1381
GetCommandLine issue
« on: February 24, 2019, 03:49:36 PM »
I thought i was getting crazy about an issue i was having while usign GetCommandLine to parse some arguments to a simple program i did. The weird problem was that GetCommandLine was putting 2 spaces between the program name and the first argument!  :shock: I was thinking that this should be a bug from my code, but i debugged a lot the program and that seemed to be the case for real. Then searching for that issue with google i found this: https://social.msdn.microsoft.com/Forums/vstudio/en-US/5e737981-3ce1-4742-aa84-9d3f8c7a6b1d/getcommandline-space-problem-in-windows-2008?forum=vclanguage which confirmed for me the issue. I have windows 8.1 but the problem still occurs (i know that the post in that link is old...). So, because this was not "documented" in the GetCommandLine official microsoft documentation i was getting crazy!  :icon_eek: Now i understand why vortex in his command line parsers modules skip all the spaces, without worring for how many they actually are. Well done vortex, you have beaten the microshitway!  :t

Yuri

  • Member
  • **
  • Posts: 179
Re: GetCommandLine issue
« Reply #1 on: February 24, 2019, 04:37:55 PM »
But anyone can put two or more spaces anywhere in a command line, not only Microsoft. It seems obvious that you should keep this in mind when writing a parser. Probably Microsoft was of the same opinion and didn't expect it to be a problem.

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 9369
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: GetCommandLine issue
« Reply #2 on: February 24, 2019, 05:31:34 PM »
The bit you are normally interested in is the command tail, the bit that comes after the executable file name. You can determine that by whether the first non blank character is a double quote or not. If the first char is a double quote, you scan up to the closing double quote, if not you scan on the basis of spaces as the delimiter. I don't like it and it is untidy but you can get it to work.
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :skrewy:

jj2007

  • Member
  • *****
  • Posts: 12479
  • Assembler is fun ;-)
    • MasmBasic
Re: GetCommandLine issue
« Reply #3 on: February 24, 2019, 07:44:19 PM »
Win7-64 behaves correctly. keeps the whitespace. Test yourself:
Code: [Select]
include \masm32\include\masm32rt.inc

.code
start:
  print "["
  invoke GetCommandLine
  inkey eax, "]"
  exit

end start

Use e.g.
Code: [Select]
        <- lots of whitespace (9, 9, 9, 32, 32, 32)   as the commandline
« Last Edit: February 24, 2019, 10:36:57 PM by jj2007 »

Vortex

  • Member
  • *****
  • Posts: 2658
Re: GetCommandLine issue
« Reply #4 on: February 24, 2019, 07:52:21 PM »
Hi felipe,

Nothing special with my command line parser. Skipping the space characters is necessary as they can make trouble during some basic operations like string comparison.

TimoVJL

  • Member
  • *****
  • Posts: 1001
Re: GetCommandLine issue
« Reply #5 on: February 24, 2019, 08:32:21 PM »
A simple test.bat with TAB char too:
Code: [Select]
@REM test commandline
GetCommandLine.exe 12345
GetCommandLine64.exe 12345
"GetCommandLine.exe"  12345
"GetCommandLine64.exe"  12345
"GetCommandLine.exe" 12345
"GetCommandLine64.exe" 12345
pause
May the source be with you

Vortex

  • Member
  • *****
  • Posts: 2658
Re: GetCommandLine issue
« Reply #6 on: February 24, 2019, 08:59:33 PM »
Hi felipe,

There is an interesting API named CommandLineToArgvW :

Quote
Parses a Unicode command line string and returns an array of pointers to the command line arguments, along with a count of such arguments, in a way that is similar to the standard C run-time argv and argc values.

This function takes care of the SPACE characters and removes them from the command line arguments.

Code: [Select]
include     \masm32\include\masm32rt.inc

.data

format      db 'Parameter %d = %s',13,10,0

.data?

buffer      db 256 dup(?)

.code

start:

    call    main
    invoke  ExitProcess,0

main PROC uses esi edi ebx

LOCAL argc:DWORD

    invoke  GetCommandLineW
    lea     ecx,argc
    invoke  CommandLineToArgvW,eax,ecx

    mov     esi,eax
    mov     ebx,argc
    xor     edi,edi
@@:
    inc     edi

; Convert UNICODE string to ANSI

    invoke  WideCharToMultiByte,CP_ACP,0,\
            DWORD PTR [esi],-1,ADDR buffer,\
            256,0,0
           
    invoke  crt_printf,ADDR format,edi,ADDR buffer
    add     esi,4
    dec     ebx
    jnz     @b

    ret

main ENDP

END start

Code: [Select]
CommandLineToArgvW.exe  test1       abc  xyz
Parameter 1 = CommandLineToArgvW.exe
Parameter 2 = test1
Parameter 3 = abc
Parameter 4 = xyz

You can also check __getmainargs and __wgetmainargs providing similar functionality :

https://docs.microsoft.com/en-us/cpp/c-runtime-library/getmainargs-wgetmainargs?view=vs-2017

felipe

  • Member
  • *****
  • Posts: 1381
Re: GetCommandLine issue
« Reply #7 on: February 25, 2019, 01:57:20 AM »
Yes i understand that you want to skip and remove (and even expect) all spaces from the string. But it may be the case that someone don't want to make a program that accepts more than one spaces between the program name and neither between arguments. But of course, that's not the big issue, the annoying thing is that when you read the GetCommandLine official documentation (and supposed updated) from microsoft (https://msdn.microsoft.com/en-us/library/windows/desktop/ms683156(v=vs.85).aspx), you really don't expect this very specific "feature".  :shock: So if you are just testing the function for the first time, typing yourself the arguments when running the program (without more than one space between the program name and the first argument, etc) it can make you a little crazy after some hours... :(
Of course the messagebox friend  :icon14: for debugging this issues showed me this spaces, but it wasn't clear the reason. Lucky for me i found that link yesterday, so i was able to go to sleep in peace.  :bgrin: