Как в *.wcx узнать путь к Wincmd.ini?

Только для тех, кто пишет плагины под Total Commander. Обмен опытом, решение проблем.

Модераторы: Avada, CaptainFlint, Nik, d-view, Моторокер

vserd
Сообщения: 118
Зарегистрирован: Вт апр 26, 2005 16:54

Как в *.wcx узнать путь к Wincmd.ini?

Сообщение vserd »

1. Есть архиваторный плугин.
Как в *.wcx узнать путь к Wincmd.ini?

2. Есть несколько копий Тотала, у которых разные файлы настроек. (заданы через параметры командной строки)
Как в *.wcx узнать путь к Wincmd.ini в данной копии?

Должна же быть какая-то возможность?
Варианты решения подходят как на C++ так и на Delphi
Аватара пользователя
Parcan
Сообщения: 399
Зарегистрирован: Ср дек 15, 2004 16:39
Откуда: Russian

Сообщение Parcan »

vserd

поищи в этой ветке помоему было обсуждение алгоритма и даже с примерами.
vserd
Сообщения: 118
Зарегистрирован: Вт апр 26, 2005 16:54

Сообщение vserd »

А в какой конкретно (или приблизительно)?
Я посомтрел на заголовки тем, ничего "завлекательного" не нашел. :(
А читать все темы подряд не очень хочется. времени на разработку плугина не очень много, так что на 90% мусора время тратить не хочется.
Аватара пользователя
D1P
Сообщения: 2987
Зарегистрирован: Пн дек 20, 2004 18:30
Откуда: Тбилиси
Контактная информация:

Сообщение D1P »

vserd
Сообщения: 118
Зарегистрирован: Вт апр 26, 2005 16:54

Сообщение vserd »

D1P
:(((
темы которую вы запросили не существует
видно вся проблема в русских буквах. Что там должно быть?
Аватара пользователя
SCHMaster
Сообщения: 296
Зарегистрирован: Ср дек 15, 2004 02:32
Откуда: Киев
Контактная информация:

Сообщение SCHMaster »

vserd
Да не морочь голову. Если ини-файл указан в параметрах запуска, то спокойно его получаешь через ParamStr
vserd
Сообщения: 118
Зарегистрирован: Вт апр 26, 2005 16:54

Сообщение vserd »

SCHMaster
Если ини-файл указан в параметрах запуска, то спокойно его получаешь через ParamStr
хм. Я почему-то считал и считаю что ParamStr для Dll (wcx) не соответствует тому что передается в EXE
Аватара пользователя
SCHMaster
Сообщения: 296
Зарегистрирован: Ср дек 15, 2004 02:32
Откуда: Киев
Контактная информация:

Сообщение SCHMaster »

vserd
Ага... А твоя DLL в чьем адресном пространстве находится? Ес-сно какой-нить программы :). Неверишь - проверь :)
Аватара пользователя
D1P
Сообщения: 2987
Зарегистрирован: Пн дек 20, 2004 18:30
Откуда: Тбилиси
Контактная информация:

Сообщение D1P »

vserd писал(а):D1P
:(((
темы которую вы запросили не существует
видно вся проблема в русских буквах. Что там должно быть?
Поищи по форуму, там такая тема уже поднималась (на неё и ссылка была), всё обсосали до последней косточки.

Модераторам: неплохо бы сходные темы объединять во избежание замусоривания.
TSergey
Сообщения: 49
Зарегистрирован: Пн янв 24, 2005 12:22

Сообщение TSergey »

D1P писал(а):
vserd писал(а):D1P
:(((
темы которую вы запросили не существует
видно вся проблема в русских буквах. Что там должно быть?
Поищи по форуму, там такая тема уже поднималась (на неё и ссылка была), всё обсосали до последней косточки.

Модераторам: неплохо бы сходные темы объединять во избежание замусоривания.
Та тема, в которой все обсасывалось - удалена.
Правда не понятно почему.
TSergey
Сообщения: 49
Зарегистрирован: Пн янв 24, 2005 12:22

Сообщение TSergey »

Вот как сделал я. (Для поиска wcx_ftp.ini)

Код: Выделить всё

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
  if FTPIniFileName <> '' //Проверяем кэш (FTPIniFileName - глобальная переменная)
  then begin
    Result := FTPIniFileName;
    exit;
  end;

  // Разбор командной строки
  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 begin
          s1 := Reg.ReadString('FtpIniName');
        end
        else begin
          s1 := '';
        end;
        if S1 = ''
        then begin
          Reg.RootKey := HKEY_LOCAL_MACHINE;
          if Reg.OpenKeyReadOnly('\Software\Ghisler\Total Commander')
          then begin
            s1 := Reg.ReadString('FtpIniName');
          end;
        end;
      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);
  FTPIniFileName := Result;
end;
Аватара пользователя
Maximus
Сообщения: 927
Зарегистрирован: Чт апр 07, 2005 10:51
Откуда: Украина, Кировоградская обл., г. Знаменка
Контактная информация:

Сообщение Maximus »

2TSergey
Че наворотил -- непонятно)) Может оттого что я паскаль уже плохо стал читать. А что имеется в виду под поддержкой кавычек? В Билдере они и так поддерживаются. По крайней мере я никогда по этому поводу ничего дополнительно с командной строкой не делал.

Но зачем там столько кода если путь к ини-файлам и к директории в которую командир проинстален валяются себе в реестре:
HKEY_LOCAL_MACHINE\Software\Ghisler\Total Commander
и здесь тоже чето:
HKEY_CURRENT_USER\Software\Ghisler\Total Commander
Это под 98ой. А как там под ХР для разных юзверей не смотрел.

А вот кто бы мне сказал как без лишних извратов узнать где валяется моя ДЛЛ т.е. откуда была запущена(хочу туды свой ини запихнуть), а то через Application->ExeName() получаю путь к командеру.
vserd
Сообщения: 118
Зарегистрирован: Вт апр 26, 2005 16:54

Сообщение vserd »

Maximus
Но зачем там столько кода если путь к ини-файлам и к директории в которую командир проинстален валяются себе в реестре:
HKEY_LOCAL_MACHINE\Software\Ghisler\Total Commander
А затем что там правильная обработка текущего файла настроек.
К сожалению или скорее к счастью Total Commander поддерживает явное указание пути в командной строке, если там не задано, тогда нужно анализировать битовую маску UseIniInProgramDir, и в зависимости от нее считываем из реестра, а при отсутствии ключа, искать в %windir%.
Вобщем читайте доку, она вам поможет.

А вот кто бы мне сказал как без лишних извратов узнать где валяется моя ДЛЛ т.е. откуда была запущена(хочу туды свой ини запихнуть),
Если изменить вопрос на такой: Куда правильно писать инишник для плугина. Тогда возможно воспользуйтесь структурой
PackDefaultParamStruct.DefaultIniName

DefaultIniName Suggested location+name of the ini file where the plugin could store its data. This is a fully qualified path+file name, and will be in the same directory as the wincmd.ini. It's recommended to store the plugin data in this file or at least in this directory, because the plugin directory or the Windows directory may not be writable!

Либо таким кодом:
С++ из multarc
GetModuleFileName(m_hInstance,szFullPath,MAX_PATH);

GetShortPathName(szFullPath, szPath, MAX_PATH);
m_strMAPath = szPath;

_splitpath(szFullPath,szDrive,szPath,szName,szExt);
strcpy(szExt,"ini");

_makepath(szFullPath,szDrive,szPath,szName,szExt);
m_strIniFile = szFullPath;
Аватара пользователя
Volniy
Сообщения: 585
Зарегистрирован: Ср дек 15, 2004 00:17
Откуда: Местный

Сообщение Volniy »

vserd писал(а):Если изменить вопрос на такой: Куда правильно писать инишник для плугина.
А если все-таки не менять вопрос? Я вот хочу писать свой ини-файл в свою же папку, а не в common. Как тогда поступить?
Аватара пользователя
CaptainFlint
Сообщения: 6239
Зарегистрирован: Вт дек 14, 2004 22:34
Контактная информация:

Сообщение CaptainFlint »

Maximus
А вот кто бы мне сказал как без лишних извратов узнать где валяется моя ДЛЛ
Есть один довольно извращённый способ... Уже не помню, где нашёл, не до конца понимаю, как и почему это работает, но работает.

Итак, заводишь следующую функцию (весь код проверен на VC++ 6):

Код: Выделить всё

extern "C" void * _ReturnAddress();
#pragma intrinsic(_ReturnAddress)

HINSTANCE GetCurrentInstance()
{
    MEMORY_BASIC_INFORMATION mem;
    if (VirtualQuery(_ReturnAddress(), &mem, sizeof(mem)))
    {
        _ASSERTE(mem.Type == MEM_IMAGE);
        _ASSERTE(mem.AllocationBase != NULL);
        return (HINSTANCE)mem.AllocationBase;
    }
    return NULL;
}
Она возвращает текущий HINSTANCE. А потом пихаешь возвращаемый результат в качестве первого параметра в вызов GetModuleFileName(...).
Ответить