«Жемчужный» доступ к 1С: Предприятию 8.2

в 12:36, , рубрики: 1c 8.2, 1c:предприятие, OLE, perl, Администрирование баз данных, ненормальное программирование, метки: , , , ,

Думаю, всем вам известен такой программный продукт, как 1С: Предприятие 8.2. И, наверное, многим из вас известен тот факт, что к 1С: Предприятию можно подключиться, используя OLE/COM-соединение. А многие ли из вас знают, что с помощью OLE/COM-соединения можно не только выполнять программный код 1С, но и “управлять” сервером 1С: Предпрития? К примеру, можно подключиться к Агенту кластера серверов 1С: Предприятия, получить список открытых клиентских сессий, прочитать информацию о выданных им лицензиях… К тому же, наличие варианта подключения посредством OLE/COM-соединения расширяет в арсенале программиста добавляет возможность выбора языка программирования, отличного от встроенного языка 1С: Предприятия. Можно выбрать любой язык, который способен работать с OLE/COM-компонентами: будь то VB.Net, C#.Net, или Java, или даже… Perl. Да, вы не ослышались. Именно Perl.

Итак…

Задача.

Необходимо реализовать автоматический рестарт службы Агент сервера 1С: Предприятия 8.2 с помощью планировщика задач Windows. Но перед рестартом необходимо проверить, не работает ли кто-нибудь в базе Base, расположенной на сервере 1С: Предприятия. Если кто-нибудь работает, то перезапуск службы недопустим.

Решение.

У вас может закрасться вопрос, мол, зачем нужно периодически перезапускать службу Агента сервера? Дело в том, что в версии 1С: Предприятие 8.2 х64 есть одна “маленькая” ошибка. Она возникает при динамическом обновлении информационной базы и приводит БД к невозможности обновления и работы в ней. Разработчики официально (в личной переписке с ними) заявили, что данная ошибка не планируется к исправлению в версии 8.2. Придется ждать и “выживать” до официального релиза 8.3. Я-то знаю способ исправления этой ошибки (если надо — расскажу в комментариях или апдейте статьи). Но, как заверяют разработчики, данный способ обхода может разрушить базу данных совсем. У меня за год использования этого способа обхода база не разрушилась. Но не об этом статья.

Итак. Задача поставлена. Основной проблемой для меня стало условие проверки существующих подключений к определенной БД. Для реализации поставленной задачи я решил не использовать встроенный язык 1С: Предприятия, ни один из .Net-языков, а также Java (only console, only true linux-way).

В синтаксис-помощнике 1С: Предприятия был найден метод проверки наличия подключений к БД, но он предполагал использование OLE/COM-соединения к Агенту сервера 1С: Предприятия. Что ж… Приступим.

Выдержка из синтаксис-помощника

Соединение с агентом сервера (IServerAgentConnection)
GetInfoBaseConnections (GetInfoBaseConnections)
Синтаксис:

GetInfoBaseConnections(<Кластер>, <ИнформационнаяБаза>)

Параметры:

<Кластер> (обязательный)
Тип: Кластер серверов. Кластер серверов, для которого должен быть получен массив описаний соединений.

<ИнформационнаяБаза> (обязательный)
Тип: Описание информационной базы. Информационная база, для которой должен быть получен массив описаний соединений.

Возвращаемое значение:
Тип: COMSafeArray. Массив описаний соединений кластера. Каждое описание соединения представлено объектом с интерфейсом Описание соединения.

Описание:
Получает массив описаний соединений информационной базы.

Доступность:
Интеграция.

Для работы с OLE/COM-объектами средствами Perl нам понадобиться задействовать модуль Win32::OLE. В используемой мной сборке StrawberryPerl данный модуль уже был предустановлен. Но даже если это не так, можно установить его через CPAN:

C:Perlperlbincpan Win32::OLE

Чтобы получить список соединений базы данных 1С, нам нужно:

  • Создать COM-подключение к объекту V82.COMConnector;
  • Подключиться к агенту кластера серверов 1С: Предприятия;
  • Получить объект кластера 1С;
  • Авторизоваться на кластере;
  • Получить список баз 1С на этом кластере;
  • Найти необходимую нам базу;
  • Получить список активных соединений к этой базе данных.

Вот код с комментариями, который получает список активных соединений клиентов с базой данных 1С: Предприятия, расположенной на сервере 1С: Предприятия.

use strict;
use warnings;

use Win32::OLE;

use Data::Dumper;

sub getConnectionsCount {
    # имя сервера (с портом) и имя базы будем получать из параметров метода
    my ($server, $dbname) = @_;
    # создаем COM-соединение
    my $ole1c = Win32::OLE->new("V82.COMConnector") or die "Could not create OLE-connector!n";
    # создаем объект Агента сервера 1С:Предприятия
    my $_agent = $ole1c->ConnectAgent($server) or die "Could not connect to server!n" . cnv(Dumper $ole1c->ErrorDescription());
    # получаем объект кластера (у меня один кластер)
    my $_cluster = $_agent->GetClusters()->[0] or die "Could not get cluster 0 from arrayn";
    # авторизуемся на кластере серверов. 
    # Авторизоваться надо с помощь логина и пароля Администратора кластера серверов,
    # которого можно задать в утилите Администрирования сервера 1С:Предприятия.
    # не путайте этого администратора с администратором базы данных, что заводится
    # через конфигуратор в пользователях.
    # У меня нет администраторов, оставляю пустыми параметры логина и пароля.
    $_agent->Authenticate($_cluster, "", "");
    # получаем список баз данных, расположенных в данном кластере
    my $_basesinfo = $_agent->GetInfoBases($_cluster);
    # найдем нашу базу данных
    my @_bases = grep { defined $_->{Name} && $_->{Name} =~ m/^$dbname$/ } @$_basesinfo;
    # она точно будет одна
    my $_base = $_bases[0];
    # заведем счетчик подключений
    my $connCounter = 0;
    # получим все активные подключения или сразу вернем 0
    my $_baseconns = $_agent->GetInfoBaseConnections($_cluster, $_base) or return 0;
    # “отсечем” все соединения по типу приложения, на которые можно не обращать внимание.
    # если эти подключения есть, то можно смело перегружать службу 
    # Агента сервера 1С:Предприятия
    foreach (@$_baseconns) {
        # нам не важны планировщики задач и подключения через консоль кластера
        if ($_->{Application} !~ m/JobScheduler/ && $_->{Application} !~ m/SrvrConsole/) {
            $connCounter++;
        }
    }

    return $connCounter;
}

# вызов очень простоой.
# только порт нужно указывать тот, который слушает агент кластера серверов 1С:Предприятия
print “There are “ . getConnectionsCount(“localhost:1540”, “Base”) . “ active connectionsn”;

Перезапустить службу Агента можно с помощью команд “net start” и “net stop”:

net stop <ИмяСлужбы>
net start <ИмяСлужбы>

Полный код, выполняющий поставленную задачу я расположил на Bitbucket-е.

Автор: bvn13

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js