Как получить содержимое Label из другого приложения

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Как получить содержимое Label из другого приложения

Сообщение awl100Alex » 29.01.2008 (Вт) 17:38

Нужно программно получить содержимое Label1.Caption (цифровое переменное значение!) из другого(!) приложения. Подскажите, пожалуйста, как можно это реализовать???

Ранее на этом сайте просматривал вот эту тему "Label из чужого окна"
http://bbs.vbstreets.ru/viewtopic.php?p ... 2b282b000b
Получил такую инфу (цитирую):
"Если программа сишная - тогда можно вытащить. Если VB - то скорей всего нет." – в моем случаи прога написана на Делфях 6.

Вообще у label нет hWnd, т.к это не окно, и его содержимое просто «рисуется» на форме, НО(!): если я правильно понимаю: прежде чем содержимое Label будет нарисовано на форме, оно сначала будет «нарисовано» в памяти компа, в цифровом виде, а уже потом переведено в граф. адаптер для "рисования"... Значит, если правильно прочесть эти данные прямо из памяти, то таким образом, можно будет получить их значения.

Как это можно сделать?
Я так понимаю, нужна грамотная манипуляция функциями работы с памятью типа: FindWindow, VarPtr, StrPtr, ObjPtr, GetProcAddress, CopyMemory...

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Как получить содержимое Label из другого приложения

Сообщение alibek » 29.01.2008 (Вт) 17:49

awl100Alex писал(а):FindWindow, VarPtr, StrPtr, ObjPtr, GetProcAddress, CopyMemory...

Нет, это не нужно.
Нужно ReadProcessMemory.
Lasciate ogni speranza, voi ch'entrate.

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Сообщение awl100Alex » 29.01.2008 (Вт) 17:58

alibek
А ты можешь указать ссылки на какие-нибудь примеры применения этой функции?? Я не очень большой спец. в программных операциях с памятью...

Igor_123
Осторожный Баянист
Осторожный Баянист
Аватара пользователя
 
Сообщения: 1325
Зарегистрирован: 21.07.2004 (Ср) 13:00
Откуда: Днепропетровск

Сообщение Igor_123 » 29.01.2008 (Вт) 19:04

а что такого написанно на этом Label, что тебе нужно его прочитать???
Водки я вам не обещаю, но погуляем хорошо.
И. Сусанин.

Аватара (с) Тёмыч

Lumen
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 841
Зарегистрирован: 03.12.2005 (Сб) 16:09
Откуда: Брянск

Сообщение Lumen » 30.01.2008 (Ср) 2:15

А что непонятного с ReadProcessMemory?
Сначала открываем процесс с правами PROCESS_VM_READ, готовим буфер, куда читать, потом собсно ReadProcessMemory:
Код: Выделить всё
Public Declare Function ReadProcessMemory Lib "kernel32.dll" (ByVal hProcess As Long, ByRef lpBaseAddress As Long, ByRef lpBuffer As Long, ByVal nSize As Long, ByRef lpNumberOfBytesWritten As Long) As Long

Здесь hProcess - хэндл процесса, который вернула OpenProcess
lpBaseAddress - адрес, откуда читать
nSize - размер считываемого куска
lpNumberOfBytesWritten - можно 0 передать.
Возвращает кол-во прочитанных байт. В идеале должно быть равно nSize...
Подпись проходит рефакторинг

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Сообщение awl100Alex » 30.01.2008 (Ср) 9:39

Igor_123

На этот Label разработчики данной проги, какого-то хрена, вывели важную статистическую информацию в числовом виде. Данные постоянно меняются, а мне нужно из своей проги получать и арифметически обрабатывать эти значения. Поэтому и возникла необходимость каким-то образом получать эти данные.

Lumen
Спасибо за подсказку, попробую разобраться...

P.S.
Чувствую, что связался я большим геморроем... :(( И геморроится мне предстоит очень долго и нудно. :((
И какого... в С-ях Label это нормальный(!) полноценный объект, с которым можно всегда «поговорить по душам» и договорится за бокалом пива, ;)) а во вех других инструменталках полный(!).. :((

Twister
Теоретик
Теоретик
Аватара пользователя
 
Сообщения: 2251
Зарегистрирован: 28.06.2005 (Вт) 12:32
Откуда: Алматы

Сообщение Twister » 30.01.2008 (Ср) 9:58

awl100Alex
Недавно я предлагал способ считывания данных из грида в чужом приложении, написанном на делфях: http://bbs.vbstreets.ru/viewtopic.php?p=6684279
А я все практикую лечение травами...

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Сообщение jangle » 30.01.2008 (Ср) 10:56

awl100Alex писал(а):alibek
А ты можешь указать ссылки на какие-нибудь примеры применения этой функции?? Я не очень большой спец. в программных операциях с памятью...


ReadProcessMemory - нафиг не нужен. Действуй так:

FindWindowEx - находишь окно твоей программы
EnumChildWindows - перебираешь дочерние окна, находишь Label - это тоже окно (не в VB)
GetWindowText - получаешь текст из лейбла.

И все

Lumen
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 841
Зарегистрирован: 03.12.2005 (Сб) 16:09
Откуда: Брянск

Сообщение Lumen » 30.01.2008 (Ср) 12:03

jangle
че-та не получается твоим способом найти заголовок лейбла в программе на Delphi7
Подпись проходит рефакторинг

Igor_123
Осторожный Баянист
Осторожный Баянист
Аватара пользователя
 
Сообщения: 1325
Зарегистрирован: 21.07.2004 (Ср) 13:00
Откуда: Днепропетровск

Сообщение Igor_123 » 30.01.2008 (Ср) 12:20

Spy++ попробуй найти свой Label. А потом будеш програмно пробовать искать
Водки я вам не обещаю, но погуляем хорошо.
И. Сусанин.

Аватара (с) Тёмыч

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Сообщение jangle » 30.01.2008 (Ср) 12:32

Lumen писал(а):jangle
че-та не получается твоим способом найти заголовок лейбла в программе на Delphi7


Lumen - получается, там вообще все элементарно делается. И кстати, не желательно давать советы, в той области, где плохо разбираешься. Можешь сильно запутать человека, задавшего вопрос.

VB сейчас под рукой нет, вот накидал пример на PB, при желании перевести на VB очень легко

Код: Выделить всё
#Compile Exe
#Include "WIN32API.INC"

Function ParentCallback (ByVal hWndChild As Long, lRaram As Long) As Long
    Local szClass As Asciiz * %MAX_PATH
    Local szText  As Asciiz * %MAX_PATH
    Local txt     As Asciiz * %MAX_PATH
    Local lRes    As Long
    lRes = GetClassName(hWndChild, szClass, SizeOf(szClass))
    lRes = GetWindowText(hWndChild, szText, SizeOf(szText))
    CharToOem(szText,txt)
    szText=txt
    CharToOem(szClass,txt)
    szClass=txt
    StdOut "-- Children window : Class=" & szClass & " " & "Text=" & szText
    lRes = EnumChildWindows(hWndChild, CodePtr(ChildCallback), 0&)
    Function = 1
End Function

Function ChildCallback (ByVal hWndChild As Long, lRaram As Long) As Long
    Local szClass As Asciiz * %MAX_PATH
    Local szText  As Asciiz * %MAX_PATH
    Local txt     As Asciiz * %MAX_PATH
    Local lRes    As Long
    lRes = GetClassName(hWndChild, szClass, SizeOf(szClass))
    lRes = GetWindowText(hWndChild, szText, SizeOf(szText))
    CharToOem(szText,txt)
    szText=txt
    CharToOem(szClass,txt)
    szClass=txt
    StdOut "Parent window: Class=" & szClass & " " & "Text=" & szText
    Function = 1
End Function

Function PBMain As Long
    On Error Resume Next
    StdOut "Enumerate child window"
      Local bResult As Long
      Local IE As Long
      Local ID As Long
      ID=Shell ("Label.exe")
      Sleep 1000
      IE=FindWindow("","Dialog1") 'хендл основного окна
      bResult = EnumChildWindows(IE, CodePtr(ParentCallback), 0&)
      WaitKey$
End Function         



В аттаче скомпилированный пример, запускаем GetLabelText.exe и смотрим, как он выдирает текст из лейбла Label.exe и выводит его в консольном окне.
Вложения
GetTextFromLabel.zip
(16.96 Кб) Скачиваний: 458

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Сообщение awl100Alex » 30.01.2008 (Ср) 12:44

jangle
Я этот путь уже прошел – НЕ получилось!..
Вот по этому адресу скачал прогу, которая делает то, что ты предлагаешь (адрес из форума, который я указывал в самом начале топика, там же теория...):
http://bbs.vbstreets.ru/download.php?id=1951
Называется - GetCtrlId.zip – она не показывает ID Label никаким макаром! :(

Igor_123
Spy++ слабенький... :(( Есть штуковина гораздо(!) круче – InqSoft Window Scanner (кстати рекомендую всем программистам! Скачать можно от суда: http://softok.org/utils/oth/17186prog.html) – она тоже Label НЕ находит!! :( Но по возможностям значительно(!) превосходит всех остальных подобного рода программ.

Здесь нужна именно работа с памятью! Иначе других вариантов я просто не вижу. :(

Twister
Много теории... Пока разбираюсь... Но могу сказать сразу, что классы типа TStringGrid и подобные определения объектов находятся легко, а вот с label, блин!.. :(

Igor_123
Осторожный Баянист
Осторожный Баянист
Аватара пользователя
 
Сообщения: 1325
Зарегистрирован: 21.07.2004 (Ср) 13:00
Откуда: Днепропетровск

Сообщение Igor_123 » 30.01.2008 (Ср) 12:48

тогда вопрос:
А Label ли это???
Водки я вам не обещаю, но погуляем хорошо.
И. Сусанин.

Аватара (с) Тёмыч

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Сообщение jangle » 30.01.2008 (Ср) 12:48

awl100Alex писал(а):jangle
Я этот путь уже прошел – НЕ получилось!..


Не получается? Значит надо учить матчасть, пока не получится! :wink: В программировании, как и в музыке, легких путей - нет.
Алгоритм извлечения текста из лейбла (при условии что он окно), показан в моем предыдущем посте

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Сообщение awl100Alex » 30.01.2008 (Ср) 12:53

Извините, поправочка (InqSoft Window Scanner)...
http://softok.org/utils/oth/17186prog.html

jangle
Когда посылал ответ, не видел твоего нового сообщения.
Сейчас попробую скачать, посмотреть... А там в архиве, есть EXE?? А то компилятора на PB у меня нет.

Igor_123
Label!.. :(

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Сообщение awl100Alex » 30.01.2008 (Ср) 13:06

jangle
Так может это в PB, как и в С-ях label – это объект, а в Делфях???

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Сообщение jangle » 30.01.2008 (Ср) 13:23

awl100Alex писал(а):jangle
Так может это в PB, как и в С-ях label – это объект, а в Делфях???


Ни какой разницы. Вопрос в другом, твой Label - это окно или нет?
Если окно, выдрать текст можно элементарно. А если Label "виртуальный" - просто позиция на диалоге, куда выводится текст (как в VB6) то текст выдрать сложнее, но все равно можно

Lumen
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 841
Зарегистрирован: 03.12.2005 (Сб) 16:09
Откуда: Брянск

Сообщение Lumen » 30.01.2008 (Ср) 14:05

jangle
В дельфях Label не STATIC.
Так что твой способ не катит.
Попробуй прочитать текст из примера в аттаче...
Spy++ естественно не видит его.
Вложения
Project1.rar
(164.59 Кб) Скачиваний: 1306
Подпись проходит рефакторинг

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Сообщение awl100Alex » 30.01.2008 (Ср) 14:43

Его не находит даже InqSoft Window Scanner! Показывает только имя класса TForm1 и все!.. :(

Ладно, зайду сюда завтра, сейчас работа... вынужден уходить. Спасибо всем неравнодушным к этой проблеме.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 30.01.2008 (Ср) 15:44

jangle
Е-мое, если все сканеры окон лабел не находят, то он НЕ ОКНО.
Лучший способ понять что-то самому — объяснить это другому.

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Сообщение jangle » 30.01.2008 (Ср) 18:00

Lumen писал(а):jangle
В дельфях Label не STATIC.


Не в дельфях, а в VCL. Я тестировал свой способ, на дельфийской проге, где Label`ы были как раз static

Так что твой способ не катит.
Попробуй прочитать текст из примера в аттаче...
Spy++ естественно не видит его


В случае с VCL действительно не катит. Это такая-же байда, как и Label в VB6. В Design-time контрол эмулируется, а в готовом EXE идет TextOut прямо на контекст устройства.
Но все равно, как я писал ранее, выдрать текст можно, только сложнее.

1 вариант - читать текст прямо с DC, наверняка в GDI+ есть какая-нибудь функция обратная TextOut

2 вариант - тупо глобальных хук на TextOut в DLL, и прописать эту библу в HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows, в AppInit_DLLs, чтобы стартовала со всеми GUI процессами. В хуковом событии определять ID текущего процесса - GetCurrentThreadId, и окно которое пишет в DC - GetGUIThreadInfo. Далее по координатам, можно определить какой Label пишет в данный момент, забираем этот текст и инициируем CallBack экзешника который будет забирать текст и передаем ему строку.

В принципе все, немного сложно, но не смертельно :)

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 31.01.2008 (Чт) 9:13

jangle писал(а):GetWindowText - получаешь текст из лейбла.

Не надо постить непроверенную ерунду.
Label это не окно, ты его не найдешь и текст не получишь.
Lasciate ogni speranza, voi ch'entrate.

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Сообщение jangle » 31.01.2008 (Чт) 10:38

alibek писал(а):
jangle писал(а):GetWindowText - получаешь текст из лейбла.

Не надо постить непроверенную ерунду.
Label это не окно, ты его не найдешь и текст не получишь.


Прочитай топик еще раз, уже было разъяснено в каких случаях Label окно, а в каких нет

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 31.01.2008 (Чт) 10:44

Ты сообщение автора топика читал? В частности, третий абзац.
Lasciate ogni speranza, voi ch'entrate.

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Сообщение jangle » 31.01.2008 (Чт) 11:03

alibek писал(а):Ты сообщение автора топика читал? В частности, третий абзац.


Естественно читал, и сразу проверил на дельфийской проге. Там Label имел тип - STATIC. Только топикстартер, оказывается имел ввиду VCL - Label, а в моем случае, дельфийская форма, была описана в ресурсах. Из-за этого и получилось взаимное непонимание проблемы.

В случае VCL Label, где идет сразу вывод текста на DC, его можно выдрать через хук на TextOut. Об этом уже писалось выше

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Сообщение awl100Alex » 31.01.2008 (Чт) 17:07

jangle
Ты молодец! Вынужден признать, что чувствую в тебе реального специалиста! Ты указал на правильный информационный(!) вектор.
Вообщем, все по порядку...

Насколько я понимаю VCL – это некий классовый интерфейс, представляющий собой компонентную модель межобъектного взаимодействия. И создан для облегчения работы программистам, поскольку многие рутинные задачи берет на себя, а так же выполняет функцию оптимизации кода.

Если честно, то я не знаю, является ли нужный мне Label объектом VCL, знаю только, что указатель на него не определяется. Ну, по всей видимости, ты прав, потому что, когда я искал инфу по VCL, то наткнулся на один сайт, где очень(!) много, и в деталях рассказано про все это. Тема называется ««Основы работы с Win API в VCL-приложениях». Приведу только основное...

В этой теме было дано понятие «ОКНО» в Windows (цитирую):
«Под словом "Окно" обычно подразумевается некоторая форма наподобие тех, что можно создать с помощью класса TForm. Однако это понятие существенно шире. В общем случае окном называется любой объект, который имеет экранные координаты и может реагировать на мышь и клавиатуру. Например, кнопка, которую можно создать с помощью класса TButton, - это тоже окно.»

После этого я посмотрел, что Label в VB (думаю и в Делфи тоже...) может(!) реагировать на события мыши! Написал такой код, и он работает!

‘ Пример 1
Private Sub Form_Load()
Label1.Caption = " 'Получить этот текст...' "
End Sub

Private Sub Label1_Click()
MsgBox "Один клик по Label -" & Label1.Caption
End Sub


Отсюда вопрос: означает ли это, что Label в данном случаи – это таки окно?! Но почему же тогда оно не имеет хэндла??? Тут явно есть какие-то тонкости!
И эти тонкости раскрываются в следующей цитате из сайта:

NOTA BENE!
«VCL вносит некоторую путаницу в понятие окон. Часть визуальных компонентов VCL не является окнами, а только имитируют(!) их, как, например, TImage. Это позволяет экономить ресурсы системы и повысить быстродействие программы. Следует запомнить, что окнами являются только те визуальные компоненты, которые имеют в числе предков класс TWinControl. Разработчики VCL постарались, чтобы разница между оконными и неоконными визуальными компонентами была минимальна. Действительно, на первый взгляд неоконный TLabel и оконный TStaticText кажутся практически близнецами. Разница становится заметной тогда, когда используется Win API.»

NOTA BENE! => С неоконными компонентами можно работать только(!) средствами VCL, они даже не имеют свойства Handle, в то время как к оконным компонентам можно взаимодействовать с помощью Win API.»
... ... ...

Получается, что в моем примере... Оконное событие Label1_Click имитируется(!) средствами VCL, но на самом деле Label1 НЕ является окном, и его содержимое рисуется в DC устройства! Эти выводы подкрепляются продолжением цитаты:

«Отметим также ещё одно различие между оконными и неоконными компонентами: неоконные компоненты рисуются непосредственно на поверхности родительского компонента, в то время как оконные как бы кладутся на родителя сверху. В частности, это означает, что неоконный TLabel, размещённый на форме, не может закрывать собой часть кнопки TButton, потому что TLabel рисуется на поверхности формы, а кнопка - это независимый объект, лежащий на форме и имеющий свою поверхность. А TStaticText может оказаться над кнопкой, потому что он тоже находится над формой.»

Все то, о чем очень сжато и писал jangle!
В связи с этим у меня к тебе несколько вопросов:

1) Ты писал:
«...Я тестировал свой способ, на дельфийской проге, где Label`ы были как раз static» - а этот Label на твоей тестовой проге определялся сканерами???
Тут еще нужно догадываться, где «STATIC», а где VCL...

Пробовал найти функцию обратную TextOut, но ничего похожего не нашел, и мне так кажется, что такой функции просто нет! Ведь в случаи VCL Label в DC это уже рисунок, а значит, искомая функция должна выполнять что-то типа OCR (Optical Character Recognition – оптического распознавания символов), как в FineReader’e.
Это же просто нереально! :( Хотя есть еще и функция DrawText. В описании пишется, что TextOut пишет(!), а DrawText рисует(!) текст... Но работают они практически одинаково.

2) Почему ты напрочь отбросил предложение Lumen’a о том, что можно применить функцию ReadProcessMemory, для того чтобы попробовать прочесть данные прямо из памяти?? Ведь я так понимаю, что все сначала происходит в ОЗУ, затем VCL работает с GDI, который уже использует TextOut.
http://www.netlib.narod.ru/library/book0007/ch02_04.htm
- рис 2.4... (примерно!).
Ведь это можно рассматривать, как вариант???

3) Почему ты решил, что хук нужно делать именно на TextOut, а не, к примеру, на подобную ей DrawText???

4) Что ты думаешь по поводу второй моей метки «NOTA BENE!» см. по тексту???.. Какие могут быть в VCL средства работы с неоконными компонентами???
Может быть это и есть то, что нужно???

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 31.01.2008 (Чт) 18:02

DrawText все-равно вызывает TextOut.
Lasciate ogni speranza, voi ch'entrate.

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Сообщение awl100Alex » 31.01.2008 (Чт) 18:56

alibek
Получается, что все дороги ведут в TextOut??

Igor_123
Осторожный Баянист
Осторожный Баянист
Аватара пользователя
 
Сообщения: 1325
Зарегистрирован: 21.07.2004 (Ср) 13:00
Откуда: Днепропетровск

Сообщение Igor_123 » 31.01.2008 (Чт) 19:03

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

Аватара (с) Тёмыч

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Сообщение awl100Alex » 31.01.2008 (Чт) 19:03

Просто пример... :)
Вложения
Proba.rar
(9.07 Кб) Скачиваний: 530

След.

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

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

Сейчас этот форум просматривают: AhrefsBot, Google-бот, Yandex-бот и гости: 54

    TopList