С Новым годом! Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.86/21: Рейтинг темы: голосов - 21, средняя оценка - 4.86
5 / 5 / 0
Регистрация: 08.12.2009
Сообщений: 213

Ошибка Could not start the MyService service on Local Computer. Error 5: Access denied.

26.02.2011, 10:14. Показов 4658. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Проблема описана в линке
http://www.relib.com/forums/topic.asp?id=847824

Я последовал совету от Messir и написал код на Си. (вернее использовал примеры от MSDN).
Он практически не отличается от приведенного ранее кода на VB, с той разницей, что на Си легче работать с поинтерами.

Инсталляция и удаление сервиса происходит на ура, без каких-либо осложнений.(впрочем как и в VB)
А вот запуск программы...

Если я запускаю сервис с помощью утилиты Services Console (помечаю сервис и делаю старт), то получаю сообщение
Code
1
2
Could not start the MyService service on Local Computer.
Error 5: Access denied.
Если я запускаю его через StartServiceCtrlDispatcher из главной процедуры то получаю false (запуск не удался), а GetLastError возвращает 1063.

Насколько я понимаю, StartServiceCtrlDispatcher должен запустить процедуру ServiceMain которая в свою очередь должна зарегистрировать Handler процедуру (плюс запуск дополнительных процессов и т.д.). Но до этого я так и не добрался. ServiceMain так и не запускается.

Вопрос в том, почему Access denied и какие флаги надо устанивливать чтобы получить доступ.
Хочу заметить, что я захожу в компьютер как администратор.

Да, и ещё. Я нашел несколько простых примеров на Си которые демонстрируют работу с сервисами, так они так же не работают, останавливаются на StartServiceCtrlDispatcher. Может нужен какой-то специальный доступ (логин) для запуска ?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
26.02.2011, 10:14
Ответы с готовыми решениями:

Ошибка запуска: Error while trying to run project: Unable to start debugging on the web server. Access is denied
Вот что пишут в MSDN When you try to debug on an application running on a Web server, you may sometimes get a message with this error...

error trying access the local web service: GetObject Failed
Здравствуйте, подскажите пожалуйста с чем связана ошибка. Когда устанавливаю php вылетает ошибка: error trying access the local web...

Ошибка Parser Error Message: Access is denied: 'WebApplication3'.
При старте ASP.NET приложения вываливается следующая ошибка: Configuration Error Description: An error occurred during the...

13
Messir
26.02.2011, 15:29
да простят меня за оффтопик от тематики форума, но приведу сишный код сервиса. Он 100% работает, проверено уже не раз... Правда, это всего лишь скелет - вся функциональность из кода вырезана

main.h:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <Windows.h>
 
#define SERVICE_NAME 'MyService'
#define SERVICE_DISPLAY_NAME 'MyService'
#define SERVICE_DESCRIPTION_TEXT 'My Service description'
 
#define WAIT_TIMEOUT 10
 
static SERVICE_STATUS ssStatus;
static SERVICE_STATUS_HANDLE sshStatusHandle;
 
VOID WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv);
VOID WINAPI service_ctrl(DWORD dwCtrlCode);
BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);
 
int start();
void stop();
void wait();
DWORD WINAPI dispatcher(LPVOID param);
main.cpp:
C++
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
#include "main.h"
 
void install_service();
void remove_service();
void usage();
 
static SERVICE_TABLE_ENTRY dispatch_table[] = {{SERVICE_NAME, service_main},{NULL, NULL}};
 
int main(int argc, char* argv[])
{
    if (argc>2) {
        usage();
    } else if (argc > 1) {
        if (strcmpi(argv[1],"-install")==0) {
            install_service();
        } else if (strcmpi(argv[1],"-uninstall")==0) {
            remove_service();
        } else {
            usage();
        }
    } else {
        if (!StartServiceCtrlDispatcher(dispatch_table))
            printf("failed to start %s service\n", SERVICE_NAME);
    }
    return GetLastError();
}
 
void usage()
{
    printf("MyService [COMMAND]\n");
    printf("   Commands:\n");
    printf("             -install\n");
    printf("             -uninstall\n");
}
 
void install_service()
{
    SC_HANDLE   schService;
    SC_HANDLE   schSCManager;
    SERVICE_DESCRIPTION scDesc;
    CHAR szPath[MAX_PATH];
 
    if (GetModuleFileName(NULL, szPath, sizeof(szPath)) == 0) {
        printf("failed to get file path!\n");
        return;
    }
 
    schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
    if (schSCManager != NULL) {
        schService = CreateService(schSCManager,SERVICE_NAME,SERVICE_DISPLAY_NAME,
                    SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS,SERVICE_AUTO_START,
                    SERVICE_ERROR_NORMAL,szPath,NULL,NULL,NULL,NULL,NULL);
        if (schService != NULL) {
            printf("%s service has been installed successfully\n",SERVICE_NAME);
            scDesc.lpDescription=SERVICE_DESCRIPTION_TEXT;
            ChangeServiceConfig2(schService,SERVICE_CONFIG_DESCRIPTION,&scDesc);
            CloseServiceHandle(schService);
        } else
            printf("failed to create %s service\n",SERVICE_NAME);
        CloseServiceHandle(schSCManager);
    }
    else
        printf("failed to access service database\n");
}
 
void remove_service()
{
    SC_HANDLE   schService;
    SC_HANDLE   schSCManager;
 
    schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
    if (schSCManager != NULL) {
        schService = OpenService(schSCManager, SERVICE_NAME, SERVICE_ALL_ACCESS);
        if (schService != NULL) {
            if (ControlService(schService, SERVICE_CONTROL_STOP, &ssStatus)) {
                printf("stopping %s...", SERVICE_NAME);
                Sleep(1000);
                while(QueryServiceStatus(schService,&ssStatus)) {
                    if (ssStatus.dwCurrentState == SERVICE_STOP_PENDING) {
                        printf("."); Sleep(500);
                    }
                    else
                        break;
                }
                printf("\n");
                if (ssStatus.dwCurrentState == SERVICE_STOPPED)
                    printf("%s successfully stopped\n",SERVICE_NAME);
                else
                    printf("failed to stop %s\n",SERVICE_NAME);
            }
Messir
26.02.2011, 16:04
Да, кстати, у тебя случайнов пути в файлу сервиса пробелов нету?
5 / 5 / 0
Регистрация: 08.12.2009
Сообщений: 213
26.02.2011, 16:38  [ТС]
Messir, спасибо.
Твой пример действительно работает, теперь буду разбираться где собака порылась.
А в пути к файлу у меня нет пробелов.
0
1 / 1 / 0
Регистрация: 22.04.2011
Сообщений: 47
24.06.2011, 00:07
Ну, оффтоп так оффтоп...

1. Взгляните пожалуйста на код, приведенный ниже. Он вроде работает. Но меня мучают
сомнения: 'Можно ли так?', 'А если нет, то почему?'

В частности:

2. В ServiceMain: нужно ли (для чего) дожидаться команды 'стоп' (SetEvent),
(т.е., фактически, все время работы сервиса) после создания потока?

3. В ServiceControl: нужно ли (для чего) дожидаться окончания потока по команде 'стоп'?

4. Что происходит при остановке сервиса в случае, если код внутри while (true) не доходит до
if (WaitForSingleObject(hEvent, MYWAIT_TIMEOUT) == WAIT_OBJECT_0) break;
например, при остановке сервиса вручную, или при выключении компьютера?

5. Как обрабатывать ошибки внутри цикла while, (например, можно ли выйти из цикла
не по WAIT_OBJECT_0 и тем самым завершить поток изнутри, без команды 'стоп')?

6. Если можно самостоятельно завершать поток, и соответственно сервис (см. п.5), то
нужно ли ожидание после
ReportStatus(SERVICE_STOPPED, NOERROR, 0);
до
return 0;
в процедуре потока?
Если да, то сойдет ли простое Sleep(500), или нужно дождаться от системы запроса
SERVICE_CONTROL_INTERROGATE в ServiceControl, и придет ли такой запрос в обязательном порядке?
Или же Windows сам сделает все что нужно (например, отметит для себя, что сервис
остановлен) и только потом выгрузит сервис?
В общем, решит ли Windows, что мы корректно завершили сервис без дополнительных манипуляций?

PS: В функции service_main (в реализации Messir'а) раз мы и так ожидаем команды 'стоп' не
выходя из функции, то нельзя ли обойтись без потока, а все что делается в потоке перенести
сюда вместо ожидания? Я понимаю, что от команды 'стоп' до завершения потока разница может
быть большая. Ну а если нет? Что если мы после команды 'стоп' мы можем быстренько закруглиться?
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

VOID WINAPI ServiceMain(DWORD argc, LPSTR *argv)
{
HANDLE hTread;
DWORD dwThreadId;

if(!(ssh = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceControl))) return;

ss.dwServiceSpecificExitCode = 0;
ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;

if (!ReportStatus(SERVICE_START_PENDING, NO_ERROR, 5000)) return; //идет запуск

if (!(hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
{
MyLog('Ошибка создания объекта Event
');
ReportStatus(SERVICE_STOPPED, NOERROR, 0);
return;
}

if (!(hTread = CreateThread(NULL, 0, ThreadFunc, 0, 0, &dwThreadId)))
{
MyLog('Ошибка создания потока сервиса
');
CloseHandle(hEvent);
ReportStatus(SERVICE_STOPPED, NOERROR, 0);
return;
}
}

//-------------------------------------------------------------------------------------------

VOID WINAPI ServiceControl(DWORD dwControlCode)
{
if((dwControlCode == SERVICE_CONTROL_STOP) || (dwControlCode == SERVICE_CONTROL_SHUTDOWN))
{
ReportStatus(SERVICE_STOP_PENDING, NOERROR, 0); // идет остановка сервиса
if(hEvent) SetEvent(hEvent); // сигнал-запрос на завершение для Трейда
}
else ReportStatus(ss.dwCurrentState, NOERROR, 0); // обрабатываем другие команды
}

//-------------------------------------------------------------------------------------------

BOOL ReportStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;

if (dwCurrentState == SERVICE_START_PENDING) ss.dwControlsAccepted = 0;
else ss.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_CONTROL_SHUTDOWN;

ss.
0
Messir
24.06.2011, 18:45
по пунктам:

1. Пропускаем, все станет ясно из следующих пунктов

2. Не обязательно. Можно ждать, можно не ждать - тут уж как удобнее... (в приведенном сервисе этот код использовался - вот там wait и остался)

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

4. Что значит - не доходит? И что есть 'остановка вручную'?
при выключении компьютера точно так же посылается сигнал остановки сервиса. И сервис завершается в штатном режиме. В случае когда мы заршаем сервис молотком и зубилом (т.е. через диспетчер задач и прочую тяжелую артиллерию), то не все ли нам равно, что будет с потоком? так или иначе - ему наступает п..дец

5. Выйти-то можно, но тогда это не будет корректным завершением. Лучшим решением является установка STOP_PENDING, и SetEvent для ожидаемого события (и, возможно, goto непосредственно к команде WaitForSingleObject). Короче, дублирование функциональности stop().

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

PS: А вот функциональность потока в service_main переносить - это плохая идея. Т.е. оно будет работать, но геморроя будет много. Контролировать поток куда проще и удобнее...
1 / 1 / 0
Регистрация: 22.04.2011
Сообщений: 47
25.06.2011, 03:19
Тоже, по пунктам:

2. можно какой нибудь намек, когда в ServiceMain ожидание окончания потока необходимо, или хотябы желательно?
2а.и чего правильней ожидать: стоп (SetEvent) или окончания потока, ведь если цель-100%-я уверенность в том, что поток сдох, то WaitForSingleObject(hEvent, ..) это не то, нужен WaitForSingleObject(hThread, ..)...

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

6. вопрос возник при попытке понять действия Windows при завершении сервиса:
а)если функция SetServiceStatus() только сообщает Windows адрес структуры, а он считывает эту инфу когда ему заблагорассудится возможно мы быстрее закроем свой поток и выгрузится сервис. А Windows будет пытаться счытыват уже несуществующую структуру со всеми вытекающими последствиями...
б) Windows узнает о сотоянии сервиса исходя из того, что мы отвечаем на запрос SERVICE_CONTROL_INTERROGATE - тогда, опять же, завершив сервис раньше времени мы столкнемся с приведенной выше проблемой.
в) в ходе обработки функции SetServiceStatus() Windows считывает и запоминает где-то у себя сотояние. Тогда получается системе SERVICE_CONTROL_INTERROGATE вообще нужен только в режиме SERVICE_..._PENDING, и только чтобы убедиться, что мы еще дышим. В других случаях SERVICE_CONTROL_INTERROGATE не посылается и не используется.

ЗЫ:Просто для тех кто пытается проделать все это на VB говорят multithread - это большая проблема

Новые вопросы:
- для чего в том коде SetLastError(0);
- как узнать, что поток в состоянии спячки (см. код ниже в функции ServiceControl)?
Ведь если поток спит, то сначала его нужно 'разбудить', иначе, во-первых, у него могли остаться незавершенные дела, а мы будем пываться его остановить насильно, во-вторых лучше он сам добровольно и корректно завершит свою работу.
А еще, наверое нельзя усыплять спящий поток, или будить бодрствующий?
- почему в оснастке 'Службы', кнопка 'Пауза' у моего сервиса неактивная, хотя в ReportStatus я внес соответствующие изменения?
- Где-то я слышал, что в ServiceMain как можно быстрее мы должны вызвать RegisterServiceCtrlHandler() и также быстро завершить инициализацию сервиса.
Но какое дело системе до нашей инициализации, если она выполняется в новом потоке, а если мы сразу схалявим и скажем, что все готово (т.е. вслед за вышепереупомянутой функцией сразу вызываем ReportStatus(SERVICE_RUNNING, NO_ERROR, 0)). В чем смысл SERVICE_START_PENDING'а ?

Спасибо огромное Messir!

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
А вот код с учетом замечаний Messir:

HANDLE hEvent;
HANDLE hThread;
SERVICE_STATUS_HANDLE ssh;
SERVICE_STATUS ss;

//-------------------------------------------------------------------------------------------

VOID WINAPI ServiceMain(DWORD argc, LPSTR *argv)
{
DWORD dwThreadId;

if(!(ssh = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceControl))) return;

ss.dwServiceSpecificExitCode = 0;
ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;

if (!ReportStatus(SERVICE_START_PENDING, NO_ERROR, 5000))
{
MyLog('Ошибка установки статуса в SERVICE_START_PENDING
');
ReportStatus(SERVICE_STOPPED, NOERROR, 0);
return;
}

if (!(hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
{
MyLog('Ошибка создания объекта Event
');
ReportStatus(SERVICE_STOPPED, NOERROR, 0);
return;
}

if (!(hThread =
0
Messir
25.06.2011, 19:41
2. Только если это нужно автору для каких-либо целей. Сервису пофиг на это, он так или иначе корректно отработает.
2а. В силу вышесказанного - ждать того, что требуется, или не ждать ничего...

4. Ну, тогда нужно предусмотреть ожидание завершения потока, и, в случае если он не завершается в течение какого-то времени, прибивать его насильно.

6. ближе всего к в)

- SetLastError(0) - чтобы уведомить о корректном завершении сервиса, даже если какая-то функция внутри него завершилась с ошибками.
- Никак не надо узнавать. См. описания ResumeThread и SuspendThread.
- SERVICE_ACCEPT_PAUSE_CONTINUE
- RegisterServiceCtrlHandler - да, а вот быстрой инициализации - ничего такого не оговаривается.
1 / 1 / 0
Регистрация: 22.04.2011
Сообщений: 47
25.06.2011, 21:13
Спасибо большое.
Я вообще такой человек: мне мало знать 'как надо', мне еще всегда интересно 'а почему именно так?'. Вы практически полностью развеяли мои сомнения и терпеливо разжевали все. Уважаю!!!

... и последние два вопроса:
- >> Никак не надо узнавать. - тогда что можно сделать в такой ситуации, когда наш поток усыпляется посередине записи данных в файл? Ладно handle'ы и т.д. и т.п. - данные можем потерять!!! А в моем приложении это очень критично - что-то типа сетевого брокера локального сервера БД (DCOM и ADO, не устраивает по разным причинам).

- Я вроде разобрался с сокетами, и вроде работает без тормозов: Перегонял большие объемы данных как по 10, так и по 100-Мбитной сети. Так вот, индикатор загрузки сети показывал почти 80% (и фактически данные передавались тоже). Если увеличить объем буфера, получается еще больше, однако, у меня иногда бывали сбои. А при 32Кб работает просто шикарно. Блокирующий accept я, при завершении приложения, бужу посылкой запроса на соединение себе же... А обмен с клиентами происходит каждый в своем потоке. Но тут как снимать блокировку и корректо завершать поток не знаю - пока просто прибиваю поток и все
Но вот беда, разобрался я только с блокирующими сокетами, а про асинхронным чего-то очень мало инфы нашел, в общем, не разобрался.
Что посоветуете, оставить все как есть или все-таки попытаться испоьзовать асинхронные?
0
Messir
25.06.2011, 21:19
чтобы решить вопрос с потерей данных, могу предложить следующее: создаем событие, которое будет определять, может ли поток быть усыплен. перед началом критической операции сбрасываем это событие, в конце - устанавливаем. При усыплении сначала ждем этого события, потом усыпляем поток.
1 / 1 / 0
Регистрация: 22.04.2011
Сообщений: 47
25.06.2011, 21:23
А про блокирующие сокетами что скажете?
0
1 / 1 / 0
Регистрация: 22.04.2011
Сообщений: 47
25.06.2011, 21:29
Ну а SERVICE_PAUSE_CONTINUE вместо SERVICE_ACCEPT_PAUSE_CONTINUE - это я конечно же лоханулся. Хотя знал, как должно быть, так сказать, механическая ошибка, но в упор не замечал. Исправил, и конечно же заработало как надо.
0
Messir
25.06.2011, 21:55
не вижу проблемы с блокирующими сокетами.
пока ждем - тред можно смело прибивать/суспендить, когда вышли из ожидания - сбросили евент, разрешающий завершение/суспенд.
или, как вариант - отказаться от блокирующих сокетов в пользу ManualResetEvent'ов
1 / 1 / 0
Регистрация: 22.04.2011
Сообщений: 47
25.06.2011, 22:20
Ок, спасибо.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
25.06.2011, 22:20
Помогаю со студенческими работами здесь

Could not start the service MySQL. Error: 0
Во время установки MySQL при выполнении «Start service» выводит ошибку: Could not start the service MySQL. Error: 0 . Может кто...

Windows service на Python: access denied
ПРЕДИСЛОВИЕ. Начну со ссылки на вопрос на stackoverflow, но там пока ничего не посоветовали. Может, кому-то будет понятнее суть вопроса. ...

General Error SQL ERROR [ mysqli ] Access denied for user 'a5936757_0'@'10.3.2.19' (using password: NO) [1045]
Здравствуйте! Помогите, разобраться, пожалуйста! Я пытаюсь, создать сайт на хостинге 000webhost. Сначала, на локальном сервере...

Ошибка "Access denied" error 5 при вызове VirtualQueryEx
Всем привет. Не могу понять в чём проблема, запускаю программу от имени администратора, но данные не могу получить. Вот кусок кода,...

Ошибка "MySQL error 1044: access denied" при создании таблицы


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и источниками (напряжения, ЭДС и тока). Найти токи и напряжения во всех элементах. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru