Поддержка тоталовских плагинов в своих программах

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

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

Аватара пользователя
Alextp
Сообщения: 4957
Зарегистрирован: Вс фев 06, 2005 17:21

Сообщение Alextp »

DrShark
А страница у него есть?
Кроме немецкой:
http://wiki.speedproject.de/index.php?t ... Commander)
Надо добавить в Вики, но не добавлять же директную ссылку.
DrShark
Сообщения: 911
Зарегистрирован: Сб окт 21, 2006 20:27
Откуда: Kyiv, Ukraine
Контактная информация:

Сообщение DrShark »

У продуктов SpeedProject всё немецкое :) Единственное английское, что я нашёл - это интерфейс SpeedCommander, и то опционально. Патриоты :) А вообще менеджер очень даже хороший.
Аватара пользователя
Alextp
Сообщения: 4957
Зарегистрирован: Вс фев 06, 2005 17:21

Сообщение Alextp »

OK. Добавил в Вики ссылку.
А вообще менеджер очень даже хороший.
Согласен 100%.
Dec
Сообщения: 466
Зарегистрирован: Чт сен 07, 2006 18:56

Сообщение Dec »

Задумал я использовать WDX плагины в одном из своих. Но не знаю, как решить одну проблему. По WDX спецификации после загрузки должна быть вызвана функция ContentSetDefaultParams, а перед выгрузкой ContentPluginUnloading. Поскольку WDX плагин может быть загружен как TC, так и моим плагином одновременно, то эти функции могут быть вызваны дважды. Мы не знаем, какой код помещает разработчик в эти функции, и поскольку у TC и моего плагина одно адресное пространство, то это может привести к повторной инициализации и преждевременной финализации данных, что в конечном счете IMHO может привести к сбоям в работе TC или плагина. Единственное, что я придумал, это копировать перед началом работы с WDX плагином этот плагин и остальное содержимое папки, в которой он лежит, в temp`овую директорию и работать с ним. Как другие решают эту проблему, или это не проблема вовсе?
Аватара пользователя
B4rr4cuda
Сообщения: 376
Зарегистрирован: Вс июн 03, 2007 00:36
Откуда: Россия, Москва

Сообщение B4rr4cuda »

Рекомендую обрабатывать DLLEntryPoint для идентификации загрузчика:

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

procedure DLLEntryPoint(dwReason: DWord);
begin
  case dwReason of
    DLL_PROCESS_ATTACH: ShowMessage('Attaching to process');
    DLL_PROCESS_DETACH: ShowMessage('Detaching from process');
    DLL_THREAD_ATTACH: MessageBeep(0);
    DLL_THREAD_DETACH: MessageBeep(0);
  end;
end;

begin
  { First, assign the procedure to the DLLProc variable }
  DllProc := @DLLEntryPoint;
  { Now invoke the procedure to reflect that the DLL is attaching to the
    process }
  DLLEntryPoint(DLL_PROCESS_ATTACH);
end.
Добавленно:
Сорри, задумался и недопонял суть вопроса. То что выше для самописного плага с поддержкой такой возможности.
ВDLL_PROCESS_ATTACH идентифицируем подключение тоталом,
в DLL_THREAD_ATTACH подключение плагином.

А для твоей ситуации - прожка лоадер+pipes.
Аватара пользователя
B4rr4cuda
Сообщения: 376
Зарегистрирован: Вс июн 03, 2007 00:36
Откуда: Россия, Москва

Сообщение B4rr4cuda »

Как другие решают эту проблему, или это не проблема вовсе?
Может быть проблемой. TotalConsole тоже сначала писалась как wdх, я много мороки получил с FindFirstThread когда тотал подключал плаг отдельным потоком. Ты проведи тесты на каком нить плагине, тогда и узнаешь точно.
Dec
Сообщения: 466
Зарегистрирован: Чт сен 07, 2006 18:56

Сообщение Dec »

в DLL_THREAD_ATTACH подключение плагином.
Reason = DLL_THREAD_ATTACH обозначает только то, что в процессе создан еще один поток. Мой плагин может загружать и вызывать функции из WDX плагина и в основном потоке, так что это ничего не меняет.
А для твоей ситуации - прожка лоадер+pipes
Самому грузить плагин, минуя LoadLibrary? Ну спасибо, я лучше буду через temp директорию работать.
Ты проведи тесты на каком нить плагине, тогда и узнаешь точно.
Сколько плагинов, столько и проблем. То, что в одном плагине сработает, то в другом может привести к access violation. Меня интересует общее универсальное решение.
Аватара пользователя
B4rr4cuda
Сообщения: 376
Зарегистрирован: Вс июн 03, 2007 00:36
Откуда: Россия, Москва

Сообщение B4rr4cuda »

Reason = DLL_THREAD_ATTACH обозначает только то, что в процессе создан еще один поток.
Это означает только то - что библиотеку вызвали потоком.
Мой плагин может загружать и вызывать функции из WDX плагина и в основном потоке, так что это ничего не меняет.
И списки айди этих потоков, процессов можно классифицировать, разделить и понять кто вызывал данный плагин.
Но тебе это не поможет, у тебя другая засада. Это решение для поддержки твоего вопроса из плагина.
Самому грузить плагин, минуя LoadLibrary? Ну спасибо, я лучше буду через temp директорию работать
Насчёт лоадера, ты меня недопонял: пишешь небольшую прожку-прослойку между твоим плагином и вызываемым плагином.
Коннектишься с этой прожкой через трубы (или через что угодно, хоть сокеты используй) и управляешь через неё вызванным плагином(передаёшь ей параметры вызовов, она передаёт плагу и обратно).
Адрессные пространства у тотала и твоей прожки разные - соответственно не будет описанных тобой проблем. А access violation этого плагин-лоадера не затронут тотал...
VadiMGP
Сообщения: 1625
Зарегистрирован: Ср мар 21, 2007 20:58

Сообщение VadiMGP »

Стер, все что написал.

Сорри, я ошибся - неправильно понял вопрос.
VadiMGP
Сообщения: 1625
Зарегистрирован: Ср мар 21, 2007 20:58

Сообщение VadiMGP »

Dec писал(а):Как другие решают эту проблему, или это не проблема вовсе?
Если я правильно понял, ты хочешь работать с WDX плагинами, так же, как SuperWdx, InfoPacker, WDXGuide и т.д.
В практическом плане никто из них, пока, ни на какую проблему (связанную с многократной загрузкой!) не наткнулся.
В теории, может возникнуть плагин, который будет делать с этим проблемы, но это вряд ли.


ЗЫ.
B4rr4cuda писал(а):Это означает только то - что библиотеку вызвали потоком.
Нет. Dec прав, DLL_THREAD_ATTACH обозначает, что в процессе создан еще один поток. В MSDN четко написано
DLL_THREAD_ATTACH Indicates that the current process is creating a new thread.
Аватара пользователя
B4rr4cuda
Сообщения: 376
Зарегистрирован: Вс июн 03, 2007 00:36
Откуда: Россия, Москва

Сообщение B4rr4cuda »

DLL_THREAD_ATTACH обозначает, что в процессе создан еще один поток. В MSDN четко написано
Т.е. подключенная библа очень красиво отслеживает создание\освобождение потоков, процесса подключившего её?
Интересно, надо подумать как это можно использовать....
VadiMGP
Сообщения: 1625
Зарегистрирован: Ср мар 21, 2007 20:58

Сообщение VadiMGP »

B4rr4cuda писал(а):Интересно, надо подумать как это можно использовать....
В общем виде ответ очевиден - когда dll использует данные, специфические для потока. :wink:
Например, многие объекты MFC не могут передавться из потока в поток. И если dll обменивается такими объектами с вызывающим модулем, то они должны быть созданы свои для каждого потока.
Другой пример - допустим есть сервер, который для обслуживания запросов создает потоки. Часть обработки вынесена в dll, который может быть вызван из любого потока. В этом случае иногда в TLS потока (thread local storage) хранят и сам запрос и все, что нужно для его обслуживания.

В любом случае - экзотика.
Dec
Сообщения: 466
Зарегистрирован: Чт сен 07, 2006 18:56

Сообщение Dec »

VadiMGP писал(а):В теории, может возникнуть плагин, который будет делать с этим проблемы
Грамотный программист, к коим я приписываю себя (возможно ошибочно), обязан предусмотреть такую ситуацию.
VadiMGP
Сообщения: 1625
Зарегистрирован: Ср мар 21, 2007 20:58

Сообщение VadiMGP »

Грамотный программист, к коим я приписываю себя (возможно ошибочно), обязан предусмотреть такую ситуацию.
Да ради бога, я же не против. Я бы в данном случае не стал париться, но это потому, что я неграмотный программист.

Но очень мне хотелось бы знать как ты собираешься предусмотреть и другую ситуацию.
Dec писал(а):Единственное, что я придумал, это копировать перед началом работы с WDX плагином этот плагин и остальное содержимое папки, в которой он лежит, в temp`овую директорию и работать с ним.
Большинство моих знакомых программистов, которые пишут dll, независимо от их уровня грамотности, заглядывают в MSDN, где умные (а может и глупые, бог их разберет) дядьки из MS говорят:
Even if an application calls LoadLibrary() for a DLL more than once, the DLL entry point, DllMain(), is called only once and only one DLL_PROCESS_ATTACH entry is created.
А это означает, что DllMain с параметром DLL_PROCESS_ATTACH вызывается только один раз для каждого процесса, а значит тут-то, как правило, и делают инициализацию всех данных, специфических для процесса (если таковые есть, конечно) пребывая в уверенности, что это происходит только один раз в процессе. Но эти дядьки не знают, что может прийти грамотный программист и скопировать dll в другую директорию, создав, тем самым, ситуацию, когда будет две попытки загрузить один и тот же dll из разных мест. Хотя ему, конечно, известно, что такое Dll Hell и, стопроцентно, он знает, что при этом DllMain с DLL_PROCESS_ATTACH будет вызван повторно для того же dll в том же процессе.

Я уже и не спрашиваю, что ты будешь копировать, если в директории плагина вдруг окажется NTFS линк на чертову прорву мегабайт.
Аватара пользователя
Alextp
Сообщения: 4957
Зарегистрирован: Вс фев 06, 2005 17:21

Сообщение Alextp »

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