Total Commander Forum Index Total Commander
Форум поддержки пользователей Total Commander
Сайты: Все о Total Commander | Totalcmd.net | Ghisler.com | RU.TCKB
 
 RulesRules   SearchSearch   FAQFAQ   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

[ Статья ] Находим местоположение WINCMD.INI
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    Total Commander Forum Index -> Написание плагинов для Total Commander printer-friendly view
View previous topic :: View next topic  
Author Message
mozers



Joined: 16 Dec 2004
Posts: 82
Location: с Нижнего

Post (Separately) Posted: Sat Feb 05, 2005 08:43    Post subject: [ Статья ] Находим местоположение WINCMD.INI Reply with quote

Уважаемые авторы замечательных плагинов и полезных утилит!
Большинству из ваших программ требуется указание точного местоположения файла TOTALCMD.EXE и INI файлов настройки Коммандера.

Каждый автор ищет решение этой проблемы по своему:
Одни (самые умные Wink вообще ничего не ищут, а требуют от пользователя вручную заводить эти пути. Решение, конечно, крайне примитивное. И пользователь может ошибиться с указанием путей, да и тулза оказывается жестко привязанной к одному месту. Если пользователь имеет несколько настроенных профилей ТС, то он вынужден держать несколько копий вашей программы - для каждого профиля отдельно Sad
Другие (слава Богу - таких уже почти не осталось) тупо считают, что эти файлы могут называться только wincmd.ini и wcx_ftp.ini и лежат они исключительно в %WINDIR%. Просто нет слов...
Третьи (кто посообразительней), пытаются анализировать содержимое ветки [HKEY_CURRENT_USER\Software\Ghisler\Total Commander] и увы, тоже не всегда бывают правы.
Этой мини-статейкой я попытаюсь проанализировать опыт тех и других и сделать некоторые выводы. Надеюсь они пригодятся вам в дальнейших разработках.

Итак, начнем с самого простого - TOTALCMD.EXE
Он ВСЕГДА находится по %COMMANDER_PATH%/TOTALCMD.EXE
Учтите только что %COMMANDER_PATH% имеется в переменных окружения только тогда, когда ваша прога стартует из ТС. Для авторов плагинов это всегда - факт, утилита же может стартовать и не из ТС.
Уважаемые авторы, заставьте своего пользователя хотя бы в первый раз запустить вашу тулзу из ТС - она запишет найденный путь, и в дальнейшем ее можно будет стартовать откуда угодно. Поверьте, 99% пользователей будут запускать вашу утилиту именно из ТС, а автоматически найденный ею путь будет лишним доказательством вашего профессионализма!

Теперь про поиск INI файлов
Единственно правильный вариант на сегодня:
  1. Анализируем командную строку ТС, ищем в ней ключи /I и /F и считываем пути к INI оттуда.
  2. Если в ком.строке ключи не найдены, то проверяем, есть ли в файле %COMMANDER_PATH%/wincmd.ini ключ UseIniInProgramDir (Еще одна беда, свалившаяся на нашу голову вместе с версией 6.5). Если есть - то ищем INI файлы в соответствии со значением этого ключа (подробности - в HELP).
  3. Если там - пусто, то смотрим в [HKEY_CURRENT_USER\Software\Ghisler\Total Commander].
  4. Если и там - пусто, то INI лежат в %WINDIR% и названия их - wincmd.ini и wcx_ftp.ini
Важные замечания
  1. Ключи ком.строки /I и /F могут быть в любом регистре, причем второй по очереди ключ может быть и без слеша.
  2. Пути в ключах ком.строки и реестра могут задаваться как полным путем, так и относительным. В путях можно использовать любые переменные окружения, включая %COMMANDER_PATH%. Пути могут быть заданы и как LongNames и в формате 8.3
  3. Если пути к файлам заданы явно (ключах ком.строки или реестре), то файлы инициализации могут иметь ЛЮБОЕ имя.
Ну а теперь - поподробнее про анализ ком.строки
Для плагина TC все решается сравнительно просто. А все потому, что он выполняется внутри процесса TC и поэтому получить командную строку можно просто вызвав API-шную функцию GetCommandLine. Кто понимает, о чем я говорю, тому не составит труда извлечь из нее нужные параметры.
Для внешней утилиты все значительно сложнее Sad Решается эта проблема с использованием ловушек (hooks), труб (pipes) и прочих мудреных вещей. Пройти все круги ада и построить рабочую программу смог только Alexander Asyabrik aka Shura (я о ReloadTC). Других, увы, не знаю Sad

Так вот обломали нас в самом начале пути Sad
Однако, есть возможность получить вожделенные пути и несколько иным способом, если мы вспомним о том, что сам ТС прекрастно осведомлен о местоположении своих INI файлов - достаточно взглянуть на окошко "About".
Итак, вкратце: Находим окно активного экземпляра ТС, шлем ему через SendMessage команду cm_About, считываем через GetWindowText драгоценную инфу, закрываем окошко About. Если на время выполнения этой процедуры запретить обновление окна, то получится почти незаметно Wink
Намеренно не говорю о подводных камнях (а то обсуждать будет нечего Wink, а вот положительные стороны данного подхода - налицо. Одним махом находим местоположения обоих INI файлов совершенно независимо от того, как и где задал их пользователь.

P.S. Всего этого разговора могло бы и не быть, если бы глубокоуважаемый Christian Ghisler ввел в обиход пару псевдо-переменных
$MAIN_INI и $FTP_INI (подобно имеющимся уже $MYPICTURES, $LOCAL_APPDATA, $COMMON_APPDATA, и т.п.). Ему то это сделать - плевое дело!
Представьте, как было бы здорово!
Как вам, к примеру, такая команда в меню "Запуск" ?:
Code:

  Команда: disk:/path/MySuperEditor.exe
Параметры: $MAIN_INI $FTP_INI

Кому так же больно как мне - отпишите Орлу нашему...
Back to top
View user's profile Send private message
TSergey



Joined: 24 Jan 2005
Posts: 49

Post (Separately) Posted: Sat Feb 05, 2005 19:01    Post subject: Reply with quote

Может сюда же выложить функции для плагинов?
Сам сразу и начну:

Code:
function GetFtpIniFileName: string;
var
  s, s1, s2 :string;
  a: array [0..MAX_PATH] of char;
  i, j: integer;
  EscEn, QuoteStr, UseProgDir: boolean;
  c: char;
  reg: TRegistry;
begin
  // Разбор командной строки
  s := StrPas(GetCommandLine);

  i := pos('f=', s);
  if i  = 0 then  i := pos('F=', s);

  s1 := '';

  if i > 0
  then begin
    i := i + 2;
    EscEn := false;
    QuoteStr := false;
    j := length(s);
    // Разворачиваем параметр с поддержкой кавычек
    while (i <= j) do
    try
      c := s[i];
      case c of
        #9, ' ':
          if QuoteStr
          then if EscEn
            then begin
              s1 := s1 + '\'+ c;
              EscEn := false;
            end
            else s1 := s1 + c
          else break;

        '"':
          if EscEn
          then s1 := s1 + '"'
          else QuoteStr := not QuoteStr;

        '\':
          if EscEn
          then begin
            s1 := s1 + '\';
            EscEn := false;
          end
          else EscEn := true;

        else if EscEn
          then begin
            s1 := s1 + '\'+ c;
            EscEn := false;
          end
          else s1 := s1 + c
      end;
    finally
      inc(i);
    end;

    if EscEn then s1 := s1 + '\';

  end;


  UseProgDir := false;

  if s1 = ''
  then begin
    // Обрабатываем каталог Тотал Командера
    s := '%COMMANDER_PATH%\wincmd.ini';
    s2 := '%COMMANDER_PATH%\wcx_ftp.ini';

    ExpandEnvironmentStrings(PChar(s), a, MAX_PATH);
    i := GetPrivateProfileInt('Configuration', 'UseIniInProgramDir', 0, a);
    UseProgDir := (i and 2) <> 0;
    if (i and 4) <> 0 then s1 := s2;
  end;

  if s1 = ''
  then begin
    // Проверяем реестр

    try
      Reg := TRegistry.Create(KEY_READ);
      try
        Reg.RootKey := HKEY_CURRENT_USER;
        if Reg.OpenKeyReadOnly('\Software\Ghisler\Total Commander')
        then s1 := Reg.ReadString('FtpIniName')
        else s1 := '';
      finally
        Reg.Free;
      end;
    except
      s1 := '';
    end;

    if (s1 = '')
    then if UseProgDir
    then s1 := s2
    else s1 := 'wcx_ftp.ini';
  end;

  if (copy(s1, 1, 2) = '.\')
  then begin
    delete(s1, 1, 2);
    s1 := '%COMMANDER_PATH%\' + s1;
  end;

  ExpandEnvironmentStrings(PChar(s1), a, MAX_PATH);
  result := strpas(a);
end;



ЗЫ. Вроде проверил работу на своем плагине, но ошибки могут быть.
ЗЗЫ. Анекдот про "длинный_мнемоничный_идентификатор_номер_один" - знаю. Twisted Evil


Last edited by TSergey on Tue Feb 15, 2005 08:31; edited 2 times in total
Back to top
View user's profile Send private message
SCHMaster



Joined: 15 Dec 2004
Posts: 296
Location: Киев

Post (Separately) Posted: Sun Feb 06, 2005 04:59    Post subject: Reply with quote

%USERPROFILE%
Еще такая хрень бывает... Под ХР и 2К.
Back to top
View user's profile Send private message
mozers



Joined: 16 Dec 2004
Posts: 82
Location: с Нижнего

Post (Separately) Posted: Sun Feb 06, 2005 14:03    Post subject: Reply with quote

SCHMaster
Угу. С %USERPROFILE%, как, впрочем, и со всеми остальными переменными окружения (%TEMP%, %ProgramFiles%, ...) все однозначно.
Если они присутствуют в ключах ком.строки или реестра (в ком.строке, в отличии от реестра, длинные пути надо обязательно задавать в кавычках), то Тотал их понимает, а значит и ваша прога должна их знать...
В общем все учесть - с ума сойти можно... И я все больше склоняюсь к тому, чтоб грабить инфу с About.
Back to top
View user's profile Send private message
Nik



Joined: 01 Jan 2005
Posts: 574
Location: Киров

Post (Separately) Posted: Sun Feb 06, 2005 15:13    Post subject: Reply with quote

В интерфейсе Lister-плагинов есть такая структура:

Code:
 
 type

  tListDefaultParamStruct=record

    size,

    PluginInterfaceVersionLow,

    PluginInterfaceVersionHi:longint;

    DefaultIniName:array[0..MAX_PATH-1] of char;

  end;


Так вот, есть извлечь путь к DefaultIniName, то получите каталог, где лежат Ini файлы TC. И никакой лишней мороки... Если конечно имена файлов стандартные.
Back to top
View user's profile Send private message
CaptainFlint



Joined: 14 Dec 2004
Posts: 5813
Location: Москва

Post (Separately) Posted: Sun Feb 06, 2005 15:52    Post subject: Reply with quote

SAM
Грабить из About'а может не получиться, если именно в это время, например, в Тотале открыт модальный диалог. В лучшем случае ничего не произойдёт, в худшем - крэш.
Nik
Это путь к INI-файлу настроек самого плагина, а не всего Тотала.
Back to top
View user's profile Send private message
Alextp



Joined: 06 Feb 2005
Posts: 4822

Post (Separately) Posted: Sun Feb 06, 2005 18:37    Post subject: Пример кода Reply with quote

Предлагаю Delphi-функции нахождения путей к wincmd.ini и wcx_ftp.ini.
Из исходника TC Plugins Manager, в нем все работает. Если путь, возвращаемый функцией, не найден, то программа запрашивает путь у пользователя.

Модули RegProc.pas/SProc.pas, которые здесь используются, высылаются емейлом.

Code:
function tcDefDir: string;
begin
  //поправка SAM-а, чтобы путь брался из запущенного TC
  Result:= SProc.SExpandVars('%COMMANDER_PATH%');
  //брать из реестра
  if Pos(':\', Result)=0 then
  Result:=
    GetRegKeyStr(HKEY_CURRENT_USER, 'Software\Ghisler\Total Commander', 'InstallDir',
    GetRegKeyStr(HKEY_LOCAL_MACHINE, 'Software\Ghisler\Total Commander', 'InstallDir',
      'C:\TotalCmd'));
end;

function tcDefExe: string;
begin
  Result:= tcDefDir+'\Totalcmd.exe';
end;

function tcDefIni: string;
begin
  Result:=
    GetRegKeyStr(HKEY_CURRENT_USER, 'SOFTWARE\Ghisler\Total Commander', 'IniFileName',
    GetRegKeyStr(HKEY_LOCAL_MACHINE, 'SOFTWARE\Ghisler\Total Commander', 'IniFileName',
    'wincmd.ini'));
  if Pos('\', Result)=0 then Insert('%windir%\', Result, 1);
  //если путь записан как ".\Wincmd.ini":
  if Pos('.\', Result)=1 then
    SReplace(Result, '.', tcDefDir);
  Result:= SExpandVars(Result);
end;

function tcDefIniFtp: string;
begin
  Result:=
    GetRegKeyStr(HKEY_CURRENT_USER, 'SOFTWARE\Ghisler\Total Commander', 'FtpIniName',
    GetRegKeyStr(HKEY_LOCAL_MACHINE, 'SOFTWARE\Ghisler\Total Commander', 'FtpIniName',
    'wcx_ftp.ini'));
  if Pos('\', Result)=0 then Insert('%windir%\', Result, 1);
  //если путь записан как ".\Wincmd.ini":
  if Pos('.\', Result)=1 then
    SReplace(Result, '.', tcDefDir);
  Result:= SExpandVars(Result);
end;

_________________
UniViewer - SynWrite - CudaText - LogViewer


Last edited by Alextp on Wed Oct 19, 2005 23:40; edited 2 times in total
Back to top
View user's profile Send private message
TSergey



Joined: 24 Jan 2005
Posts: 49

Post (Separately) Posted: Sun Feb 06, 2005 18:43    Post subject: Reply with quote

Alextp, а где обработка ситуации, когда ini-файлы передаются в командной строке?

SCHMaster, SAM: Все переменные легко разворачиваются в функции ExpandEnvironmentStrings.
Back to top
View user's profile Send private message
Alextp



Joined: 06 Feb 2005
Posts: 4822

Post (Separately) Posted: Sun Feb 06, 2005 18:52    Post subject: Reply with quote

TSergey wrote:
Alextp, а где обработка ситуации, когда ini-файлы передаются в командной строке?

Нету. Smile

Подразумевается, что как и в комстроке TC, пользователь сам укажет в PlugMan-е этот ini-файл (через кнопку "Обзор").
_________________
UniViewer - SynWrite - CudaText - LogViewer
Back to top
View user's profile Send private message
TSergey



Joined: 24 Jan 2005
Posts: 49

Post (Separately) Posted: Sun Feb 06, 2005 18:54    Post subject: Reply with quote

Alextp wrote:
TSergey wrote:
Alextp, а где обработка ситуации, когда ini-файлы передаются в командной строке?

Нету. Smile

Подразумевается, что как и в комстроке TC, пользователь сам укажет в PlugMan-е этот ini-файл (через кнопку "Обзор").
А смысл заставлять пользователя что-то лишнее вводить, если есть вполне нормальный автоматический способ?
Back to top
View user's profile Send private message
Alextp



Joined: 06 Feb 2005
Posts: 4822

Post (Separately) Posted: Sun Feb 06, 2005 18:57    Post subject: Reply with quote

Ну, ты прав, надо бы еще в ф-ции tcDefIni обрабатывать комстроку TC...
Back to top
View user's profile Send private message
Nik



Joined: 01 Jan 2005
Posts: 574
Location: Киров

Post (Separately) Posted: Sun Feb 06, 2005 20:45    Post subject: Reply with quote

CaptainFlint wrote:

Nik
Это путь к INI-файлу настроек самого плагина, а не всего Тотала.


Да, но по-умолчанию Total предлагает размещать файлы настройки плагина в той же папке, где и свои собственные... Проверено на AmpView: ранние версии читали цвет фона Lister из файлов конфигурации, а путь к ним я определял именно таким способом...
Back to top
View user's profile Send private message
Gosha



Joined: 02 Feb 2005
Posts: 11

Post (Separately) Posted: Sun Feb 06, 2005 21:57    Post subject: Reply with quote

Разрешите высказать свое мнение.
Если кому либо было не лень писать командную строку для запуска TC и в ней указать полный путь до INI файлов, то может его не очень смутит тот факт, что левые программы не всегда находят их. И может быть им даже будет также не лень указать где эти файла всетаки находятся.
Back to top
View user's profile Send private message
TSergey



Joined: 24 Jan 2005
Posts: 49

Post (Separately) Posted: Sun Feb 06, 2005 22:12    Post subject: Reply with quote

Gosha wrote:
Разрешите высказать свое мнение.
Если кому либо было не лень писать командную строку для запуска TC и в ней указать полный путь до INI файлов, то может его не очень смутит тот факт, что левые программы не всегда находят их. И может быть им даже будет также не лень указать где эти файла всетаки находятся.
Хороший подход: пользователи будут довольны и благодарны. Twisted Evil
Back to top
View user's profile Send private message
mozers



Joined: 16 Dec 2004
Posts: 82
Location: с Нижнего

Post (Separately) Posted: Mon Feb 07, 2005 00:25    Post subject: Reply with quote

CaptainFlint
Quote:
Грабить из About'а может не получиться, если именно в это время, например, в Тотале открыт модальный диалог

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

Nik
Лишь путь Sad А имя?

Gosha
Quote:
Если кому либо было не лень писать командную строку для запуска TC

Если кому то было не лень написать в своем плагине/утилите процедуру обнаружения пути к INI файлам, то он получил еще плюсом добрую половину благодарных пользователей, покоренных мастерством автора.
Кстати, по моим данным, у более чем 50 тысяч пользователей (большинство из которых - новички), путь к INI задается с ярлыка и выглядит приблизительно так:
С:\Program Files\Total Commander XP\Profiles\Prof\main.ini

А, впрочем, не хватает ума определить правильно - не определяйте вообще! Лучше позволить пользователю задать путь вручную, чем мучится с неработоспособной прогой.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Total Commander Forum Index -> Написание плагинов для Total Commander All times are GMT + 4 Hours
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group