Командная строка. Решение в лоб не проходит

Тема в разделе "WASM.BEGINNERS", создана пользователем mutex_llc, 1 дек 2008.

  1. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    mutex_llc
    Ну а я напишу ещё разок. :)
    Тут так и не понял, о себе это Вы или обо мне. Если о себе, то рад, что здравый смысл в Вас проснулся. Если обо мне, то я не в обиде. :)
    Оффтоп начался уже после второго-третьего поста. Второй был не совсем корректен, но в нём содержится указание, воспользовавшись которым Вы получите ответ на Ваш вопрос в полной мере. Третий пост - это корректировка второго поста (если судить строго, то тоже может подпадать под оффтоп).
     
  2. mutex_llc

    mutex_llc New Member

    Публикаций:
    0
    Регистрация:
    7 июн 2007
    Сообщения:
    14
    I_inc, думайте и считайте как желаете, Ваше право.

    Судя по всему люди, скачавшие и запустившие тест, получили тот же результат. Причина осталась не выясненной. Что ж, это тоже результат, показывающий что ОС и система MASM в чем-то рассогласованы. Можно закрывать тему.
     
  3. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    mutex_llc
    Мда... Вы непробиваемы. Причина была указана в постах 2, 4, 6, 9, как это ни странно 11, 13, 16. Восемь раз было повторено, почему вываливается сообщение о том, что аргумент есть.
    Честно говоря, я не понимаю, зачем я пытаюсь разжевать это в девятый раз. То, что утверждение Эйнштейна насчёт бесконечностей верно, мне и так наглядно известно... но именно это и бесит.
    Итак разжёвываю в девятый раз:
    Когда Вы запускаете из проводника свою программку, explorer (тот процесс, который запускает Вашу программку) передаёт NULL в качестве командной строки. Для Вашей программы это означает, что в качестве командной строки ей будет передан! путь к ней. Функция GetCommandLine вернёт указатель на строку, содержащую путь. Если в этом пути находятся пробелы, то Ваша программа при сканировании строки параметров (по сути этого самого пути с пробелами) на эти пробелы наткнётся и, соответственно, выдаст, что аргументы присутствуют.
     
  4. litrovith

    litrovith Member

    Публикаций:
    0
    Регистрация:
    20 июн 2007
    Сообщения:
    509
    l_inc- ironman )))
    mutex_llc, не ищите черную кошку в темной комнате......)))
     
  5. mutex_llc

    mutex_llc New Member

    Публикаций:
    0
    Регистрация:
    7 июн 2007
    Сообщения:
    14
    Фу, ты чёрт, дошло наконец. Привык всегда работать с путями без пробелов и упустил. Спасибо, что не поленились и добили меня, тупого консерватора. :) Извините меня за грубость.

    Значит буду сканировать строку с конца и если первым встречу кавычку, буду считать, что аргумента нет.

    Ага, согласен. :)

    Между прочим выяснилось, что у меня Проводник и Отладчик OllyDbg ведут себя по разному, когда аргумент отсутствует в командной строке: Проводник добавляет один пробел после пути и имени приложения, а Отладчик не добавляет.
    Это-то и запутало меня, усугубив мое паршивое поведение на форуме, хотя служить оправданием не может никак!

    После строки loop sravn добавил две строки и программа заработала в моих каталогах с короткими именами. Конечно для длинных имен с пробелами она работать не станет. Вот основной код:
    ...
    invoke GetCommandLine ;адрес ком.строки в eax
    mov dCmd,eax
    invoke lstrlen,eax
    mov ecx,eax
    cmp ecx,0
    je netu
    mov esi,dCmd
    sravn:
    cmp byte ptr [esi],0
    je vyxod
    cmp byte ptr [esi],20h
    je vyxod
    inc esi
    loop sravn
    vyxod:
    cmp ecx,1
    jg est
    netu:
    ...
    Выставляю исправленную версию в архиве.
    Всем спасибо и извините за лишнее с моей стороны.
    Теперь уж тема точно исчерпана.
     
  6. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Есть такая штука: GetModuleFileName.
    Она позволит вам отделить зерна (параметры) от плевел (имя исполняемого файла) и получить вожделенные параметры. Независимо от наличия/отсутствия пробелов в имени файла и прочих разных кавычек...
     
  7. Com[e]r

    Com[e]r Com[e]r

    Публикаций:
    0
    Регистрация:
    20 апр 2007
    Сообщения:
    2.624
    Адрес:
    ого..
    CommandLineToArgvW(GetCommandLineW(),&argc) уже упомянали?

    вот как поступил я:
    int GetArgs(int *argc,char*argv[]){
    argv[0]=alloc(256);
    GetModuleFileNameA(0,argv[0],256);
    WCHAR** argvw = CommandLineToArgvW(GetCommandLineW(),argc);
    for(byte i=1;i<*argc;i++) {
    int wlen=lstrlenW(argvw);
    argv=alloc(wlen+1);
    wcstombs(argv,argvw,wlen);
    }
    return *argc;
    }

    всё очень коротко и просто, и нечего бояться юникода.
     
  8. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    а если аргумент содержит кавычку? ;)
     
  9. K10

    K10 New Member

    Публикаций:
    0
    Регистрация:
    3 окт 2008
    Сообщения:
    1.590
    Из Delphi RTL
    Код (Text):
    1. function GetParamStr(P: PChar; var Param: string): PChar;
    2. var
    3.   Len: Integer;
    4.   Buffer: array[0..4095] of Char;
    5. begin
    6.   while True do
    7.   begin
    8.     while (P[0] <> #0) and (P[0] <= ' ') do Inc(P);
    9.     if (P[0] = '"') and (P[1] = '"') then Inc(P, 2) else Break;
    10.   end;
    11.   Len := 0;
    12.   while (P[0] > ' ') and (Len < SizeOf(Buffer)) do
    13.     if P[0] = '"' then
    14.     begin
    15.       Inc(P);
    16.       while (P[0] <> #0) and (P[0] <> '"') do
    17.       begin
    18.         Buffer[Len] := P[0];
    19.         Inc(Len);
    20.         Inc(P);
    21.       end;
    22.       if P[0] <> #0 then Inc(P);
    23.     end else
    24.     begin
    25.       Buffer[Len] := P[0];
    26.       Inc(Len);
    27.       Inc(P);
    28.     end;
    29.   SetString(Param, Buffer, Len);
    30.   Result := P;
    31. end;
    32.  
    33. function ParamCount: Integer;
    34. var
    35.   P: PChar;
    36.   S: string;
    37. begin
    38.   P := GetParamStr(GetCommandLine, S);
    39.   Result := 0;
    40.   while True do
    41.   begin
    42.     P := GetParamStr(P, S);
    43.     if S = '' then Break;
    44.     Inc(Result);
    45.   end;
    46. end;
    47.  
    48. function ParamStr(Index: Integer): string;
    49. var
    50.   P: PChar;
    51.   Buffer: array[0..260] of Char;
    52. begin
    53.   if Index = 0 then
    54.     SetString(Result, Buffer, GetModuleFileName(0, Buffer, SizeOf(Buffer)))
    55.   else
    56.   begin
    57.     P := GetCommandLine;
    58.     while True do
    59.     begin
    60.       P := GetParamStr(P, Result);
    61.       if (Index = 0) or (Result = '') then Break;
    62.       Dec(Index);
    63.     end;
    64.   end;
    65. end;
    И не надо никаких CommandLineToArgvW )
     
  10. mutex_llc

    mutex_llc New Member

    Публикаций:
    0
    Регистрация:
    7 июн 2007
    Сообщения:
    14
    Comer_, к сожалению надо работать и под Win9x, а там с юникодом не прокатит у юзеров.

    shoo, сканирую прямо как и было. Этот вариант прошел все мои тесты. Надеюсь, что он правильный.

    Код (Text):
    1. ; Есть ли аргумент в командной строке?
    2. .386
    3. .model flat, stdcall
    4. option casemap:none
    5. include \masm32\include\kernel32.inc
    6. include \masm32\include\user32.inc
    7. includelib \masm32\lib\user32.lib
    8. includelib \masm32\lib\kernel32.lib
    9.  
    10. .data
    11. sNet db "Аргумент в ком.строке отсутствует",0
    12. sEst db "Аргумент в ком.строке имеется",0
    13. sZag db "Тест",0
    14.  
    15. .code
    16. start:  push ebx
    17.         push esi
    18.         push edi
    19.         invoke GetCommandLine
    20.         cmp byte ptr [eax],0
    21.         je netu               ;значит, комстрока пуста
    22.         inc eax
    23.         mov cl,'"'
    24.         cmp [eax-1],cl
    25.         je cikl               ;идти на поиск закрывающей кавычки
    26.         mov cl,' '            ;иначе, искать пробел
    27. cikl:   cmp byte ptr [eax],0
    28.         je netu
    29.         cmp [eax],cl
    30.         je vyx
    31.         inc eax
    32.         jmp cikl
    33. vyx:    inc eax
    34.         mov ch,cl
    35.         mov cl,' '
    36.         cmp ch,'"'
    37.         je cikl               ;после закрывающей кавычки надо искать пробел
    38. cikl2:  cmp byte ptr [eax],0  ;пропустить повторяющиеся пробелы
    39.         je netu
    40.         cmp byte ptr [eax],' '
    41.         jne est
    42.         inc eax
    43.         jmp cikl2
    44. est:    mov eax,offset sEst
    45.         jmp stop
    46. netu:   mov eax,offset sNet
    47. stop:   invoke MessageBox,0,eax,addr sZag,0
    48.         pop edi
    49.         pop esi
    50.         pop ebx
    51.         invoke ExitProcess,0
    52. end start
    K10, красив Паскаль, ничего не скажешь. Мне он нравится, особенно в исполнений виртуозов Борланда.
     
  11. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    значит результат достигнут :)
     
  12. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    mutex_llc
    А под досом случайно не надо?

    Comer_
    wcstombs хороша для английских буков, боюсь для национальных это будет работать плохо. Натыкался на подобные грабли. Думаю лучше заюзать WideCharToMultiByte
     
  13. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    mutex_llc
    А ты пробовал? в 9х все уникод версии функций отлично работают.
     
  14. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    я пробовал. не могу подтвердить :) кое-что есть во врапперах, кое-что появляется после установки определенных версий IE и офисов, а для остального нужно ставить специальную поддержку.

    даже специально сохранил скриншот из 98 винды, в которой нет офиса и эксплорер родной (4.1 вроде бы)

    [​IMG]
     
  15. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Ф-ия подготавливает массив адресов переданных аргументов. (WARN: "портит" оригинальную строку, разделяя аргументы нулями). Принимает адрес массива адресов, который надо заполнить, возвращает количество аргументов.

    Код (Text):
    1. STATE_IN_QUOTE  = 0xFF
    2. STATE_OUT_QUOTE = 0x0
    3.  
    4. format PE GUI
    5.  
    6. include '%fasminc%\win32a.inc'
    7.  
    8. ;Test command line: test test "this is just a test" test "just a test"test test"one more"
    9.  push array
    10.  call parse_command_line
    11.  mov ecx, eax
    12. .l00p:
    13.  push ecx
    14.  push 0x0
    15.  push 0x0
    16.  push dword [array + ecx * 4 - 0x4]
    17.  push 0x0
    18.  call [MessageBoxW]
    19.  pop ecx
    20.  loop .l00p
    21.  xor eax, eax
    22.  ret
    23.  
    24. ;dword get_command_line(dword *argv)
    25. parse_command_line:
    26.  call [GetCommandLine]
    27.  mov esi, eax
    28.  mov edi, esi
    29.  xor ecx, ecx
    30. .l00p:
    31.   lodsw
    32.   cmp ax, '"'
    33.   jnz .not_quote
    34.    not byte [state]
    35.    jmp .l00p
    36.  .not_quote:
    37.   cmp ax, ' '
    38.   jnz .not_space
    39.    cmp byte [state], STATE_IN_QUOTE
    40.    jz .l00p
    41.     mov eax, [esp + 0x4]
    42.     mov [eax + ecx * 4], edi
    43.     mov edi, esi
    44.     mov word [edi - 0x2], 0x0
    45.     inc ecx
    46.     jmp .l00p
    47.  .not_space:
    48.   test ax, ax
    49.   jnz .l00p
    50.  mov eax, [esp + 0x4]
    51.  mov [eax + ecx * 4], edi
    52.  lea eax, [ecx + 1]
    53.  ret 0x4
    54.  
    55. state: db STATE_OUT_QUOTE
    56. array: dd 0x6 dup 0x0
    57.  
    58. data import
    59.  
    60.  library kernel32,'KERNEL32.DLL',\
    61.          user32, 'USER32.DLL'
    62.  
    63.  import kernel32,\
    64.         GetCommandLine, 'GetCommandLineW'
    65.  
    66.  import user32,\
    67.         MessageBoxW, 'MessageBoxW'
    68.  
    69. end data
    По сути, маленький конечный автомат. Вроде, все предусмотрел.
     
  16. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    http://board.flatassembler.net/topic.php?t=6663