Dispatch или Unknown?

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
ANDLL
Великий гастроном
Великий гастроном
Аватара пользователя
 
Сообщения: 3450
Зарегистрирован: 29.06.2003 (Вс) 18:55

Dispatch или Unknown?

Сообщение ANDLL » 24.08.2004 (Вт) 7:54

Здравствуйте.

Я тут решил написать довольно большую программку, включающую(на данный момент) 5 ActiveX DLL и 1 ActiveX Control. И что бы было в ней что-то общее решил, что бы все объекты этой программы поддерживали единый интерфейс, скажем IAppObject. И что-бы не организовывать специально для этого интерфейса еще одну dll самого нижнего уровня решил просто написать TypeLibrary на IDL.
Изначально код интерфейса был такой:
Код: Выделить всё
   [
      object,
      uuid(CFFFFFFF-70DE-AAAA-BCDC-F43FBFAED684),
      helpstring("Application Object Interface"),
      dual,
      pointer_default(unique)
   ]
   interface IAppObject : IDispatch
   {
      //Some methods
   };


И VB вроде без ошибок компиляции соглашался имплементировать этот интерфейс.
Тут я решил, что интерфейс можно слегка укоротить:
Код: Выделить всё
   [
      object,
      uuid(CFFFFFFF-70DE-AAAA-BCDC-F43FBFAED684),
      helpstring("Application Object Interface"),
      pointer_default(unique)
   ]
   interface IDTMApplication : IUnknown
   {
      //Some methods
   };


Т.е. во-первых он стал не-дуальным(убрано слово dual в объявлении интерфейса) и во-вторых он не стал поддерживать IDispatch(т.е. он производен непосредственно от IUnknown).
Собственно самое смешное, что и этот интерфейс VB имплементирует без ошибок компиляции.
Вопросы
1) Почему? Ведь по правилам в автоматизации могут использоваться только интерфейсы производные от IDispatch? Уж не ждут ли меня тут какие подводные камни, типа, внезапного вылетания моей программы по непонятным причинам?
2) Может еще можно как-то облегчить интерфейс? Может кто подскажет?
3) А сильно ли я его облегчил избавленем от IDispatch? А то может риск не стоит свечь?

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 24.08.2004 (Вт) 9:26

1. Потому! :) Дуальный интерфейс нужен только тогда, когда используется позднее связывание. Если тебе оно не нужно, смело отрубай IDispatch. Правда тогда для компиляции обязательно будет нужно tlb, иначе бы VB сам разобрался.
2. Да куда ж ещё?
3. Если не ошибаюсь, ты убрал из vTable то ли 5, то ли 6 методов, при этом полностью отрубил late-binding и осложнил жизнь тем, которые, возможно, захотят поюзать твоей интрефейс, а tlb у них нет, только описание...
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

ANDLL
Великий гастроном
Великий гастроном
Аватара пользователя
 
Сообщения: 3450
Зарегистрирован: 29.06.2003 (Вс) 18:55

Сообщение ANDLL » 24.08.2004 (Вт) 10:35

А почему если я запускаю одну из Dll(в режиме полной совместимости) из IDE, а потом запускаю exe-шник появляеться сообщение Type mysmatch? Причем, не "Run-time error '13'. Type mismatch" А именно просто Type mysmatch. Хотя у VB вообще иногда бывают чудиковатые соббщения об ошибках. До подключения tlb и внедрения этой штуки такого не наблюдалось. Вот это меня и волную. Подводный камень.
Гастрономия - наука о пище, о ее приготовлении, употреблении, переварении и испражнении.
Блог

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 31.08.2004 (Вт) 16:38

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

Vi
Постоялец
Постоялец
 
Сообщения: 739
Зарегистрирован: 25.01.2002 (Пт) 11:03
Откуда: Россия, Ижевск

Сообщение Vi » 31.08.2004 (Вт) 16:53

Кстати, добавь ключевое слово oleautomation, иначе понадобится прокси/стаб DLL, использование которой можно избежать через использование typelib маршаллинга.
Код: Выделить всё
   [
      object, *oleautomation*,
      uuid(CFFFFFFF-70DE-AAAA-BCDC-F43FBFAED684),
      helpstring("Application Object Interface"),
      pointer_default(unique)
   ]
   interface IDTMApplication : IUnknown
   {
      //Some methods
   };
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 31.08.2004 (Вт) 22:13

GSerg писал(а):3. Если не ошибаюсь, ты убрал из vTable то ли 5, то ли 6 методов, при этом полностью отрубил late-binding и осложнил жизнь тем, которые, возможно, захотят поюзать твоей интрефейс, а tlb у них нет, только описание...

Вставлю свои 2коп.
1. Во-первых, 4. Члены IDispatch надо знать наизусть ;-)
2. Во-вторых, начиная с VB5, VB нигде не требует диспинтерфейсы. То, что вообще хоть где-то нужно наследование от IDispatch - заблуждения, оставшиеся со времени VB4.
3. Однако все скриптовые движки (VBS, JS, ActiveX-модули для всяких Perl-подобных штук) до сих пор требуют диспинтерфейсы.

Таким образом, ANDLL потерял:
1) возможность позднего связывания под VB (вряд ли ему это где-то надо)
2) возможность использования этого компонента из скриптов.

А сэкономил - 16 байт оперативки. Имхо не стоит того.

2Vi: oleautomation в его tlb не надо. Регистрироваться на машине всё равно будет не она, а та, которую генерирует VB. Там все необходимые для маршалинга вещи будут.

2Всем: oleautomation в tlb для VB писать не стоит никогда. Пользы от этого никакой нет, а вред будет в случае, когда переопределяется системный интерфейс - в реестре невосстановимо сотрётся правильная информация о маршалинге.

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 31.01.2005 (Пн) 19:09

tyomitch писал(а):... начиная с VB5, VB нигде не требует диспинтерфейсы. То, что вообще хоть где-то нужно наследование от IDispatch - заблуждения, оставшиеся со времени VB4...

в смысле - для компиляции не потребуется tlb?

Я вижу, тут люди конкретные собрались. Спрошу, я, ламер, вот что:
зачем нужна регистрация tlb? (еще о каком-то regtlib слыхать было)
Есть ли у меня вопрос? У меня всегда есть вопрос

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 01.02.2005 (Вт) 6:03

У tlb, как и у всего остального, есть UUID. По нему её и находят. А хранится он в реестре.

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

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 01.02.2005 (Вт) 8:33

GSerg писал(а):У tlb, как и у всего остального, есть UUID. По нему её и находят. А хранится он в реестре.

А для компиляции tlb не нужна только тогда, когда юзается позднее связывание.

Ну, а регистрация-то как осуществляется? Я много раз пользовал tlb сторонних разрботчиков и ни о какой регистрации не задумывался, но связывание всегда использовалось раннее, тут понятно. А вот на кой нужна регистрация tlb при позднем связывании - для OLE-серверов, у которых отсутствует DLLRegisterServer, что-ли? Что это за regtlib.exe? - у меня его нет..
Есть ли у меня вопрос? У меня всегда есть вопрос

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 04.02.2005 (Пт) 19:01

Eugenio писал(а):Я вижу, тут люди конкретные собрались. Спрошу, я, ламер, вот что:
зачем нужна регистрация tlb? (еще о каком-то regtlib слыхать было)

1. Для компиляции ;-)
2. Для маршалинга, когда твой компонент использует в публичном интерфейсе члены этой TLB.

На машине пользователя для Standard EXE регистрация TLB не нужна. А выполняется она очень просто - вставляется ветка в HKEY_CLASSES_ROOT\Typelib\{LibID библиотеки}\
Изображение

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 05.02.2005 (Сб) 11:41

tyomitch писал(а):
Eugenio писал(а):Я вижу, тут люди конкретные собрались. Спрошу, я, ламер, вот что:
зачем нужна регистрация tlb? (еще о каком-то regtlib слыхать было)

1. Для компиляции ;-)

так эта регистрация, типа, происходит автоматом, при ссылке на tlb в референсах? А самой ссылки VB недостаточно?
tyomitch писал(а):На машине пользователя для Standard EXE регистрация TLB не нужна.

А для ActiveX Control'ов и dll? Tyomitch! Можно популярно на эту тему или ссылку какую - конкретные случаи, когда требуется наличие и регистрация tlb, которая использовалась в проекте, когда нужно совать её в ресурсы?
tyomitch писал(а):А выполняется она очень просто - вставляется ветка в HKEY_CLASSES_ROOT\Typelib\{LibID библиотеки}\

Это то, что происходит при вызове RegisterTypeLib?
Есть ли у меня вопрос? У меня всегда есть вопрос

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 05.02.2005 (Сб) 12:03

Eugenio писал(а):
tyomitch писал(а):На машине пользователя для Standard EXE регистрация TLB не нужна.

А для ActiveX Control'ов и dll? Tyomitch! Можно популярно на эту тему или ссылку какую - конкретные случаи, когда требуется наличие и регистрация tlb, которая использовалась в проекте, когда нужно совать её в ресурсы?

С этим - всё, вроде понятно (перечитал посты на http://bbs.vbstreets.ru/viewtopic.php?t ... oadtypelib)
Есть ли у меня вопрос? У меня всегда есть вопрос

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 05.02.2005 (Сб) 12:29

Eugenio писал(а):
tyomitch писал(а):
Eugenio писал(а):Я вижу, тут люди конкретные собрались. Спрошу, я, ламер, вот что:
зачем нужна регистрация tlb? (еще о каком-то regtlib слыхать было)

1. Для компиляции ;-)

так эта регистрация, типа, происходит автоматом, при ссылке на tlb в референсах? А самой ссылки VB недостаточно?

Угу, автоматом. VB умный :-)
Ссылки, наверное, достаточно - думаю, он сам зарегистрирует.

Eugenio писал(а):
tyomitch писал(а):А выполняется она очень просто - вставляется ветка в HKEY_CLASSES_ROOT\Typelib\{LibID библиотеки}\

Это то, что происходит при вызове RegisterTypeLib?

Не только:
In addition to filling in a complete registry entry under the type library key, RegisterTypeLib adds entries for each of the dispinterfaces and Automation-compatible interfaces, including dual interfaces. This information is required to create instances of these interfaces. Coclasses are not registered (that is, RegisterTypeLib does not write any values to the CLSID key of the coclass).
Изображение

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 05.02.2005 (Сб) 16:56

tyomitch писал(а):Ссылки, наверное, достаточно - думаю, он сам зарегистрирует.

Не, я не могу взять в толк, почему ему надо регистрировать tlb для компиляции. Получается, он регистрирует tlb, а затем юзает результаты? А получить их так? В tlb ведь всё равно нет процедуры "саморегистрации", типа DllRegisterServer. Или может, там что-то еще есть?
Есть ли у меня вопрос? У меня всегда есть вопрос

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 05.02.2005 (Сб) 20:03

Да, VB регистрирует библиотеку, а потом юзает предоставляемый ей ITypeLib, чтобы не парсить TLB-файл вручную.
Изображение

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 06.02.2005 (Вс) 6:11

Угу...
А ещё позырь в каталоге Windows на предмет Regtlib.exe...
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 06.02.2005 (Вс) 10:21

tyomitch писал(а):Да, VB регистрирует библиотеку, а потом юзает предоставляемый ей ITypeLib...
Стало быть, всё-таки в tlb есть некая процедура "саморегистрации", которая либо пишет данные в реестр, либо возвращает данные для реестра, если VB "предпочитает" не "накапывать" их?
GSerg писал(а):А ещё позырь в каталоге Windows на предмет Regtlib.exe...
Так в том-то и дело, что никакого Regtlib у меня нету. Я впервые упоминание о нем встретил на Edanmo's
Есть ли у меня вопрос? У меня всегда есть вопрос

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 06.02.2005 (Вс) 10:47

Eugenio писал(а):
tyomitch писал(а):Да, VB регистрирует библиотеку, а потом юзает предоставляемый ей ITypeLib...
Стало быть, всё-таки в tlb есть некая процедура "саморегистрации", которая либо пишет данные в реестр, либо возвращает данные для реестра, если VB "предпочитает" не "накапывать" их?

Не в самой TLB, а внутри COM. COM парсит TLB, а VB пользуется предоставляемым COM для данной TLB объектом ITypeLib, чтобы не парсить ту TLB самому.
В реестр пишутся и через ITypeLib возвращаются разные данные, кажется ты их путаешь. Ещё раз, в реестр пишется только LibID, путь к TLB, и все IID-ы. Например, методы объектов - туда не пишутся.
Изображение

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 09.02.2005 (Ср) 8:07

Да, наверное, я что-то путаю. Вот и пытаюсь распутать. Как, tyomitch, VB получает указатель на ITypeLibe - функции этого интерфейса в самой tlb реализованы :shock: ? Или через ту самую API LoadTypeLib - интерфейс создается в памяти этой функцией (которая парсит tlb) и содержит полученные из неё данные, так?
Последний раз редактировалось Eugenio 09.02.2005 (Ср) 8:16, всего редактировалось 1 раз.
Есть ли у меня вопрос? У меня всегда есть вопрос

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 09.02.2005 (Ср) 8:13

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

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 09.02.2005 (Ср) 8:15

то есть, это всё LoadTypeLib?
Есть ли у меня вопрос? У меня всегда есть вопрос

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 09.02.2005 (Ср) 8:16

Получается так :)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 09.02.2005 (Ср) 8:39

Eugenio писал(а):Или через ту самую API LoadTypeLib - интерфейс создается в памяти этой функцией (которая парсит tlb) и содержит полученные из неё данные, так?

На всякий случай подтвержу :-)
Да, именно так - интерфейс создается в памяти этой функцией.
Изображение

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 09.02.2005 (Ср) 8:49

Спасибо, о мегачелы.
Я просто подумал, что это всё полезно понимать еще до того, как примешься за чтение концептуальных статеек.
ANDLL, извини, что в твоем топике так потусовался.
Есть ли у меня вопрос? У меня всегда есть вопрос

codemaster
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 604
Зарегистрирован: 13.02.2004 (Пт) 13:35

Сообщение codemaster » 09.02.2005 (Ср) 13:19

Eugenio писал(а):Спасибо, о мегачелы.
Я просто подумал, что это всё полезно понимать еще до того, как примешься за чтение концептуальных статеек.
ANDLL, извини, что в твоем топике так потусовался.


Самым ценным в топике был пост Vi

Если посмотреть правде в глаза
то насвистели в этом топике с три кучи :wink: :wink:

Особенно хорш этот перл

2Всем: oleautomation в tlb для VB писать не стоит никогда. Пользы от этого никакой нет, а вред будет в случае, когда переопределяется системный интерфейс - в реестре невосстановимо сотрётся правильная информация о маршалинге.


если тебя действительно интересует
COM /DCOM купи книгу "Модель COM и применение ATL 3.0"

http://www.ozon.ru/context/detail/id/110643/

+ статьи на RSDN
//<-
Mit freundlichen Grüßen
//->

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 09.02.2005 (Ср) 13:45

2 codemaster
Кого именно "интересует COM"? А то ты, вроде, обращаешься ко мне, но цитируешь то, что отвечали на посты ANDLL, а не на мои вопросы
(я про ссылку на Vi и того, кто насчет определения интерфейса советовал) :) . На случай, если про меня речь: такая книга - это хорошо, наверное. Но я начну с Роджерсона. Mit Glückwunsch :)
Есть ли у меня вопрос? У меня всегда есть вопрос

codemaster
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 604
Зарегистрирован: 13.02.2004 (Пт) 13:35

Сообщение codemaster » 09.02.2005 (Ср) 14:42

Eugenio писал(а):. Но я начну с Роджерсона.


На мой взгляд не лучшая книга.
Но как говорится "Jedem eigen"
//<-
Mit freundlichen Grüßen
//->

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 09.02.2005 (Ср) 14:55

codemaster писал(а):Если посмотреть правде в глаза
то насвистели в этом топике с три кучи :wink: :wink:

Особенно хорш этот перл

2Всем: oleautomation в tlb для VB писать не стоит никогда. Пользы от этого никакой нет, а вред будет в случае, когда переопределяется системный интерфейс - в реестре невосстановимо сотрётся правильная информация о маршалинге.


Если ты несогласен с каким-то утверждением, то имеет смысл приводить свои контраргументы, а не эмоции :evil:

Итак, ты несогласен с этим "перлом" :?: В MSDN пальцем показать, где это написано?
Изображение

codemaster
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 604
Зарегистрирован: 13.02.2004 (Пт) 13:35

Сообщение codemaster » 10.02.2005 (Чт) 14:42

tyomitch писал(а):
codemaster писал(а):Если посмотреть правде в глаза
то насвистели в этом топике с три кучи :wink: :wink:

Особенно хорш этот перл

2Всем: oleautomation в tlb для VB писать не стоит никогда. Пользы от этого никакой нет, а вред будет в случае, когда переопределяется системный интерфейс - в реестре невосстановимо сотрётся правильная информация о маршалинге.


Если ты несогласен с каким-то утверждением, то имеет смысл приводить свои контраргументы, а не эмоции :evil:

Итак, ты несогласен с этим "перлом" :?: В MSDN пальцем показать, где это написано?


Итак потратим время и поговорим о "пользе" oleautomation:

Добавлением атрибута [oleautomation] к определению интерфейса
ты разрешаеш исп. универсального маршаллера.
( интерфейс должен пользовать VARIANT совм. типы данных. )
В реестр же RegisterTypeLib добавляет
в \hkcr\intrface\твой интерфейс \ProxyStubClsid32 и ProxyStubClsid32 значение
{00020424-0000-0000-C000-000000000046} - СLSID униврсального маршаллера
и ничего более !

+ см. пост VI

P.S. отсутствие oleautomation приводит к большому гемору при исп DCOM. Универсальный маршаллер работает в 90% + совм. с MTS
//<-
Mit freundlichen Grüßen
//->

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 10.02.2005 (Чт) 15:35

В случае, когда "мой интерфейс" - это один из стандартных интерфейсов OLE (скажем для ясности, IInternetProtocol, или даже IDispatch), который я вынужден объявлять в своей TLB из-за того, что он использует нестандартные типы данных - тогда ProxyStubClsid32, вставляемый при регистрации такой TLB, перезапишет уже прописанный (правильный) ProxyStubClsid32 стандартным (неправильным).

Так что навредить это может. А вот где это может оказать "пользу"? Пока что у тебя только общие слова про "большой гемор при исп DCOM". А что именно будет хуже, чем без oleautomation?
Изображение

След.

Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: AhrefsBot и гости: 39

    TopList