Скрипт отключения неактивных сессий в 1С

Часто возникает задача автоматического отключения неактивных пользовательских сеансов в 1С.

Для того, чтобы выполнять эту процедуру по расписанию можно воспользоваться средствами, предоставляемыми COM-интерфейсом 1С. Такой подход позволяет использовать штатные механизмы 1С в сочетании с родными для ОС средствами автоматизации.

Пример скрипта на PowerShell, выполняющего отключение сеансов по расписанию:

# Переменные.
$server1C = «<Имя сервера>»
$bases = («<База1>»,»<База2>»)
$timeDelay = -10
$logFile = «<Путь к файлу лога>»
# Создается COM-объект подключения к 1С.
$connector = New-Object -Comobject «V83.COMConnector»
# Подключение к агенту на сервере.
$AgentConnection = $connector.ConnectAgent($server1C)
# Выбор кластера. Сейчас используется только один кластер, поэтому просто получаем единственный элемент.
$Cluster = $AgentConnection.GetClusters()[0]
# Авторизация.
$AgentConnection.Authenticate($Cluster,»»,»»)
# Для заданного списка баз в цикле получаем списки сессий и обрабатываем их.
foreach ($base in $bases)
{
$sessions1CtoTerminate = ($AgentConnection.GetSessions($Cluster) | Where-Object {$_.Infobase.Name -eq $base -and $_.AppId -ne «SrvrConsole» -and $_.AppId -ne «BackgroundJob» -and $_.LastActiveAt -lt ((Get-Date).AddHours($timeDelay))})
foreach ($session in $sessions1CtoTerminate)
{
$sessionToKillMsg = «Session ‘» + $session.infoBase.Name.ToString() + » — » + $session.userName.ToString() + » — » + $session.Host.ToString() + » — » + $session.AppID.ToString() + » — » + $session.StartedAt.ToString() + » — » + $session.LastActiveAt.ToString() + «‘ has been terminated at » + (Get-Date).ToString()
echo $sessionToKillMsg >> $logFile
$AgentConnection.TerminateSession($Cluster,$session)
}
}

Данный скрипт осуществляет отключение всех сессий, период неактивности для которых, составляет более 10 часов. При этом осуществляется дополнительная фильтрация и сессии административной консоли и фоновых заданий не отключаются. За это отвечают условия:

-and $_.AppId -ne «SrvrConsole» -and $_.AppId -ne «BackgroundJob»

 

Фильтрация по времени осуществляется с помощью условия:

-and $_.LastActiveAt -lt ((Get-Date).AddHours($timeDelay))

Get-Date возвращает текущее время, а его метод AddHours позволяет получить значение времени на 10 часов назад, просто добавив отрицательное смещение (-10 часов).

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

COM- интерфейс для 1С нельзя назвать очень богатым, однако практически все необходимые действия он позволяет выполнять. При работе из PowerShell можно использовать командлет Get-Member для просмотра свойств и методов COM-объектов. Единственный момент — некоторые свойства будут самостоятельными объектами, как, например свойство «Infobase» у сессии. Это самостоятельный объект, поэтому не стоит забывать, что для того, чтобы посмотреть, например, имя информационной базы из сессии не достаточно просто обратиться к свойству «Infobase», а необходимо обращаться к уже вложенному свойству «Infobase.Name»

Ну и еще одна тонкость — необходимо следить за разрядностью приложений. Так, например, если запустить PowerShell x64 и попытаться обратиться к x86 COM-объекту, то произойдет ошибка. В этом случае, можно запустить x86 PowerShell для корректной работы (он находится по следующему пути — %SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe).

Небольшая особенность GAL и RecipientFilter или не отображаются вложенные группы

Microsoft определяет GAL, как хранилище записей о группах, пользователях, контактах в организации Microsoft Exchange:

The global address list (GAL) is a directory that contains entries for every group, user, and contact within an organization’s implementation of Microsoft Exchange.

Механизм работы с GAL достаточно гибкий и позволяет гранулировано управлять попаданием объектов в глобальный список. А добавленная в Exchange 2010 технология Address Book Policy, позволяющая осуществлять разделение адресных книг, значительно расширила возможности работы с адресными книгами.

Это хорошо видно на примере командлета New-GlobalAddressList, который создает новый GAL Так, данный командлет позволяет задать фильтр, который будет определять, какие объекты попадут в созданный GAL. На странице документации приведен пример такого фильтра:

New-GlobalAddressList -Name GAL_AgencyB -RecipientFilter {((RecipientType -eq "UserMailbox") -and (CustomAttribute15 -eq "AgencyB"))}

В данном случае, в создаваемый GAL попадут все объекты класса UserMailbox (почтовые ящики) у которых в Active Directory атрибут «CustomAttribute15» имеет значение «AgencyB».

И вот тут кроется одна маленькая особенность. Если GAL будет создан подобным образом, то он не будет содержать другие объекты, например группы. Для того, чтобы можно было увидеть группы, обычно создается дополнительный список адресов с помощью командлета New-AddressList. Однако, если в этой ситуации попытаться просмотреть членство в группах через адресную книгу Outlook, представленных в созданном адресном списке для групп, то можно обнаружить, что вложенное членство групп не отображается. То есть, например, если в группе существуют вложенные подгруппы, то с их отображением возникнет проблема.

Корни этой проблемы растут из фильтра GAL, заданного ранее, который ограничивает участие только объектами класса UserMailbox. Таким образом, в данной ситуации более правильным вариантом является вот такой фильтр:

((CustomAttribute15 -eq ‘AgencyB’) -and ((RecipientType -eq ‘UserMailbox’) -or (ObjectClass -eq ‘Group’)))

Для изменения уже существующего GAL можно воспользоваться командой:

Get-GlobalAddressList GAL_AgencyB | Set-GlobalAddressList -RecipientFilter «((CustomAttribute15 -eq ‘AgencyB’) -and ((RecipientType -eq ‘UserMailbox’) -or (ObjectClass -eq ‘Group’)))»

Подобный фильтр можно расширять, так, чтобы включить еще и контакты с переговорными, можно воспользоваться таким фильтром:

((CustomAttribute15 -eq ‘AgencyB’) -and ((ObjectClass -eq ‘Contact’) -or (RecipientType -eq ‘UserMailbox’) -or (ObjectClass -eq ‘Group’) -or (RecipientDisplayType -eq ‘ConferenceRoomMailbox’)))