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 

Поддержка тоталовских плагинов в своих программах
Goto page Previous  1, 2, 3
 
Post new topic   Reply to topic    Total Commander Forum Index -> Написание плагинов для Total Commander printer-friendly view
View previous topic :: View next topic  
Author Message
Dec



Joined: 07 Sep 2006
Posts: 466

Post (Separately) Posted: Sat Sep 01, 2007 18:09    Post subject: Reply with quote

VadiMGP wrote:
я неграмотный программист
2 VadiMGP и остальным:
Извиняюсь, если мои фразы Вас как-либо оскорбили, я ни кого не хотел обижать и ни кого не хотел обвинять в безграмотности.

VadiMGP wrote:
Большинство моих знакомых программистов, которые пишут dll, независимо от их уровня грамотности, заглядывают в MSDN ... DllMain с параметром DLL_PROCESS_ATTACH вызывается только один раз для каждого процесса, а значит тут-то, как правило, и делают инициализацию всех данных
В этом же MSDN паписано:
Quote:
The entry-point function should perform only simple initialization or termination tasks. It must not call the LoadLibrary or LoadLibraryEx function (or a function that calls these functions)… Similarly, the entry-point function must not call the FreeLibrary function (or a function that calls FreeLibrary) during process termination… Do not call the registry functions… do not call malloc… Calling imported functions other than those located in Kernel32.dll may result in problems that are difficult to diagnose. For example, calling User, Shell, and COM functions can cause access violation errors, because some functions in their DLLs call LoadLibrary to load other system components. Conversely, calling those functions during termination can cause access violation errors because the corresponding component may already have been unloaded or uninitialized…Because DLL notifications are serialized, entry-point functions should not attempt to communicate with other threads or processes. Deadlocks may occur as a result.
Я уверен, что Ghisler, как и Вы, тоже знает, что
Quote:
DllMain с параметром DLL_PROCESS_ATTACH вызывается только один раз для каждого процесса
но, тем не менее, добавляет в интерфейс процедуру ContentPluginUnloading. Он объясняет это словами
Quote:
This function was added by request from a user who needs to unload GDI+. It seems that GDI+ has a bug which makes it crash when unloading it in the DLL unload function, therefore a separate unload function is needed.
Т.е. не всегда возможна полная корректная инициализации и финализации в DllMain. Для этого есть ContentSetDefaultParams и ContentPluginUnloading. Повторюсь, что мы не знаем, какой код помещает разработчик в процедуры инициализации и финализации, которые, по его мнению, должны вызываться только один раз. И мы не знаем, к чему приведет их повторный вызов.

VadiMGP wrote:
Я бы в данном случае не стал париться
Я все же считаю, что попариться все стоит, что бы в конечном итоге получить рабочий при любых условиях продукт.

VadiMGP wrote:
Но эти дядьки не знают, что может прийти грамотный программист и скопировать dll в другую директорию, создав, тем самым, ситуацию, когда будет две попытки загрузить один и тот же dll из разных мест. Хотя ему, конечно, известно, что такое Dll Hell и, стопроцентно, он знает, что при этом DllMain с DLL_PROCESS_ATTACH будет вызван повторно для того же dll в том же процессе
Не допонял. Почему для того же dll? Ведь после копирования это физически будет другая dll.

Знаю, что решение с копирование плагина не самое лучшее, но оно рабочее. И именно для того, что бы найти более лучшее решение я и поднял этот вопрос.
Back to top
View user's profile Send private message
B4rr4cuda



Joined: 03 Jun 2007
Posts: 376
Location: Россия, Москва

Post (Separately) Posted: Sat Sep 01, 2007 19:38    Post subject: Reply with quote

Alextp Может. У меня база плага CdDataBase метров 20 весит. И храню я её в каталоге плага.
Что-то такое может быть и в каталоге wdx плага. Ситуация конечно теоретическая, но возможная.
Back to top
View user's profile Send private message
Alextp



Joined: 06 Feb 2005
Posts: 4957

Post (Separately) Posted: Sat Sep 01, 2007 19:49    Post subject: Reply with quote

B4rr4cuda wrote:
CdDataBase метров 20 весит. И храню я её в каталоге плага.
Что-то такое может быть и в каталоге wdx плага. Ситуация конечно теоретическая, но возможная.

Очень теоретическая: для WFX плагов да, а для WDX это редкость.
Решение Dec копировать плаг - оно правда, крайнее.
Т.к. может быть много WDX плагов, и копировать их - долго.
Back to top
View user's profile Send private message
VadiMGP



Joined: 21 Mar 2007
Posts: 1625

Post (Separately) Posted: Sat Sep 01, 2007 20:46    Post subject: Reply with quote

Dec wrote:
Не допонял. Почему для того же dll? Ведь после копирования это физически будет другая dll.
Это будет другой файл, да. Но я имел в виду, это тот же самый код дважды смаппированный в процесс. А код этого никак не ожидает, особенно в части инициализации данных, специфических для процесса (и даже для каждого потока этого процесса). А что если в dll есть общая память и он хранит в ней список процессов, в которые он загружен? А что если он содает атом используя идентификатор процесса, как уникальное знаечение?
Dec wrote:
В этом же MSDN паписано:
Это верно. Только это к обсуждаемому вопросу не относится. Это совершенно другое. В DllMain не надо делать ничего критического и разумеется мало-мальски опытный программист не будет в DllMain вставлять ни коммуникацию, ни межпоточную синхронизацию ни загрузку других dll. К сожалению, те дятлы, которые писали GDI+ этого не выучили, и на FreeLibrary тоже вызывают FreeLibrary. Они не предполагали, что GDI+ будут загружать динамически. Поэтому Гислер и был вынужден дать возможность обойти этот баг для плагинов, и дать шанс выгрузить GDI+ до того, как будет вызвана FreeLibrary для плагина.
Dec wrote:
Повторюсь, что мы не знаем, какой код помещает разработчик в процедуры инициализации и финализации, которые, по его мнению, должны вызываться только один раз. И мы не знаем, к чему приведет их повторный вызов.
Совершенно верно. Только мы не знаем, также, какой код инициализации разработчик поместил в DllMain, а в твоем варианте это будет повторный вызов DllMain. Та же проблема, но с другой стороны.

И поверь, если бы я считал, что твой метод действительно даст решение "при любых условиях" - то только восторгнулся бы этим. Но в том тот и дело, что я считаю, что ты собираешься взвалить на себя здоровый кусок работы, но все равно останутся ситуации, которые ты обслужить не сможешь. А в некоторых ситуациях, наборот - сделаешь хуже.
А вдруг плагин хранит в totalcmd.ini путь к какому-то своему файлу? Что-то вроде %COMMANDER_PATH%\Plugin\ppp\file.dat? Между прочим, Гислер как раз рекомендует хранить плагиновые данные в totalcmd.ini. Этой рекомендации, по-моему никто не следует, а все создают свои ini айлы. А вдруг не все?

Давай резюмировать. Ты хочешь избежать повторного вызова ContentSetDefaultParams. На мой взгляд - напрасно. В документации к TC API сказано, что плагин может быть вызван из разных потоков одного процесса и нормальный программист учтет это. Но мне трудно поверить, что кто-то учтет возможность, что DllMain будет вызван дважды в одном процессе.
Back to top
View user's profile Send private message
Athari



Joined: 19 Dec 2004
Posts: 81
Location: Казань

Post (Separately) Posted: Sun Sep 02, 2007 02:25    Post subject: Reply with quote

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

Насчёт того, что в DllMain должно быть только примитивное — спасибо за науку. Впервые об этом слышу… Confused У меня возникли подозрения о природе некоторых аномалий моего плагина. Х)

Только тогда встаёт вопрос: а куда совать инициализацию, общую для всей библиотеки? Не проверять же в каждой функции, всё ли инициализировано… Конструкторы статических объектов вызываются до или после DllMain? А всякие #pragma start? Можно ссылкой. Только не в Гугл. Rolling Eyes
_________________
«Today is the first day of the rest of your life»
Back to top
View user's profile Send private message AIM Address Yahoo Messenger MSN Messenger
VadiMGP



Joined: 21 Mar 2007
Posts: 1625

Post (Separately) Posted: Sun Sep 02, 2007 03:08    Post subject: Reply with quote

Athari wrote:
а куда совать инициализацию, общую для всей библиотеки?
Нет универсального рецепта, к сожалению. Лучше всего экспортировать отдельную функцию для такой инициализации которую должен будет вызвать тот кто загрузил dll. Но если ты пишешь плагин, то ты не можешь сам решать что именно экспортировать. Ты вынужден следовать API. В плагинах TC часто используют для этого функцию xxxSetDefaultParam. Эти функции вызываются одинократно после загрузки плагина.

Если речь о С++, то там конструкторы статических объектов точно вызываются до DllMain. Думаю, что и в других средах то же самое. А что такое #pragma start? Что-то не припоминаю такой.
Back to top
View user's profile Send private message
Athari



Joined: 19 Dec 2004
Posts: 81
Location: Казань

Post (Separately) Posted: Sun Sep 02, 2007 03:22    Post subject: Reply with quote

Что ж, попытаю счастья с SetDefaultParam, спасибо.

Quote:
А что такое #pragma start? Что-то не припоминаю такой.

Вру, #pragma startup и #pragma exit. Билдеровская приблуда — выполнение void функций (void) на запуске/выходе с заданием приоритетов. В MSVC такого не припоминаю.
_________________
«Today is the first day of the rest of your life»
Back to top
View user's profile Send private message AIM Address Yahoo Messenger MSN Messenger
Dec



Joined: 07 Sep 2006
Posts: 466

Post (Separately) Posted: Tue Sep 04, 2007 14:56    Post subject: Reply with quote

2VadiMGP:
Вы меня убедили в том, что копирование плохая идея. Как на Ваш взгляд, какие подводные камни есть в методе, предложенном B4rr4cuda - программа загрузчик + pipes.
Back to top
View user's profile Send private message
VadiMGP



Joined: 21 Mar 2007
Posts: 1625

Post (Separately) Posted: Tue Sep 04, 2007 18:05    Post subject: Reply with quote

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

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

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

Теперь о решение Барракуды. Мне оно не нравится по следующим причинам. Сразу оговариваюсь, что я не знаю, что именно ты хочешь, делать, возможно не все эти причины для тебя существенны, но я пишу "по максимуму".
1. Очень нехилый объем работы. Насколько я вижу, протокол связи должен включать в себя весь WDX API! Отсюда вытекает следующий минус.
2. Вечная гонка за версией API. А что будет завтра, когда Гислер добавит к API пару функций или флажков?
3. Когда запускать эту прожку-прослойку? Если непосредственно в тот момент, когда потребовались данные из плагина, то это может оказаться ощутимой добавкой времени. Особенно, если данные выбираются из огромного количества файлов (как, например, при поиске по условиям). Добавить к паре тысяч файлов по 200 миллисекунд на загрузку, уже будет 400 секунд доп. времени. Если же запускать ее однократно, сразу при загрузке твоего плагина, то возникает куча вопросов. а) Как прожка должна узнать что в ТС изменились переменных окружения? Ведь плагин может ими пользоваться. б) Как реализовать одновременную работу нескольких копий ТС?. в) Как быть если ТС слетел (а значит и твой плагин тоже) и был загружен заново?
4. Если плагин работает с сallback, то я, пока, вообще не вижу способа осуществить его для плагина, загруженного в прожку. Тут раздельные адресные пространства только мешают.
5. Все равно будут плагины, которые потребуют отдельной обработки. Media.wfx показывает диалог на вызов значения поля. Есть плагины, которые не желают работать не из ТС.

Короче. Ста процентов не будет. Нужно искать разумный компромисс между усилиями и выгодой.

ЗЫ. И можно "на ты". Wink
Back to top
View user's profile Send private message
Dec



Joined: 07 Sep 2006
Posts: 466

Post (Separately) Posted: Wed Sep 05, 2007 22:10    Post subject: Reply with quote

VadiMGP wrote:
Если мое предположение было верным ...

Абсолютно верное предположение. Я хочу добавить в decClipboardFS настраиваемые пользователем колонки. В него, в принципе, добавить больше нечего.

VadiMGP wrote:
В практическом плане никто из них, пока, ни на какую проблему (связанную с многократной загрузкой!) не наткнулся.

Возможно, они просто не видны, а отлично скрываются за try…except…end. При этом, возможно, возникают какие-нибудь утечки памяти или ресурсов.

VadiMGP wrote:
на мой взгляд, ничего вообще делать не надо пока не столкнешься с каким-то плагином, который будет делать траблы. В этом случае он потребует специфического обслуживания, но какого именно - будет известно, только после того, как станет ясно какую именно проблему он создает.

Я бы не хотел при появлении какого либо проблемного плагина каждый раз искать причину и перекомпилировать свой. И я не могу гарантировать, что я буду вечно поддерживать свой плагин – например, могут быть утеряны исходники в результате случайно набранной комбинации букв format c: + <Enter>. Мне проще и интереснее написать более-менее универсальную обработку.

Некоторые факты, которые возможно объяснят Вам мою настырность.
-Я не профессиональный программист, моя работа не связана с программированием, программирование для меня хобби и средство поддержания IQ в спортивной форме.
-Все, что я делаю, я делаю для самообразования и самообучения.
-Для меня (пока еще?) чем проект сложнее, тем он интереснее.
-При выборе между стабильность+сложность и скорость+размер я выберу первое.
-Я ни когда не работал с pipes, и у меня есть отличный повод их изучить.

VadiMGP wrote:
1. Очень нехилый объем работы.

Будет, чем заняться длительными зимними вечерами.


VadiMGP wrote:
Насколько я вижу, протокол связи должен включать в себя весь WDX API! Отсюда вытекает следующий минус.
2. Вечная гонка за версией API. А что будет завтра, когда Гислер добавит к API пару функций или флажков?

Поддержка появления новых проблемных (для моего плагина) плагинов или поддержка новых API функций – пока я буду поддерживать свой проект, нужно будет делать либо первое или второе. Во втором случае даже если я брошу проект, то новые плагины для нового API должны работать по принципу обратной совместимости.

VadiMGP wrote:
3. Когда запускать эту прожку-прослойку?

Один раз перед первым чтением информации. Не со всеми плагинами будет вестись работа через pipes, а только с теми, в которых реализована ContentSetDefaultParams или ContentPluginUnloading.

VadiMGP wrote:
Если же запускать ее однократно, сразу при загрузке твоего плагина, то возникает куча вопросов. а) Как прожка должна узнать что в ТС изменились переменных окружения? Ведь плагин может ими пользоваться.

Пересылать их при FsFindFirst.

VadiMGP wrote:
б) Как реализовать одновременную работу нескольких копий ТС?.
в) Как быть если ТС слетел (а значит и твой плагин тоже) и был загружен заново?

Пока не знаю, нуждаюсь в совете.

VadiMGP wrote:
4. Если плагин работает с сallback, то я, пока, вообще не вижу способа осуществить его для плагина, загруженного в прожку. Тут раздельные адресные пространства только мешают.

В WDX нет функций с сallback.

VadiMGP wrote:
5. Все равно будут плагины, которые потребуют отдельной обработки. Media.wfx показывает диалог на вызов значения поля. Есть плагины, которые не желают работать не из ТС.

Ну что поделать, красота требует жертв.
Back to top
View user's profile Send private message
VadiMGP



Joined: 21 Mar 2007
Posts: 1625

Post (Separately) Posted: Thu Sep 06, 2007 02:33    Post subject: Reply with quote

Dec wrote:
Возможно, они просто не видны, а отлично скрываются за try…except…end.
Конечно, возможно. Просто это тот случай, когда я спрашиваю "А существует ли на самом деле проблема"? Если такой проблемы нет, то ради чего стараться? Если есть, то надо иметь подходящий test-case чтобы убедиться, что проблема действительно решена.
Dec wrote:
Во втором случае даже если я брошу проект, то новые плагины для нового API должны работать по принципу обратной совместимости.
Нет. Обратная совместимость означает, что старые плагины должны работать в новой версии API. И тут проблем нет. А вот новые плагины со старым API вовсе не обязаны жить дружно.
Допустим, в новой версии API появилась новая функция или флаг, которые я долго выпрашивал у Гислера. Я обрадовался и написал WDX плагин, рассчитанный именно на эту версию API. Когда меня загрузят я поинтересуюсь версией API. Что мне ответит промежуточная программа? Если версия прошита в коде, она меня не устроит, я не буду работать. Если же версия будет взята из ТС, то я буду работать исходя из предположения, что новая Функция/флажок имеют место быть, то есть буду работать неправильно.
Насчет советов. На первом этапе, на работу с несколькими копиями можно забить. Запускай для каждой копии ТС новую копию "посредника". Позже, когда освоишься с протоколами, если будет желание, сможешь переделать посредника в этакий сервер, обслуживающий несколько копий ТС. Падение ТС, видимо, можно отловить по разорваной трубе. В общем случае, это необязательно падение, но для твоих целей это эквивалентно. Аналогично, твой плагин тоже должен быть готов, что соединение упадет.
Dec wrote:
В WDX нет функций с сallback.
Действительно, там их сегодня нет. Пока это не актуально. Но если пояаится в новых версиях API, то абзац.
Кстати, если я правильно помню, твой плагин реализует GetLocalName, так? Интересно, что будет, если в ТС будет разрешен диалог атрибутов файла для "виртуальных панелей".
Dec wrote:
Ну что поделать, красота требует жертв.
Ну, раз ты готов принести себя в жертву, то мне остается только пожелать "если смерти - то мгновенной, если раны - небольшой". Smile Удачи, то есть.
Back to top
View user's profile Send private message
Dec



Joined: 07 Sep 2006
Posts: 466

Post (Separately) Posted: Sat Sep 08, 2007 11:05    Post subject: Reply with quote

VadiMGP wrote:
Dec wrote:
Возможно, они просто не видны, а отлично скрываются за try…except…end.
Конечно, возможно.
В исключении нет ничего страшного, я не считаю его появление неправильным ходом работы. Неправильным я считаю возможные утечки ресурсов при его обработке. Пример: WDX плагин написан на Delphi c использованием SysUtils. При повторном вызове ContentPluginUnloading возникает какое-либо исключение, в dll создается объект класса Exception, который в теории должен быть автоматически разрушен в блоке try…except…end. Но этот блок находится в моей dll, в которой уже совершенно другой свой менеджер памяти. В теории такая ситуация может привести к еще одному исключению при попытке освобождения памяти в try…except…end.
VadiMGP wrote:
Dec wrote:
Во втором случае даже если я брошу проект, то новые плагины для нового API должны работать по принципу обратной совместимости.
Нет. Обратная совместимость означает, что старые плагины должны работать в новой версии API.
Я имел ввиду, что новые плагины будут работать без поддержки новой функциональности.

VadiMGP wrote:
Кстати, если я правильно помню, твой плагин реализует GetLocalName, так? Интересно, что будет, если в ТС будет разрешен диалог атрибутов файла для "виртуальных панелей".
Недопонял.
Back to top
View user's profile Send private message
VadiMGP



Joined: 21 Mar 2007
Posts: 1625

Post (Separately) Posted: Sat Sep 08, 2007 19:09    Post subject: Reply with quote

Dec wrote:
В исключении нет ничего страшного, я не считаю его появление неправильным ходом работы.
Да и я тоже не считаю так. Я писал о другом. Ты хочешь быть убежден, что действительно решил проблему? Что не зря писал весь этот код? Значит надо продумать как именно это проверить.
Dec wrote:
Я имел ввиду, что новые плагины будут работать без поддержки новой функциональности.
Да, это одна из возможностей. Другая возможность - они вообще не будут работать в твоем плагине.
Dec wrote:
VadiMGP wrote:

Кстати, если я правильно помню, твой плагин реализует GetLocalName, так? Интересно, что будет, если в ТС будет разрешен диалог атрибутов файла для "виртуальных панелей".
Недопонял.
В меню ТС есть пункт File->Change Attributes. Он вызывает диалог атрибутов файла, и в этом диалоге можно отображать и редактировать поля из WDX-плагинов. Сегодня этот диалог работает только для "обычных" файлов на диске и не работает в FS-плагинах. Мне видится вполне вероятным, что Гислер добавит вызов такого диалога для "виртуальных панелей", то есть, когда плагин держит ссылки на реальные файлы.
Back to top
View user's profile Send private message
Dec



Joined: 07 Sep 2006
Posts: 466

Post (Separately) Posted: Tue Sep 11, 2007 16:40    Post subject: Reply with quote

VadiMGP wrote:
Dec wrote:
Я имел ввиду, что новые плагины будут работать без поддержки новой функциональности.
Да, это одна из возможностей. Другая возможность - они вообще не будут работать в твоем плагине.
Проблемы с новым WDX интерфейсом появятся, только если я перестану поддерживать проект, причем не зависимо от того, как я буду подключать WDX плагины. Если я заброшу проект, то в обоих случаях, с pipes или без них, ни программа прослойка, ни мой FS плагин не будут ни чего знать ни о новых функциях и флагах, ни о текущей версии интерфейса.

VadiMGP wrote:
В меню ТС есть пункт File->Change Attributes. Он вызывает диалог атрибутов файла, и в этом диалоге можно отображать и редактировать поля из WDX-плагинов. Сегодня этот диалог работает только для "обычных" файлов на диске и не работает в FS-плагинах. Мне видится вполне вероятным, что Гислер добавит вызов такого диалога для "виртуальных панелей", то есть, когда плагин держит ссылки на реальные файлы.
Недопонимаю сути проблемы. Если Ghisler добавит возможность редактирования атрибутов файлов для "виртуальных панелей", то в этом случае TC сам создаст окно диалога, сам натравит свои копии WDX плагинов на файлы, имена которых получит из GetLocalName, WDX плагины сами сделают необходимые изменения в реальных файлах. От моего плагина требуются только имена реальных файлов. Или я чего-то не понимаю? Кстати, если Ghisler добавит возможность редактирования атрибутов файлов для "виртуальных панелей", то он вероятно добавит и настраиваемые колонки, что я и пытаюсь сделать.
Back to top
View user's profile Send private message
VadiMGP



Joined: 21 Mar 2007
Posts: 1625

Post (Separately) Posted: Tue Sep 11, 2007 21:13    Post subject: Reply with quote

Dec wrote:
Проблемы с новым WDX интерфейсом появятся, только если я перестану поддерживать проект,
Это смотря о чьих проблемах речь. Если о проблемах у юзера, то, конечно, пока ты будешь поддерживать проект, у юзера проблем не будет. Разве что, за исключением короткого переходного периода между версиями.
Но для меня, как для автора плагина, проблема прежде всего состояла бы в том, что нужно следить за версиями API и возможно что-то менять в моем плагие, только для того, чтобы он продолжал нормально работать. Я себя хорошо знаю - я на такое не способен. На несколько плагинов я забил именно по этой причине.
Dec wrote:
Недопонимаю сути проблемы.
А никакой проблемы пока нет. Я еще только пытаюсь понять будет тут проблема или нет в будущем. Я же писал - мне интересно поразмышлять, что тут может быть.
TC cам загрузить нужный WDX не может. Всю информацию он получает только от тебя. Откуда ему знать какой WDX грузить?
Или ты имеешь в виду, что там уже юзер сам должен выбрать нужный WDX? То есть отображать инфу через твой плагин, а редактировать через оригинал?
Dec wrote:
Кстати, если Ghisler добавит возможность редактирования атрибутов файлов для "виртуальных панелей", то он вероятно добавит и настраиваемые колонки, что я и пытаюсь сделать.
А кто знает? Зависит от того нужно ли это кому-нибудь. Я предлагал добавить настраиваемые колонки в виртуальные панели - ноль по массе. В смысле - никто не поддержал. Если будет много жаждущих - тогда, наверное, сделает.
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 Previous  1, 2, 3
Page 3 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