Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2009.11.01;
Скачать: [xml.tar.bz2];

Вниз

Разбор командной строки на имя файла и параметры   Найти похожие ветки 

 
DVM ©   (2009-09-01 15:17) [0]

Понадобилась тут мне функция, которая бы разбивала строку на имя файла и параметры запуска. Вобщем то ничего сложного, но хотелось бы максимально приблизится к разбору строки к проводнику Windows.

Загвоздка вот в чем:
Проводник успешно стартует из автозагрузки строку:
C:\Program Files\Flashget\flashget.exe /min

Я никак не могу понять, как он понимает где здесь имя файла, где параметр? Кавычек нет, слеш в параметре тоже необязателен.


 
Skyle ©   (2009-09-01 15:18) [1]

ParamStr, ParamCount + F1?


 
DVM ©   (2009-09-01 15:23) [2]


> Skyle ©   (01.09.09 15:18) [1]

Читаем внимательно текст поста, мне не нужны параметры запуска моего приложения.


 
Rouse_ ©   (2009-09-01 15:23) [3]

имя файла ParamStr(0)

> слеш в параметре тоже необязателен

FindCmdLineSwitch()


 
clickmaker ©   (2009-09-01 15:24) [4]

> Проводник успешно стартует из автозагрузки строку:
> C:\Program Files\Flashget\flashget.exe /min

а C:\Program Files\Flashget\flashget /min ?


 
DVM ©   (2009-09-01 15:29) [5]


> Rouse_ ©   (01.09.09 15:23) [3]


> имя файла ParamStr(0)

Речь не идет о моей программе, я обрабатываю внешние строки из которых надо выделить путь и параметры.


> clickmaker ©   (01.09.09 15:24) [4]


> а C:\Program Files\Flashget\flashget /min ?

Типа такого он тоже обрабатывает нормально, вот строка которую он успешно обрабатывает:

%systemroot%\system32\dumprep 0 -k


 
tesseract ©   (2009-09-01 15:34) [6]


> вот строка которую он успешно обрабатывает:


%systemroot%  -это же переменная окружения :-)


 
Skyle ©   (2009-09-01 15:35) [7]

Может тогда что-нибудь типа
ExpandEnvironmentStrings + до второй кавычки или первого пробела?


 
DVM ©   (2009-09-01 15:38) [8]


> tesseract ©   (01.09.09 15:34) [6]


> %systemroot%  -это же переменная окружения :-)

а то я не знаю, дело то не в это


 
clickmaker ©   (2009-09-01 15:38) [9]

попробовал запустить из меню Run
C:\Program Files\Far\Far.exe /min

ругнулся, что не может найти C:\Program


 
DVM ©   (2009-09-01 15:39) [10]


> Skyle ©   (01.09.09 15:35) [7]


> ExpandEnvironmentStrings

Это само собой, но точно не до первого пробела или второй кавычки


 
DVM ©   (2009-09-01 15:40) [11]


> clickmaker ©

а у меня флешжет тем не менее запускается


 
DVM ©   (2009-09-01 15:40) [12]


> > clickmaker ©

из автозагрузки только


 
clickmaker ©   (2009-09-01 15:45) [13]

ну тогда напрашивается вариант, что если нет кавычек, то ищет до последнего слэша, а после него - до первого пробела


 
DVM ©   (2009-09-01 15:45) [14]

Путем эксперимента я кажется понял логику работы проводника в таких случаях.

1) Сначала он убирает кавычки
2) Разворачивает EnvironmentStrings
3) Идет от первого символа строки и плюсует их во временный буфер, каждый раз проверяя не накопилось ли в буфере имени существующего файла.

Но до такого метода он пытается разобраться со строкой по-хорошему, учитывая кавычки и т.д.


 
Rouse_ ©   (2009-09-01 15:47) [15]

FindExecutableImage()


 
Медвежонок Пятачок ©   (2009-09-01 15:48) [16]

каждый раз проверяя не накопилось ли в буфере имени существующего файла.

перебирая в том числе все папки %path% ?
сомнительно как-то


 
Anatoly Podgoretsky ©   (2009-09-01 15:58) [17]

> clickmaker  (01.09.2009 15:38:09)  [9]

Тоже правильно, имя не соответствует правилам именования.


 
Anatoly Podgoretsky ©   (2009-09-01 16:00) [18]

> clickmaker  (01.09.2009 15:45:13)  [13]

не правильно.

C:\Program files\filename1.ext  \folder\filename2.ext


 
DVM ©   (2009-09-01 16:03) [19]


> Anatoly Podgoretsky ©   (01.09.09 15:58) [17]

Правильно-неправильно, однако ж работает. Мне надо чтобы тоже работало.
Вообще непонятно. кто пошел у кого на поводу, то ли MS подстроилась к кривым программам, создающим кривые записи в реестре, то ли программы эксплуатируют такое либерально отношение проводника, но проблемы определенные это создает.


 
clickmaker ©   (2009-09-01 16:12) [20]

> то ли MS подстроилась к кривым программам, создающим кривые
> записи в реестре

скорей всего
непонятно только, изначально ли был прицел на такую возможную кривизну, или уже "по просьбам трудящихся"


 
DVM ©   (2009-09-01 16:20) [21]


> clickmaker ©   (01.09.09 16:12) [20]

я думаю дело в том, что изначально длинных путей не было, и многие программы не задумываясь писали в реестр %systemroot%\proga.exe /param и проблем не было, после подстановки переменных окружения.

Но вот появились длинные пути. Надо было обеспечить совместимость ОС с такими программами. Программы писали все как и раньше, без кавычек (путь то без пробелов для них), а вот после замены переменных окружения он становился неверным, т.к могли появляться пробелы.


 
TIF ©   (2009-09-01 18:32) [22]


> Я никак не могу понять, как он понимает где здесь имя файла,
>  где параметр? Кавычек нет, слеш в параметре тоже необязателен.
>

Я, наверное и эту тему не понял o_O
А разве нельзя начать проверку с конца и остановиться на первом пробеле, после этого сказав - стоп! Всё что слева - путь, всё что справа - параметры
?


 
clickmaker ©   (2009-09-01 18:48) [23]

> А разве нельзя начать проверку с конца и остановиться на
> первом пробеле, после этого сказав - стоп! Всё что слева
> - путь, всё что справа - параметры

свежая мысль. Особенно, если учесть, что параметров может быть до хрена


 
TIF ©   (2009-09-01 19:12) [24]

> Особенно, если учесть, что параметров может быть до хрена

Ну, с учётом этого топать дальше, но закругляться, встретив обратный слеш \


 
Eraser ©   (2009-09-01 19:24) [25]

> [0] DVM ©   (01.09.09 15:17)

на сколько я понял, нужно чтобы работало аналогично "Выполнить"?


 
Anatoly Podgoretsky ©   (2009-09-01 19:39) [26]

> TIF  (01.09.2009 19:12:24)  [24]

слеша может и не быть.


 
TIF ©   (2009-09-01 19:52) [27]

> слеша может и не быть.

Это имеется в виду такой случай
myexe /a /b /c
?

Тут успешно доходим до начала строки, а оринтируемся на последний с конца (первый с начала) пробел

Название исполняемого файла с пробелом в имени не в счёт, в этом случае 100% нужны кавычки


 
DVM ©   (2009-09-01 19:55) [28]


> Eraser ©   (01.09.09 19:24) [25]


> на сколько я понял, нужно чтобы работало аналогично "Выполнить"?

Скорее так, как проводник отрабатывает ключ
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

В случае с "выполнить" он не выполняет C:\Program Files\Far\Far.exe /min
А в случае чтения из реестра выполняет. Т.е. даже без кавычек.


 
DVM ©   (2009-09-01 19:56) [29]


> TIF ©   (01.09.09 19:52) [27]


> Название исполняемого файла с пробелом в имени не в счёт,
>  в этом случае 100% нужны кавычки

Ну ё-мое, ты это проводнику объясни, что нужны. Но ему не нужны. И мне надо так.


 
DVM ©   (2009-09-01 19:57) [30]


> Eraser ©   (01.09.09 19:24) [25]

Только мне выполнять ничего не надо, мне нужно имя файла и параметры отдельно.


 
Anatoly Podgoretsky ©   (2009-09-01 19:58) [31]

> TIF  (01.09.2009 19:52:27)  [27]

Может быть вариант

myexe myexe /a /b /c


 
Anatoly Podgoretsky ©   (2009-09-01 19:59) [32]

> DVM  (01.09.2009 19:55:28)  [28]

На Виста выполняет.


 
DVM ©   (2009-09-01 20:03) [33]

По всей видимости проводник действительно просматривает строку с конца, каждый раз отбрасывая по одному символу и проверяет, не является ли оставшаяся строка реально существующим исполняемым файлом.


 
TIF ©   (2009-09-01 20:04) [34]

> Может быть вариант myexe myexe /a /b /c

У меня "Выполнить" в Windows такого уже не понимает. Принимает за имя exe только первый myexe


 
Anatoly Podgoretsky ©   (2009-09-01 20:05) [35]

> DVM  (01.09.2009 19:56:29)  [29]

Так надо сначало оговорить условия, откуда берется список и где он применяется, точный формат списка и прочее.
Частные решения имеют, общего решения нет.


 
DVM ©   (2009-09-01 20:10) [36]


> Anatoly Podgoretsky ©


> Так надо сначало оговорить условия, откуда берется список
> и где он применяется

1) Список берется из HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

2) Все программы из данного списка проводник успешно запускает.

3) Мне надо разобрать этот список на пары: Полный путь к файлу -> Параметры

Затык пока у меня только с длинными именами не заключенными в кавычки.


 
Anatoly Podgoretsky ©   (2009-09-01 20:13) [37]

> DVM  (01.09.2009 20:03:33)  [33]

Это хоть допустимый, но глупый алгоритм, проще слева направо и не символами, а словами.
Но нужен ответ на ранее заданый вопрос про условия применимости.


 
Anatoly Podgoretsky ©   (2009-09-01 20:15) [38]

> TIF  (01.09.2009 20:04:34)  [34]

Потому что второй myexe является параметром.


 
DVM ©   (2009-09-01 20:20) [39]


> Anatoly Podgoretsky ©   (01.09.09 20:13) [37]


> проще слева направо и не символами, а словами.

нет не проще, даже я бы сказал неправильно слева направо.

Пример:
Разбираем слева направо строку C:\Program Files\Folder\File /param
На каком то шаге мы должны проверить наличие исполняемого файла
C:\Program Files\Folder
Но в папке C:\Program Files\ может не оказаться подпапки Folder, но запросто может оказаться файл Folder.exe, который и будет выполнен - ОШИБКА!


 
Eraser ©   (2009-09-01 20:24) [40]

> [28] DVM ©   (01.09.09 19:55)


> В случае с "выполнить" он не выполняет C:\Program Files\Far\Far.exe
> /min

в висте и 7 выполняет.

///  <summary>Разделение командной строки на путь к файлу и параметры запуска</summary>
///  <param name="ACommandLine">Командная строка</param>
///  <param name="AFilePath">Путь к файлу</param>
///  <param name="AParams">Параметры запуска</param>
procedure SplitCommandLine(ACommandLine: string; var AFilePath, AParams: string);
var
 sFile, sParams: string;
 sSource: PWideChar;
 StringArray: TStringArray;
 I, J: Integer;
begin
 sFile := "";
 sParams := "";
 ACommandLine := Trim(ACommandLine);
 if FileExists(ACommandLine) then
 begin
   sFile := ACommandLine;
   sParams := "";
 end
 else
 begin
   // Ищем вхождение существующего файла.
   StringArray := Explode(" ", ACommandLine);
   for I := 0 to Length(StringArray) - 1 do
   begin
     sFile := Trim(sFile + " " + StringArray[I]);
     if FileExists(sFile) then
     begin
       // Файл найден, принимаем оставшуюся часть строки за параметры.
       for J := I + 1 to Length(StringArray) - 1 do
         sParams :=  Trim(sParams + " " + StringArray[J]);

       Break;
     end;
   end;

   if not FileExists(sFile) then
   begin
     // Если файл так и не удалось выделить.
     // Определяем, указаны ли ковычки.
     if Pos(""", sFile) = 1 then
     begin
       // Ковычки найдены, извлекаем путь с их учетом.
       sSource := PChar(sFile);
       sFile := SysUtils.AnsiExtractQuotedStr(sSource, Char("""));
       sParams := sSource;
     end
     else
     begin
       sFile := StringArray[0];
       sParams := "";
       for I := 1 to Length(StringArray) - 1 do
         sParams :=  Trim(sParams + " " + StringArray[I]);
     end;
   end;
 end;

 AFilePath := sFile;
 AParams := sParams;
end;

вряд ли подойдет для 100% случаев, но в целом поведение "выполнить" повторяет.


 
Anatoly Podgoretsky ©   (2009-09-01 20:25) [41]

> DVM  (01.09.2009 20:10:36)  [36]

Поскольку именя реальные для данной машины и видимо полные, то решение есть и очень простое. Надо выделять слева направо и направо и проверять FileExists/
Например для С:\Program Files\Folder X\File.exe параметры, проверка идет так

1. C:\Program - No
2. С:\Program Files - No
3. С:\Program Files\Folder - No
4. С:\Program Files\Folder X - No
5. С:\Program Files\Folder X\File.exe - Yes

На шаге пять получен правильный вариант и все что правее это параметры
В алгоритме шаги ограничиваются пробелом и ключом (-/)


 
Eraser ©   (2009-09-01 20:26) [42]

> [40] Eraser ©   (01.09.09 20:24)

в догонку
function Explode(const ASeparator, ASource: string; ALimit: Integer = 0): TStringArray;
var
 SepLen: Integer;
 F, P: PChar;
begin
 SetLength(Result, 0);
 if (ASource = "") or (ALimit < 0) then
   Exit;

 if ASeparator = "" then
 begin
   SetLength(Result, 1);
   Result[0] := ASource;
   Exit;
 end;
 SepLen := Length(ASeparator);

 P := PChar(ASource);
 while P^ <> #0 do
 begin
   F := P;
   P := AnsiStrPos(P, PChar(ASeparator));

   if (P = nil) or ((ALimit > 0) and (Length(Result) = ALimit - 1)) then
     P := StrEnd(F);

   SetLength(Result, Length(Result) + 1);
   SetString(Result[High(Result)], F, P - F);
   F := P;
   while (P^ <> #0) and (P - F < SepLen) do
     Inc(P);
 end;
end;


 
DVM ©   (2009-09-01 20:30) [43]


> Eraser ©   (01.09.09 20:24) [40]

Важные замечания, которые не учитывает функция:

1) У файла может не быть расширения
2) У файла может не быть пути (путь файла должен быть восстановлен после просмотра %PATH% и прочих системных папок)

Что такое TStringArray и Explode?


 
Eraser ©   (2009-09-01 20:34) [44]

> [43] DVM ©   (01.09.09 20:30)


> Важные замечания, которые не учитывает функция:

согласен.

> Explode?


> TStringArray

type
 TStringArray = array of string;


 
DVM ©   (2009-09-01 20:34) [45]


> Anatoly Podgoretsky ©   (01.09.09 20:25) [41]


> Например для С:\Program Files\Folder X\File.exe параметры,
>  проверка идет так
>
> 1. C:\Program - No
> 2. С:\Program Files - No
> 3. С:\Program Files\Folder - No
> 4. С:\Program Files\Folder X - No
> 5. С:\Program Files\Folder X\File.exe - Yes
>

Ошибка запросто может возникнуть на первом же шаге, т.к. в пути необязательно указано расширение файла, а следовательно, если на диске будет файл C:\Program.exe то он будет взят за искомый этим алгоритмом что неверно!


 
Eraser ©   (2009-09-01 20:36) [46]

> [45] DVM ©   (01.09.09 20:34)


> Ошибка запросто может возникнуть на первом же шаге, т.к.
> в пути необязательно указано расширение файла, а следовательно,
> если на диске будет файл C:\Program.exe то он будет взят
> за искомый этим алгоритмом что неверно!

тут надо эксперементальным путем смотреть, как реализовано у MS, в любом случае, думаю какие-то ноухау там вряд ли применяются.


 
DVM ©   (2009-09-01 20:38) [47]


> Eraser ©   (01.09.09 20:36) [46]


> тут надо эксперементальным путем смотреть, как реализовано
> у MS

Этим и занимаюсь, предположительно просмотр идет с конца, тогда описанной проблемы в [45] вроде бы не должно быть.


 
DVM ©   (2009-09-01 20:43) [48]

В Shlwapi.dll есть две функции, котрыми мог пользоваться эксплорер, это:
PathRemoveArgsW(), PathGetArgsW(), проверил, они тоже спотыкаются об имя файла с пробелами и без кавычек, тупо отрезают считают все что до первого пробела именем, остальное параметрами.


 
TIF ©   (2009-09-01 21:14) [49]

> Потому что второй myexe является параметром.

Правильно.
И мой алгоритм работает аналогично:
А)
> начать проверку с конца и остановиться на первом пробеле,
>  после этого сказав - стоп! Всё что слева - путь, всё что
> справа - параметры

или если нет \
Б)
> успешно доходим до начала строки, а оринтируемся на последний
> с конца (первый с начала) пробел


> Разбираем слева направо строку C:\Program Files\Folder\File
> /param

Вариант А - ибо есть \


 
TIF ©   (2009-09-01 21:17) [50]

> и остановиться на первом пробеле,

ЧОрт. Вру, вру, вру... Не на первом. Отпадает. Тогда до последнего пробела перед \


 
DVM ©   (2009-09-01 21:24) [51]


> TIF ©   (01.09.09 21:14) [49]

Зря мучишся, вот тебе командная строка:

file name1 file name2

Никаких тебе \ и прочего.
Тем не менее, при наличии на диске file name1.exe в одной из доступных папок он будет запущен и ему параметром будет передан file name2


 
TIF ©   (2009-09-01 21:41) [52]

> он будет запущен

У меня не будет:
> У меня "Выполнить" в Windows такого не понимает.

PS: win 7


 
DVM ©   (2009-09-01 21:45) [53]


> TIF ©   (01.09.09 21:41) [52]


> У меня "Выполнить" в Windows такого не понимает

Так речь не о Пуск - > Выполнить же. Я про автозагрузку - там проблем нет, все выполняется.


 
TIF ©   (2009-09-01 22:16) [54]

> Я про автозагрузку

Как всегда в винде везде всё по-разному %-\


 
DVM ©   (2009-09-01 22:30) [55]

Короче, вот реализация, которая меня более-менее устроила, по крайней мере разобрала все имеющиеся ключи у меня в реестре.

unit uCmdLineHelper;

interface

uses
 Windows, SysUtils;

function SplitCommandLine(CmdLine: string; var FileName, Arguments: string): boolean;

implementation

function GetParamStr(P: PChar; var Param: string): PChar;
var
 i, Len: Integer;
 Start, S: PChar;
begin
 while True do
 begin
   while (P[0] <> #0) and (P[0] <= " ") do
     Inc(P);
   if (P[0] = """) and (P[1] = """) then Inc(P, 2) else Break;
 end;
 Len := 0;
 Start := P;
 while P[0] > " " do
 begin
   if P[0] = """ then
   begin
     Inc(P);
     while (P[0] <> #0) and (P[0] <> """) do
     begin
       Inc(Len);
       Inc(P);
     end;
     if P[0] <> #0 then
       Inc(P);
   end
   else
   begin
     Inc(Len);
     Inc(P);
   end;
 end;

 SetLength(Param, Len);

 P := Start;
 S := Pointer(Param);
 i := 0;
 while P[0] > " " do
 begin
   if P[0] = """ then
   begin
     Inc(P);
     while (P[0] <> #0) and (P[0] <> """) do
     begin
       S[i] := P^;
       Inc(P);
       Inc(i);
     end;
     if P[0] <> #0 then Inc(P);
   end
   else
   begin
     S[i] := P^;
     Inc(P);
     Inc(i);
   end;
 end;

 Result := P;
end;

//------------------------------------------------------------------------------

function ParamCountFromCommandLine(CmdLine: PChar): Integer;
var
 S: string;
 P: PChar;
begin
 P := CmdLine;
 Result := 0;
 while True do
 begin
   P := GetParamStr(P, S);
   if S = "" then Break;
   Inc(Result);
 end;
end;

//------------------------------------------------------------------------------

function ParamStrFromCommandLine(CmdLine: PChar; Index: Integer): string;
var
 P: PChar;
begin
 P := CmdLine;
 while True do
 begin
   P := GetParamStr(P, Result);
   if (Index = 0) or (Result = "") then Break;
   Dec(Index);
 end;
end;

//------------------------------------------------------------------------------

procedure SplitCommandLine1(const CmdLine: string; var ExeName, Params: string);
var
 Buffer: PChar;
 Cnt, I: Integer;
 S: string;
begin
 ExeName := "";
 Params := "";
 Buffer := StrPCopy(StrAlloc(Length(CmdLine) + 1), CmdLine);
 try
   Cnt := ParamCountFromCommandLine(Buffer);
   if Cnt > 0 then begin
     ExeName := ParamStrFromCommandLine(Buffer, 0);
     for I := 1 to Cnt - 1 do begin
       S := ParamStrFromCommandLine(Buffer, I);
       if Pos(" ", S) > 0 then S := """ + S + """;
       Params := Params + S;
       if I < Cnt - 1 then Params := Params + " ";
     end;
   end;
 finally
   StrDispose(Buffer);
 end;
end;

//------------------------------------------------------------------------------

procedure SplitCommandLine2(CmdLine: string; var FilePath, Arguments: string);
var
 i: integer;
 TempStr: string;
begin
 CmdLine := Trim(CmdLine);
 FilePath := "";
 Arguments := "";
 if CmdLine = "" then Exit;
 CmdLine := StringReplace(CmdLine, """, "", [rfReplaceAll]);
 TempStr := "";
 for i := 1 to Length(CmdLine) do
   begin
     TempStr := TempStr + CmdLine[i];
     if FileExists(TempStr) then
       begin
         FilePath := TempStr;
         Delete(CmdLine, 1, i);
         Arguments := Trim(CmdLine);
         Break;
       end;
   end;
end;

//------------------------------------------------------------------------------

function ExpandEnvironment(const CmdLine: string): string;
var
 Buff: array[0..MAX_PATH - 1] of Char;
 Ret: DWORD;
begin
 Ret := ExpandEnvironmentStrings(PChar(CmdLine), Buff, MAX_PATH);
 if Ret = 0 then
   Result := CmdLine
 else
   SetString(Result, Buff, Ret);
end;

//------------------------------------------------------------------------------

function SearchPath(FileName: string): string;
var
 Buff: array[0..MAX_PATH] of Char;
 n: PChar;
 Len: integer;
begin
 Result := "";

 if FileExists(FileName) then
   begin
     Result := FileName;
     exit;
   end;

 Len := Windows.SearchPath(nil, PChar(FileName), ".exe", MAX_PATH, Buff, n);
 if Len > 0 then
   SetString(Result, Buff, Len);
end;

//------------------------------------------------------------------------------

function SplitCommandLine(CmdLine: string; var FileName, Arguments: string): boolean;
begin
 result := false;
 CmdLine := ExpandEnvironment(CmdLine);
 SplitCommandLine1(CmdLine, FileName, Arguments);
 FileName := SearchPath(FileName);
 if FileName = "" then
   SplitCommandLine2(CmdLine, FileName, Arguments);
 Result := FileName <> "";
end;

end.


 
Игорь Шевченко ©   (2009-09-01 23:21) [56]

Система парсит строку запуска слева направо (что, в общем-то очевидно), если имя файла не заключено в кавычки, то после очередного найденного пробела запускается цикл поиска \, если символ найден, то пробел считается частью имени файла, если не найден, то считается, что имя файла закончилось до этого пробела.

Поэтому файл "run me please.exe" без кавычек запустить не получится


 
DVM ©   (2009-09-01 23:45) [57]


> Игорь Шевченко ©   (01.09.09 23:21) [56]


> Поэтому файл "run me please.exe" без кавычек запустить не
> получится

Но только не в случае запуска такой строки из реестра!

Можете проверить:
1) В папке Windows создайте копию блокнота с именем run me.exe
2) создайте в ключе HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run новый параметр типа REG_SZ со значением run me please.txt
3) Логофф/логон юзера

Запустится блокнот и предложит создать файл please.txt


 
Eraser ©   (2009-09-02 00:08) [58]

> [56] Игорь Шевченко ©   (01.09.09 23:21)

это в давно устаревших версиях ОС.


 
DVM ©   (2009-09-02 00:50) [59]

Небольшая поправка к [55]. Как раз для того, чтобы он корректно воспринимал строки вида run me please.txt

function SearchPath(FileName: string): string;
var
 Buff: array[0..MAX_PATH - 1] of Char;
 n: PChar;
 Len: integer;
begin
 Result := "";

 if FileExists(FileName) then
   begin
     Result := FileName;
     exit;
   end;

 Len := Windows.SearchPath(nil, PChar(FileName), nil, MAX_PATH, Buff, n);
 if Len > 0 then
   SetString(Result, Buff, Len);
end;

//------------------------------------------------------------------------------

procedure SplitCommandLine2(CmdLine: string; var FilePath, Arguments: string);
var
 i: integer;
 TempStr, a, b: string;
begin
 CmdLine := Trim(CmdLine);
 FilePath := "";
 Arguments := "";
 if CmdLine = "" then Exit;
 CmdLine := StringReplace(CmdLine, """, "", [rfReplaceAll]);
 TempStr := "";
 for i := 1 to Length(CmdLine) do
   begin
     TempStr := TempStr + CmdLine[i];
     a := TempStr;
     a := SearchPath(a);
     if FileExists(a) then
       begin
         FilePath := a;
         Delete(CmdLine, 1, Length(TempStr));
         Arguments := Trim(CmdLine);
         Break;
       end;
   end;

 if FilePath <> "" then Exit;

 TempStr := "";
 for i := 1 to Length(CmdLine) do
   begin
     TempStr := TempStr + CmdLine[i];
     b := TempStr + ".exe";
     b := SearchPath(b);
     if FileExists(b) then
         begin
           FilePath := b;
           Delete(CmdLine, 1, Length(TempStr));
           Arguments := Trim(CmdLine);
           Break;
         end;
   end;
end;


 
Игорь Шевченко ©   (2009-09-02 01:13) [60]


> это в давно устаревших версиях ОС.


Э...а что это - "давно устаревшие версии ОС" ?


 
Игорь Шевченко ©   (2009-09-02 01:20) [61]

DVM ©   (01.09.09 23:45) [57]

Действительно выполняется. Я скопировал notepad.exe в run me please.exe и в реестре создал параметр со значением run me please foo
Запустился блокнот. Windows XP SP3.
Осталось выяснить, это поведение происходит на уровне CreateProcess или таки несколько на более высоком уровне. Но пример писать лень.


 
brother ©   (2009-09-02 05:29) [62]

я воообще проблеммы не понимаю...

C:\Program Files\Flashget\flashget.exe /min
>
> Я никак не могу понять, как он понимает где здесь имя файла,
> где параметр?
Кавычек нет, слеш в параметре тоже необязателен.

C:\Program Files\Flashget\ - путь тк он корректен (пробел тож в счет)
flashget.exe - имя файла тк. есть расширение и фактически  C:\Program Files\Flashget\flashget.exe он присутствует
/min - dct все что после пробела - параметр...
я что-то упустил?


 
brother ©   (2009-09-02 05:34) [63]

имхо, кавычками пользователь явно объявляет, что я вляется именем файла и путями, исключая нужность парсить...

> Осталось выяснить, это поведение происходит на уровне CreateProcess
> или таки несколько на более высоком уровне.

имхо - CreateProcess...


 
DVM ©   (2009-09-02 07:51) [64]


> brother ©   (02.09.09 05:29) [62]


> я что-то упустил?

Упустил тот момент, что пути, которые я разбираю, уже имеются в реестре, и их внешний вид вне зависимости от моих желаний и может быть от нормального до вот такого: run me please.exe,
но т.к. с точки зрения системы такое допустимо, то мне надо так же. Только запускать эти файла не надо, мне иконки с них тащить надо, а это возможно только вытащив полный и нормальный путь к файлу.


 
DVM ©   (2009-09-02 07:56) [65]


> имхо - CreateProcess...

Если бы это было реализовано в CreateProcess, то Пуск -> Выполнить хватало бы пути вида run me please.exe. Однако ж не понимает, в XP по крайней мере. Следовательно ни CreateProcess, ни даже ShellExecute не обладают способностью понимать такие пути. Очевидно, эксплорер разбирает сначала сам, а потом уже ShellExecute.


 
Skyle ©   (2009-09-02 08:16) [66]


> DVM ©   (02.09.09 07:56) [65]
Очевидно, эксплорер разбирает сначала сам, а потом уже ShellExecute.

В этом смысле интересно было бы попробовать альтернативный шелл, астон какой-нибудь или far.


 
brother ©   (2009-09-02 08:39) [67]

> а это возможно только вытащив полный и нормальный путь к
> файлу.

тогда [62] +
начинать слева до первого \ , тк имя файла без расширения не предвидится)


 
DVM ©   (2009-09-02 08:42) [68]


> brother ©   (02.09.09 08:39) [67]

Да я уже собственно сделал. Работает пока без нареканий. Вытащил все пути.


 
brother ©   (2009-09-02 08:42) [69]

> Работает пока без нареканий. Вытащил все пути.

парсишь слева или справа?


 
DVM ©   (2009-09-02 08:45) [70]


> парсишь слева или справа?

слева, прибавляя по одному символу, каждый раз проверяя нет ли файла среди доступных в Path и т.д. каталогах, если нет, то проверяю еще раз прибавив .exe на конце.


 
Anatoly Podgoretsky ©   (2009-09-02 09:51) [71]

> brother  (02.09.2009 05:29:02)  [62]

Упустил, расширение тоже не обязательно и тут возможны варианты, подразумевалось .ехе а запустился .сом


 
Anatoly Podgoretsky ©   (2009-09-02 09:53) [72]

> DVM  (02.09.2009 07:51:04)  [64]

И этот момент тоже упустил.


 
Anatoly Podgoretsky ©   (2009-09-02 09:57) [73]

> DVM  (02.09.2009 08:45:10)  [70]

Это же неправильно (по символам и с прибавлением .exe), могут быть file.exe и filename.exe в одной папке и получается, что вместо filename.exe будет использовано file.exe и такая ситуация норма.


 
DVM ©   (2009-09-02 10:56) [74]


> Anatoly Podgoretsky ©


> И этот момент тоже упустил.


> могут быть file.exe и filename.exe в одной папке и получается

Я об этом писал выше, и именно поэтому я говорил парсить справа налево, хотя это тоже не 100% гарантия. Но похоже тут уже ничего не поделаешь.


 
DVM ©   (2009-09-02 10:58) [75]


> Anatoly Podgoretsky ©   (02.09.09 09:51) [71]
>
> > brother  (02.09.2009 05:29:02)  [62]
>
> Упустил, расширение тоже не обязательно и тут возможны варианты,
>  подразумевалось .ехе а запустился .сом

Об этом тоже думал, но пока решил COM не учитывать. Если по хорошему там еще и BAT и CMD файлы.


 
Anatoly Podgoretsky ©   (2009-09-02 11:10) [76]

> DVM  (02.09.2009 10:56:14)  [74]

Ну я могу повторить - полного решения нет.


 
Anatoly Podgoretsky ©   (2009-09-02 11:11) [77]

> DVM  (02.09.2009 10:58:15)  [75]

Естественно, что это подразумевается.


 
brother ©   (2009-09-02 11:41) [78]

> пути, которые я разбираю, уже имеются в реестре


> Если по хорошему там еще и BAT и CMD файлы.

О_О и иконки из них тырить ваще круто)


 
DVM ©   (2009-09-02 12:11) [79]


> brother ©   (02.09.09 11:41) [78]


> О_О и иконки из них тырить ваще круто)

А что у тебя в окне папки BAT и CMD файлы не обозначены иконками? Прямо так черное место вместо иконки?


 
brother ©   (2009-09-02 13:52) [80]

> Прямо так черное место вместо иконки?

мы же понимаем, откуда система берет эти иконки)


 
Eraser ©   (2009-09-02 14:13) [81]

> [76] Anatoly Podgoretsky ©   (02.09.09 11:10)

ну почему же? магия там никакая не применяется, думаю у MS примерно такой же подход, как в этой ветке описан. в крайнем случае можно реверс-инженеринг сделать и глянуть как оно там у них устроено.


 
Leonid Troyanovsky ©   (2009-09-03 09:20) [82]


> DVM ©   (02.09.09 10:56) [74]

> тут уже ничего не поделаешь.

Думаю, что надо внимательно смотреть в сторону SHGetFileInfo.
А если парсить, то справа налево, только не по одному символу,
а до пробела, кавычек или до недопустимого в имени файла символа.

--
Regards, LVT.



Страницы: 1 2 3 вся ветка

Форум: "Прочее";
Текущий архив: 2009.11.01;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.7 MB
Время: 0.009 c
2-1252953846
cyberspy85
2009-09-14 22:44
2009.11.01
не запускается скрипт


9-1183538262
@!!ex
2007-07-04 12:37
2009.11.01
Преобразовать кооринаты.


15-1250747781
Медвежонок Пятачок
2009-08-20 09:56
2009.11.01
Первый канал отжигает


2-1249031312
Nel
2009-07-31 13:08
2009.11.01
Многострочная надпись и иконка на кнопке


4-1220776855
Дмитрий Белькевич
2008-09-07 12:40
2009.11.01
Количество записанных байт на жесикий





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский