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

Конечно, существуют некоторые решения позволяющие пройти процесс бэкапа без использования стороннего софта. Например, не секрет что можно отключить терминальные сессии программно и запустить 1С с параметрами:
1cv8.exe DESIGNER /S"trum\acc" /NArhive /DumpIB"C:\scripts\tmp\MyBase_acc.dt" /Out"C:\scripts\tmp\acc.log"

где
trum — имя кластера
acc — название базы в кластере
Arhive — пользователь который в базе
и в файл C:\scripts\tmp\MyBase_acc.dt упадет бэкап базы, да еще и лог запишется.

Если с этим более менее все просто, то с процессом выкидывания пользователей в локальной сети из базы сложнее. Давайте разберем этапы этого занятия:
  • Зайти на сервер
  • Найти нужную базу
  • Получить список процессов, которые используют базу
  • Отфильтровать системные
  • Вызвать метод Disconect для остальных

Как это реализовать? COM+!
Да, 1С версий 8 экспортируют в систему новый КОМ+ обьект, через который можно получить доступ к агенту сервера, а через него и к базам. Давайте попробуем. Я использую freepascal, тк для меня он ближе. Но на других языках отличия будут минимальны, тк все манипуляции будут через ком объекты.

Объявим функцию и переменные:
function GoAut(Cluster, Bd: variant): boolean;
  var
    server, agent, clusters, workprocess, ConnectToWorkProcess,
    InfoBases, InfoBase, Connections: variant; // Виртуальные ком объекты
    i, j, k, m: integer; // счетчики циклов, пригодятся

Теперь реализуем 1 пункт плана захвата мира входа на сервер. Реализуется просто:
server := CreateOleObject('v82.COMConnector'); // Цепляемся к объекту 
agent := server.ConnectAgent(Cluster); // теперь к агенту сервера (пункт 2 в нашем плане)
clusters := agent.GetClusters(); // и наконец, получаем кластеры


Так, готово. У нас в руках два важных объекта — агент сервера и ссылка на кластеры.
Что нужно сделать? правильно! перебрать кластеры, делаем это так:
 for i := VarArrayLowBound(clusters, 1) to VarArrayHighBound(clusters, 1) do
      begin
        agent.Authenticate(clusters[i], 'AdminLogin', 'AdminPass'); // Авторизуется как админ кластера
        workprocess := Agent.GetWorkingProcesses(clusters[i]);   // и получаем список процессов в этом кластере  


Теперь, переберем все запущенные процессы в данном кластере:
for j := VarArrayLowBound(workprocess, 1)
          to VarArrayHighBound(workprocess, 1) do
        begin
          if workprocess[j].Running = 1 then 


теперь только осталось подключиться к процессу и найти нужных пользователей, делается это так:
ConnectToWorkProcess :=
              server.ConnectWorkingProcess('tcp://' + workprocess[j].HostName +
              ':' + IntToStr(workprocess[j].MainPort));
            ConnectToWorkProcess.AuthenticateAdmin('AdminLogin', 'AdminPass');
            ConnectToWorkProcess.AddAuthentication('BdLogin','BdPass'); // Пользователь в базе с правами на бэкап
            InfoBases := ConnectToWorkProcess.GetInfoBases(); // Указатель на открытые базы в данном процессе
for k := VarArrayLowBound(InfoBases, 1)
              to VarArrayHighBound(InfoBases, 1) do
            begin
              if lowercase(InfoBases[k].Name) = lowercase(bd) then
              begin
                InfoBase := InfoBases[k];
                Connections :=
                  ConnectToWorkProcess.GetInfoBaseConnections(InfoBase);
                for m :=
                  VarArrayLowBound(Connections, 1)
                  to VarArrayHighBound(Connections, 1) do
                begin
                  if (((Connections[m].AppID) <> 'COMConsole') and
                    (Connections[k].AppID <> 'SrvrConsole')) then
                    ConnectToWorkProcess.Disconnect(Connections[m]); // Урра, мы его убили (Кенни, ты?)!
               end;
             end;
           end;


Порядок, процесс отправлен к прародителю. Теперь можно делать бэкап. Код получился громоздким, но работающим.

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

Страничка с проектом: sourceforge.net/projects/cbackaper/files

Кратко:
  • Умеет слать логи на электронку
  • Умеет выкидывать пользователей из базы
  • Поддержка шаблонов настроек для баз, применение шаблона global по умолчанию
  • Поддержка нескольких папок-приемников
  • Консольная
  • Малый размер (относительно — 136 Кб)


Хотелось бы услышать отзывы и предложения. Проект для меня актуален, поэтому планирую его развивать. Так же там выложены сорцы проекта, для тех энтузиастов, что решат вместе со мной изобрести велосипед — качественный аналог платных программ.