powered by simpleCommunicator - 2.0.38     © 2025 Programmizd 02
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Отсечение повторного запуска приложения
25 сообщений из 25, страница 1 из 1
Отсечение повторного запуска приложения
    #32203623
Чернышов Вадим Константинович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как в visual FoxPro организовать такую штуку:
Если приложение уже запущено, то при повторном запуске этого приложения, оно просто не запускалось.
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32203631
Crip
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Поищите на http://nsvisual.com/ph/list.php3?f=5
Там это много обсуждалось.
При желании могу прислать свой вариант сделанный с помощью виндовых семафоров
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32203773
Фотография NNN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
thanks universalthread:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
************************************************************
*  FUNCTION FirstInstance()
************************************************************
*  Author............: Gary Foster, Pointsource Consulting, Inc.   104171 . 3677 @compuserve.com
*  Project...........: Starbase
*  Created...........:  03 / 13 / 98    15 : 39 : 58 
*  Copyright.........: Public Domain
*) Description.......: This function uses the creation of a named MUTEX
*)                   : to determine existing instance of an application.
*)                   : Call this function very early in an application's
*)                   : startup to create a named object that can be checked
*)                   : every time the application is started.  If the named 
*)                   : object exists, the function will try to bring foreward
*)                   : the applications main frame.  In this case, the main frame
*)                   : is the FoxPro _SCREEN. Any other hWnd would do as well.
*)                   : 
*  Calling Samples...: IF !FirstInstance()
*                    :    QUIT  && Or something along that line.
*                    : ELSE
*                    :    yada yada yada...
*)  Parameter List...: lcStarBase - уникальный идентификатор прилодения 
*)                   : в виде строковой константы
*  Major change list.:

FUNCTION FirstInstance()
LPARAMETERS lcStarBase

   *-- Declare just enough API functions and constant defines to support this function.
   #DEFINE SW_RESTORE               9
   #DEFINE ERROR_ALREADY_EXISTS   183
   #DEFINE GW_HWNDNEXT              2
   #DEFINE GW_CHILD                 5

   DECLARE INTEGER CreateMutex IN win32api INTEGER, INTEGER, STRING @
   DECLARE INTEGER CloseHandle IN win32api INTEGER
   DECLARE INTEGER GetLastError IN win32api
   DECLARE INTEGER SetProp IN win32api INTEGER, STRING @, INTEGER
   DECLARE INTEGER GetProp IN win32api INTEGER, STRING @
   DECLARE INTEGER RemoveProp IN win32api INTEGER, STRING @
   DECLARE INTEGER IsIconic IN win32api INTEGER
   DECLARE INTEGER SetForegroundWindow IN USER32 INTEGER
   DECLARE INTEGER GetWindow IN USER32 INTEGER, INTEGER
   DECLARE INTEGER ShowWindow IN WIN32API INTEGER, INTEGER
   DECLARE INTEGER GetDesktopWindow IN WIN32API

   *-- We need a function from Foxtools. I know I could get this from the API, but I'm lazy.
   IF !( "FOXTOOLS"  $ UPPER(SET( "LIBRARY" )))
      SET LIBRARY TO FOXTOOLS.fll ADDI
   ENDIF
   
   LOCAL cExeFlag  && Name of the MUTEX
   LOCAL nExeHwnd  && MUTEX handle
   LOCAL hWnd      && Window handle
   LOCAL lRetVal   && Return value of this function

   * -- Try and create a new MUTEX with this name.
 
*!*	   cExeFlag =  "STARBASE" +CHR( 0 )
   IF EMPTY(lcStarBase)
	   cExeFlag =  "STARBASE" +CHR( 0 )
   ELSE
	   cExeFlag = lcStarBase+CHR( 0 )
   ENDIF
   nExeHwnd = CreateMutex( 0 , 1 ,@cExeFlag)

   * -- If the named MUTEX creation fails because it exists already, try to display
 
   * -- the existing application and have this function return .F., presumably
 
   * -- to a calling routine that is deciding whether to continue instantiation.
 
   IF GetLastError() = ERROR_ALREADY_EXISTS

      * -- Get the hWnd of the first top level window on the Windows Desktop.
 
      HWND = GetWindow(GetDesktopWindow(), GW_CHILD)

      * -- Loop through the windows. If the application has no top level window, 
 
      * -- the loop will quickly run out of desktop windows and simply exit.
 
      DO WHILE HWND >  0 

         * -- Is this the proper window? GetProp looks() for a property we added
 
         * -- the first time, not a caption.
 
         IF GetProp(HWND, @cExeFlag) =  1 

            * -- If the application window is minimized, open %af_src_str_1failed to open%af_src_str_2t need it any more.
 
      CloseHandle(nExeHwnd)

      lRetVal = .F.

   ELSE
      * -- Add a property to the FoxPro main frame so we can identify this 
 
      * -- window again regardless of caption changes.
 
      SetProp(MainHwnd(), @cExeFlag,  1 )
      lRetVal = .T.
   ENDIF

   RETURN lRetVal

ENDFUNC


ЗЫ В vfp 7/8, естественно, MainHwnd() лучше заменить на _screen.hWnd.
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32203780
IgorProgrammer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
NNN: Зачем так сложно???

Можно по-простому...
Создать пустую таблицу...

В главной проге вначале всего несколько строк... + функция выхода...
И хай хоть 100 клацають... {:-)}


on error do my_exit
if !used('tab1')
sele 0
use tab1 exclu
endif
on error

Procedure my_exit
messagebox(' Пощастыть наступного разу',64,'')
Quit

При втором заходе побежит по обработчику ошибок на выход...
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32203784
Фотография NNN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2IgorProgrammer

> Зачем так сложно???

1. Подними запущенную программу, если она свернута в панель задач.
2. Удали файл tab1.dbf (или поломай его, измени пути в программе и т.д.) и попробуй запустить программу хотя бы один раз (только не говори, что пользователь это сделать не сможет)
3. Предложи схему, основанную на твоем методе, при которой программа повторно не запускалась бы под одним логином, но позволяла запускаться под другим.
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32203792
IgorProgrammer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
NNN:

1 При втором входе она сразу идет на выход... Ведь нельзя поднять того че нету...

2 Таблицу надо кинуть туда же где и ехе-шник(там всегда найдет). А если пользователь хряпнет таблицу... так приложение и первый раз не запустится... Пусть пользователь еще и все конфиги с сисами хряпнет... иль отформатит диск где винда и спршивает че у него приложение не запускается...

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


У тебя есть нормальный грусский хелп по win32api...
У меня хелп есть, но через одно место написана... Хотелось бы человеческий...
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32203801
Фотография NNN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2IgorProgrammer

Дружественней надо быть, юзверь он тоже человек и иногда с него можно поиметь пиво..

> 1 При втором входе она сразу идет на выход... Ведь нельзя поднять того че нету...

Почему нету? Программа уже запущна? Запущена. Зачем заставлять пользователя искать окно программы, если его можно вывести на передный план?

> 2 Таблицу надо кинуть туда же где и ехе-шник(там всегда найдет). А если пользователь хряпнет таблицу... так приложение и первый раз не запустится... Пусть пользователь еще и все конфиги с сисами хряпнет... иль отформатит диск где винда и спршивает че у него приложение не запускается...

Юзвери тоже люди, но зачем лишний раз с ними общаться, особенно когда они не в хорошем расположении духа? Если файла нет, то ему ничего не грозит, следовательно, меньше поводов для общения.

> 3 Если я правильно понял его вопрос... Так вроде ему надо что б второй раз небыло... Можно даже с нехорошой мессагой кинуть... Иль в этой таблице занести кому мона - кому нет...

Попробую обрисовать мой работающий вариант.
1. С любого компьютера под своим логином к sql server может обращаться любой пользователь.
2. Иногда надо запусть две копии программы, например, когда два пользователя хотят сверить свои данные.
3. Если пользователь еще не подключился - висит окно с логином, второе окно с логином не появится.
4. Если пользователь ввел правильнвй пароль, то при повторной запуске его либо перебросит на уже запущенное приложение, либо программа запустится с новым логином.
Это, конечно, выходит за рамки сабжа, но все-таки, попробуй реализовать такую схему через use?
Кстати, еще проще (без поднятия окна):
Код: plaintext
1.
2.
3.
lcUniqueFileName='..'
if fcreate(lcUniqueFileName)< 0 
 =messagebox('..')
quit


> У тебя есть нормальный русский хелп по win32api...

Есть :) В виде книги. Это практически перевод основных функций:
http://market.yandex.ru/search.xml?hid=&text=%D1%E0%E9%EC%EE%ED+windows+2000+api

> У меня хелп есть, но через одно место написана... Хотелось бы человеческий...

Меня вполне устраивает MSDN. Какой-то вариант лежит здесь:
http://www.cs.virginia.edu/~lcc-win32/
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32204411
Crip
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В vfp 7/8, естественно, MainHwnd() лучше заменить на _screen.hWnd.
Правильно на _vfp.Hwnd ...
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32204471
Фотография NNN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2Crip

Ну это если уж очень правильно :)
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32204586
Crip
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нет это просто правильно. _Screen.Hwnd дает не тот hwnd. Я это еще когда сам делал защиту от повторного доступа столкнулся. Думаю и че у меня SetForegroundWindow не отрабатывает
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32204629
Фотография NNN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2Crip

А у меня в обоих случаях отрабатывет нормально. Относительно, вот так надежнее, наверняка вылетит, а не будет моргать на панели:
Код: plaintext
1.
2.
n=_screen.WindowState
_screen.WindowState=  1 
_screen.WindowState= n

Кстати, у них заголовки разные, что приятно, можно вверху ничего не менять, а в панели задач какой-нибудь счетчик пустить.
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32204657
Crip
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В любом случае
Код: plaintext
1.
set library to foxtools.fll
messageb(_vfp.Hwnd = Mainhwnd())

Выдаст .T.
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32207565
Чернышов Вадим Константинович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да уж палемику вы развили :)
Дело в том, что я не особый сторонник фокса, даже противник, но по долгу службы приходится вести одну дырявую прогу, которую писал, соответственно я. Так вот в этой проге призпуске происходит копирование базы данных из одной папки в другую, и если вдрук глупый юзверь запускает ее два раза подряд, то файлы начисто убиваются, а так как фокс с файлами работает на дос уровне, то их поднять нериально, если конечно прям сразу это сделать, но как правило, юзер наделает еще всяких всячин, а уж потом сообщает о глюках :(

Ну так вот текст там такой:

LOCAL lcMainClassLib
LOCAL lcLastSetTalk,lcLastSetPath,lcLastSetClassLib,lcOnShutdown
*-- Save and configure environment.
lcLastSetTalk=SET("TALK")
SET TALK OFF
set exact on
lcLastSetPath=SET("PATH")
*CD "\foxpro projects\rat\"
SET PATH TO ;DATA;INCLUDE;FORMS;GRAPHICS;HELP;LIBS;MENUS;PROGS;REPORTS
PUSH MENU _msysmenu
lcLastSetClassLib=SET("CLASSLIB")
lcMainClassLib="libs\rat"
SET CLASSLIB TO (lcMainClassLib) ADDITIVE
lcOnShutdown="ShutDown()"
ON SHUTDOWN &lcOnShutdown
ON ERROR ErrorHandler(ERROR(),PROGRAM(),LINENO())
_shell="DO Cleanup IN progs\rat"

*-- Instantiate application object.
RELEASE goApp
PUBLIC goApp
goApp=CREATEOBJECT("cApplication")

*-- Configure application object.

goApp.SetCaption("Рейтинг")
*goApp.cStartupMenu="menus\rat"
goApp.cStartupForm="forms\start"
* Запуск через пороль
*goApp.cStartupForm="forms\password"

*-- Show application.
goApp.Show


*-- Release application.
RELEASE goApp

*-- Restore default menu.
POP MENU _msysmenu

*-- Restore environment.
ON ERROR
ON SHUTDOWN
IF NOT lcLastSetClassLib==SET("classlib")
RELEASE CLASSLIB (lcMainClassLib)
ENDIF
IF EMPTY(lcLastSetPath)
SET PATH TO
ELSE
SET PATH TO &lcLastSetPath
ENDIF
IF lcLastSetTalk=="ON"
SET TALK ON
ELSE
SET TALK OFF
ENDIF
RETURN



FUNCTION ErrorHandler(nError,cMethod,nLine)
LOCAL lcErrorMsg,lcCodeLineMsg

WAIT CLEAR
lcErrorMsg=MESSAGE()+CHR(13)+CHR(13)
lcErrorMsg=lcErrorMsg+"Method: "+cMethod
lcCodeLineMsg=MESSAGE(1)
IF BETWEEN(nLine,1,10000) AND NOT lcCodeLineMsg="..."
lcErrorMsg=lcErrorMsg+CHR(13)+"Line: "+ALLTRIM(STR(nLine))
IF NOT EMPTY(lcCodeLineMsg)
lcErrorMsg=lcErrorMsg+CHR(13)+CHR(13)+lcCodeLineMsg
ENDIF
ENDIF
IF MESSAGEBOX(lcErrorMsg,17,_screen.Caption)#1
ON ERROR
RETURN .F.
ENDIF
ENDFUNC



FUNCTION ShutDown
*IF TYPE("goApp")=="O" AND NOT ISNULL(goApp)
* RETURN goApp.OnShutDown()
*ENDIF
*Cleanup()

*nDialogType = 4 + 32 + 256
*set date to ITALIAN
*SET HOURS TO 24
*SET SECONDS ON
*dt = DATETIME()
*s = TTOC(dt)
*MESSAGEBOX(s , nDialogType, "ДАТА/ВРЕМЯ")
*zapusk = ".\BackUpData.bat " + "/" + alltrim(s)
*MESSAGEBOX( zapusk , nDialogType, "ДАТА/ВРЕМЯ")


! /N "BackUp.exe"

CLOSE ALL
QUIT
ENDFUNC


FUNCTION Cleanup

IF CNTBAR("_msysmenu")=7
RETURN
ENDIF
ON ERROR
ON SHUTDOWN
SET CLASSLIB TO
SET PATH TO
CLEAR ALL
CLOSE ALL
POP MENU _msysmenu
RETURN

Вы мне можите точно написать в каком месте, и какой код нужно вставить :)
Буду признателен, а то уже эта проблема достала.
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32207701
Фотография NNN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2Чернышов Вадим Константинович

> но по долгу службы приходится вести одну дырявую прогу, которую писал, соответственно я.

Сдается мне, что сию дырявую прогу писал преимущественно визард..

> Вы мне можите точно написать в каком месте, и какой код нужно вставить :)

В самом начале (перед всем остальным)
Код: plaintext
1.
2.
IF !FirstInstance('MyProgram')
    CANCEL
ENDIF
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32209793
Чернышов Вадим Константинович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот ведь, сам и описался
Прогу на самомом деле писал не я :)

Ну вставил я в сомое начало:


IF !FirstInstance('Baza')
CANCEL
ENDIF



А при компиляции FoxPro (5.0) ругается:

Unable to find Unknown FIRSTINSTANSE

Что дальше то делать?
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32209819
Фотография NNN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2Чернышов Вадим Константинович

Ах, ну да!
Будь проще и люди к тебе потянутся: Короче, вместо того, что я тебе написал в прошлый раз, пиши:
Код: plaintext
1.
2.
if fcreate('tmp12345.tmp')< 0 
 cancel
endif
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32211614
linnad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Привет!
При запуске создавай файл (любой), при выходе удаляй.
Перед запуском сделай проверку наличия этого файла.
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32212795
Чернышов Вадим Константинович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Привет всем
Решил я эту проблему вот так:
В самом начале проги рисуем:

if (file('test.tmp') == .t.)
quit
else
fcreate('test.tmp')
endif

И в функции ShutDown добавляем строчку:

delete file test.tmp


И все работает.
Только вот, одна деталь, дырка есть, если вдруг юзверь при работающей проге файл "test.tmp" грохнет, то прога может быть повторно запущена.
Если же при создании файла "test.tmp" устанавливать ему атрибут СКРЫТЫЙ, то тогда прога не работает :(((
Что можите посоветовать?
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32212798
Чернышов Вадим Константинович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2NNN
Твой метод я так и не просек! (Либо лыжи не едут либо ....)
Ошибка все равно повторяется!
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32212799
Фотография NNN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чернышов Вадим Константинович

> Только вот, одна деталь, дырка есть, если вдруг юзверь при работающей проге файл "test.tmp" грохнет, то прога может быть повторно запущена.
Если же при создании файла "test.tmp" устанавливать ему атрибут СКРЫТЫЙ, то тогда прога не работает :(((
Что можите посоветовать?


Объясняю свой код от 16 июл 03, 15:01. Более правильный код:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
public hFile
hFile=fcreate('test.tmp')
if hFile < 0 
 quit
endif
*!* ShutDown
=fclose(hFile)
delete file test.tmp


Перерь о том, как это работает. Резервирует глобальную переменную для хендла файла. Следующий этап создание файла. Возможные варианты:
1. Файл отсутсвует. В этом случае будет созадан новый файл, который будет монопольно захвачен и удалить его, пока программа работает, невозможно. Значение hFile будет больше нуля.
2. Файл существует и захвачен работающей программой. В этом случае произойдет ошибка при создании файла и значение hFile будет -1 (type 'help fcreate').
3. Файл существует, но не захвачен. Будет создан новый файл, который перезапишет старый. Далее как в варианте 1.
Привыходе закрываем файл и удаляем его.
Почему до этого я привел более короткий вариант? Да просто я не считаю, что один кластер на диске стоит возни с отслеживанием глобальных переменных в программе.

> Твой метод я так и не просек! (Либо лыжи не едут либо ....)
Ошибка все равно повторяется!


Unable to find Unknown FIRSTINSTANSE?
При сборке проект не может найти функцию FirstInstance, которая приведена в моей мессаге от 9 июл 03, 21:17. Сразу скажу, что файл FOXTOOLS.fll должен быть виден ехешнику, иначе будет runtime error.
Если тебе ненужно поднимать свернутые окна и выводить программу на передний план, то достаточно и варианта с файлом.
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32212800
Фотография NNN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По поводу скрытых файлов:
Код: plaintext
1.
?FILE('c:\boot.ini') && .F.
?FILE('c:\boot.ini', 1 ) && .T.
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32215763
Aijik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 NNN

В вашем споре с Crip'ом относительно хэндла фоксового окна, Crip совершенно прав. Согласно нововведениям в VFP7, эти два объекта были разделены. А именно: _VFP проедставляет всё окно фокса целиком, _SCREEN представляет клиентскую часть этого окна (то, куда выводится результат ?<тра-та-та>). Поэтому в контексте рассматриваемого вопроса _VFP.hWnd правильнее.
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32215813
Aijik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 IgorProgrammer

Есть еще одна ситуация, когда способ NNN с Mutex'ом предпочтительней. А именно - если EXE лежит в сети и по-сети же и запускается. В вашем способе с USED при таких обстоятельствах 2-й юзер на другом сетевом компе не запустит прогу, т.к. нарвется на эксклюзивную блокировку таблицы, лежащей там же на серваке. Mutex же создается в памяти винды на каждой отдельной машине и ограничивает запуск 2-й копии проги на ЭТОМ ЖЕ компе. На любой же другой машине по-сети прогу запустить можно
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32216461
Samir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
if file('test.tmp')
quit
else
create table test.tmp (i i)
endif
...
Рейтинг: 0 / 0
Отсечение повторного запуска приложения
    #32216466
Samir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Или еще лучше

err=.f.
if file('test.dbf')
on error err=.t.
use test excl
if err
quit
endif
else
create table test (i i)
endif
...
Рейтинг: 0 / 0
25 сообщений из 25, страница 1 из 1
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Отсечение повторного запуска приложения
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]