helpf.pro
Регистрация

v8: Бездействие пользователя

Migleon
15.12.2016 10:02Прочитано: 8380

Как в 1С 8.х определить бездействие пользователя и через заданный период оного выполнить действие, например закрыть 1С пользователя?

Yandex
Возможно, вас также заинтересует
Реклама на портале
all4cf
15.12.2016 12:37Ответ № 1

ну на вскидку:

1. Стандартное средство:

В конфигураторе - Администрирование - Параметры ИБ   Нужно настроить время засыпания и время завершения пассивных сеансов

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

3. если база серверная, то подключиться к консоли и отслеживать показатели активности:

Код 1C v 8.3
 Процедура ЗавершениеРаботыНеактивныхПользователей() Экспорт
    
    ПодстрокиСтрокиСоединения  = РазложитьСтрокуВМассивПодстрок(СтрокаСоединенияИнформационнойБазы(),";");
    
    Если ПодстрокиСтрокиСоединения.Количество()> 1 и Лев(ПодстрокиСтрокиСоединения[0], 5) = "Srvr=" и Лев(ПодстрокиСтрокиСоединения[1], 4) = "Ref=" Тогда
    
        ИмяСервера = СтрЗаменить(Сред(ПодстрокиСтрокиСоединения[0],7, СтрДлина(ПодстрокиСтрокиСоединения[0]) - 7),":",Символы.ПС);
        ИмяБазы      = Сред(ПодстрокиСтрокиСоединения[1],6, СтрДлина(ПодстрокиСтрокиСоединения[1]) - 6);
        Порт = СтрПолучитьСтроку(ИмяСервера,2);
        Порт = Лев(Порт,СтрДлина(Порт)-1)+"0";
        ИмяСервера = СтрПолучитьСтроку(ИмяСервера,1);
        
        Попытка
            Коннектор = Новый COMОбъект("V82.COMConnector");
            
            Агент = Коннектор.ConnectAgent(ИмяСервера+?(Порт="","",":"+Порт));    
            
            Кластеры = Агент.GetClusters();
            Для каждого Кластер из Кластеры Цикл
                АдминистраторКластера = "";
                ПарольКластера = "";
                Агент.Authenticate(Кластер, АдминистраторКластера, ПарольКластера);
                Процессы = Агент.GetWorkingProcesses(Кластер);
                Для каждого Процесс из Процессы Цикл
                    Порт = Процесс.MainPort;
                   // теперь есть адрес и порт для подключения к рабочему процессу
 
                    РабПроц = Коннектор.ConnectWorkingProcess(ИмяСервера + ":" + СтрЗаменить(Порт, Символы.НПП, ""));
                    РабПроц.AddAuthentication("Администратор", "");
                    
                    ИнформационнаяБаза = "";
                    
                    Базы = Агент.GetInfoBases(Кластер);
                    Для каждого База из Базы Цикл
                        Если База.Name = ИмяБазы Тогда
                            ИнформационнаяБаза = База;
                            Прервать;
                        КонецЕсли;
                    КонецЦикла;
                    Если ИнформационнаяБаза = "" Тогда
                       // база не найдена
 
                    КонецЕсли;
                    
                    Сеансы = Агент.GetInfoBaseSessions(Кластер, ИнформационнаяБаза);
                    Для каждого Сеанс из Сеансы Цикл
                        Если нРег(Сеанс.AppID) = "backgroundjob" ИЛИ нРег(Сеанс.AppID) = "designer" ИЛИ нРег(Сеанс.AppID) = "comconsole" Тогда
                           // если это сеансы конфигуратора или фонового задания, то не отключаем
 
                            Продолжить;
                        КонецЕсли;
                        Если Сеанс.userName = ИмяПользователя() Тогда
                           // это текущий пользователь
 
                            Продолжить;
                        КонецЕсли;
                       //Сообщить(ТекущаяДата()-Сеанс.dbProcTookAt); //здесь не заполняется dbProcTookAt, поэтому отключил это
 
                       //Агент.TerminateSession(Кластер, Сеанс);
 
                    КонецЦикла;
                    
                    ИнформационнаяБаза2 = РабПроц.CreateInfoBaseInfo(); 
                    ИнформационнаяБаза2.Name = ИмяБазы; 
                    СоединенияБазы = РабПроц.GetInfoBaseConnections(ИнформационнаяБаза2);                    
                   // Разорвать соединения клиентских приложений.
 
                    Для Каждого Соединение Из СоединенияБазы Цикл
                        Если нРег(Соединение.AppID) = "backgroundjob" ИЛИ нРег(Соединение.AppID) = "designer" ИЛИ нРег(Соединение.AppID) = "comconsole" Тогда
                           // если это соединение конфигуратора или фонового задания, то не отключаем
 
                            Продолжить;
                        КонецЕсли;
                        Если Соединение.UserName = ИмяПользователя() Тогда
                           // это текущий пользователь
 
                            Продолжить;
                        КонецЕсли;
                        Осталось = 120-(ТекущаяДата()-Соединение.dbProcTookAt);//здесь 120 это 2 минуты это так для примера, можно свою константу
 
                        Сообщить(Осталось);
                        Если Осталось<=0 Тогда
                            РабПроц.Disconnect(Соединение);
                        КонецЕсли;
                    КонецЦикла;
                КонецЦикла;
            КонецЦикла;
        Исключение
            СообщитьОбОшибке(ОписаниеОшибки());
        КонецПопытки; 
        
    КонецЕсли;
    
КонецПроцедуры

для 8.3

Код 1C v 8.3
   Если Найти(ВРЕГ(СтрокаСоединенияИнформационнойБазы()), "SRVR") > 0 Тогда
        // серверный вариант
        Поиск1 = Найти(ВРЕГ(СтрокаСоединенияИнформационнойБазы()), "SRVR=");
        ПодстрокаПоиска = Сред(СтрокаСоединенияИнформационнойБазы(), Поиск1 + 6);
        ИмяСервера = Лев(ПодстрокаПоиска, Найти(ПодстрокаПоиска, """") - 1);
        // теперь ищем имя базы
        Поиск1 = Найти(ВРЕГ(СтрокаСоединенияИнформационнойБазы()), "REF=");
        ПодстрокаПоиска = Сред(СтрокаСоединенияИнформационнойБазы(), Поиск1 + 5);
        ИмяБазы = Лев(ПодстрокаПоиска, Найти(ПодстрокаПоиска, """") - 1);
    Иначе
        // для других способов подключения алгоритм не актуален
        Возврат;
    КонецЕсли;


  
    connector = новый comobject("V83.COMConnector");
    AgentConnection = Connector.ConnectAgent(ИмяСервера);
    Clusters = AgentConnection.GetClusters();
  
    Для  Каждого  Cluster  Из  Clusters   Цикл
       
        Попытка
            AgentConnection.Authenticate(Cluster,,);
        Исключение
            Сообщить("Укажите корректные Имя и Пароль пользователя с правами АДМИНИСТРАТОРА КЛАЙСТЕРА");
            Возврат;
        КонецПопытки;
       
        ИнформационнаяБаза = "";
       
        Базы = AgentConnection.GetInfoBases(Cluster);
        Для каждого База из Базы Цикл
            Если ВРег(База.Name) = ВРег(ИмяБазы) Тогда
                ИнформационнаяБаза = База;
                Прервать;
            КонецЕсли;
        КонецЦикла;
       
        // Отключение сеансов
        Сеансы = AgentConnection.GetInfoBaseSessions(Cluster, ИнформационнаяБаза);
        Для каждого Сеанс из Сеансы Цикл
           
            Если нРег(Сеанс.AppID) = "backgroundjob" ИЛИ нРег(Сеанс.AppID) = "comconsole" ИЛИ нРег(Сеанс.AppID) = "designer" Тогда
                // если это сеансы com-приложения или фонового задания, то не отключаем
                Продолжить;
            КонецЕсли;
            Если Сеанс.UserName = ИмяПользователя() Тогда
                // это текущий пользователь
                Продолжить;
            КонецЕсли;
            AgentConnection.TerminateSession(Cluster, Сеанс);
            Сообщить("Отключен сеанс "+строка(Сеанс.UserName));
        КонецЦикла;
       
    КонецЦикла;
all4cf
15.12.2016 12:44Ответ № 2

У меня еще на 8.2 была похожая проблема. Боролся с пользователями, чтобы выходили из 1С. Все бестолку.

Я пошел немного другим путем.

В конфиге есть глобальная переменная "глДатаВремяПоследнейАктивностиПользователя"

При начале работы системы подключил обработчик ожидания,который запускается каждые 900 сек.

В обработчике такой код:

Код 1C v 8.х
  ТекДата = ТекущаяДата();
    Если ТекДата >= Дата(Год(ТекДата), Месяц(ТекДата), День(ТекДата), "18","0","0") Тогда
        Если РольДоступна("ПолныеПрава") Или РольДоступна("БухгалтерРасчетчик") Тогда
            // Ничего не делаем
        Иначе
            ВремяПростоя = ТекДата - глДатаВремяПоследнейАктивностиПользователя;
            Если ВремяПростоя >= 9000 Тогда
                ЗавершитьРаботуСистемы(Ложь);
            КонецЕсли;   
        КонецЕсли;
    Иначе
        глДатаВремяПоследнейАктивностиПользователя = ТекДата;
    КонецЕсли; 

Так же есть подписка на событие "ПриЗаписи". Источник: СправочникОбъект, ДокументОбъект

В обработчике подписки код:

глДатаВремяПоследнейАктивностиПользователя = ТекущаяДата();

Вот и все...

Получается, если после 18:00 в течении 2,5 часов никаких действий небыло, то завершаем сеанс.

Единственно, что если пользователь работает только с отчетами, то ДатаВремяПоследнейАктивности не меняется, т.к. подписка на событие срабатывает только на документ или справочник.

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

А в остальном этот механизм отлично работает уже больше года. Вообще проблем нет.

Migleon
15.12.2016 14:04Ответ № 3

Спасибо за методики! Вариант 1 - 1С никак не реагирует на изменения параметров засыпания сеанса и завершения спящего сеанса.Наверное либо через журнал регистрации делать, либо через глДатаВремяПоследнейАктивностиПользователя...

Migleon
15.12.2016 16:29Ответ № 4
Вопрос закрыт!
Подсказка: Щелникни по Имени пользователя напротив ответа, и тем самым покажешь, что сообщение адресовано ему.
Вы не можете отправить комментарий анонимно, пожалуйста войдите или зарегистрируйтесь.