В основном проблема обновления платформы 1С стоит для клиентской части. Клиентских компьютеров может быть десятки и сотни, в то время как серверов на порядки меньше. У нас проблема обновления клиентских машин не стоит, клиенты запускаются на VDI, а там обновление сводится к установке на одной виртуальной машине и ее клонировании.

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

С серверной частью все ПОЧТИ тоже самое. Вот про это ПОЧТИ и хочу рассказать.

У нас для серверов 1С используется Windows, поэтому все, что написано далее относится только к установке 1С на Windows.

Обновление серверной части, состоит из нескольких действий:

  • Установка платформы 1С на сервере

  • Регистрация компонентов, таких как COM и консоль администрирования

  • Обновление пути к компоненте wsisapi.dll в конфигурационных файлах веб-сервера, в нашем случае IIS.

Отдельный вопрос - выбор среды для запуска языка и среды запуска скриптов. Нам хотелось как можно меньше использовать чего-то нового, поэтому выбор пал на то, что уже есть везде -  PowerShell. У нас есть своя система для учета серверов и какие сервисы на них должны быть запущены. Из нее создаются индивидуальные скрипты для каждого сервера, которые запускаются из единого места.

$session = New-PSSession -ComputerName [Сервер];
Invoke-Command  -Session $session -ScriptBlock {[Скрипт]} ;
Remove-PSSession $session

Побеждаем установку сервера

Суть всей установки сводится к запуску 1CEnterprise 8 (x86-64).msi с параметрами, которые есть в документации:

  • DESIGNERALLCLIENTS - все виды клиентов

  • THICKCLIENT – толстый клиент (в том числе позволяет запускать конфигуратор)

  • THINCLIENT – тонкий клиент для клиент-серверного варианта работы.

  • THINCLIENTFILE – тонкий клиент с возможностью работы с файловыми информационными базами

  • SERVER – серверная часть 1С

  • WEBSERVEREXT – компоненты расширения для веб-сервера

  • CONFREPOSSERVER – сервер хранилища конфигураций

  • SERVERCLIENT – компоненты для администрирования кластера серверов

  • CONVERTER77 – конвертер информационных баз из версии 1С:Предприятия 7.7

  • LANGUAGES – список языков интерфейса для установки через запятую

То есть, если хотим установить серверную часть 1С, то запуск установки будет выглядеть примерно так:

msiexec /i “C:\LastVersion\1CEnterprise 8 (x86-64).msi”    /qn 
TRANSFORMS=adminstallrestart.mst;1049.mst DESIGNERALLCLIENTS=1 
THICKCLIENT=0 THINCLIENTFILE=0 THINCLIENT=0 WEBSERVEREXT=1 SERVER=1 CONFREPOSSERVER=0 CONVERTER77=0 SERVERCLIENT=1 LANGUAGES=RU  

И вот здесь начинаются проблемы. При установке серверной части происходит регистрация сервиса и его запуск. При этом, такие параметры запуска, как каталог файлов сервера, пользователь под которым будет работать служба сервера указать невозможно. Это приводит к тому, что настроенные в реестре параметры запуска службы сервера будут перезаписаны на значения по умолчанию. Мы попробовали два подхода к устранению этой неприятности:

Подход 1: Не будем регистрировать и запускать сервис

Попробуем отключить регистрацию и запуск сервиса. Регистрацию и запуск сделаем отдельными скриптами. Стандартных параметров запуска недостаточно. Давайте поменяем саму программу установки. Качаем Windows SDK и устанавливаем Orca. Открываем нашего пациента 1CEnterprise 8 (x86-64).msi и, посмотрев на таблицу InstallExecuteSequence, видим, что многие действия, в том числе и запуск сервиса, зависят от параметра INSTALLSRVRASSRVC. Скорее всего его установка в «0» и поможет нам отказаться от регистрации и запуска сервиса. Поиском ищем, где же он устанавливается. Установка значения нашлась в таблице CustomAction в действии customSetSrvrAsService. Меняем Target на 0 и сохраняем наш файл трансформации DoNotRegister.mst.

Добавляем его в команду установки, и все выполняется без регистрации и запуска сервиса.

msiexec /i "C:\LastVersion\1CEnterprise 8 (x86-64).msi" /qr 
TRANSFORMS=adminstallrelogon.mst;1049.mst;DoNotRegister.mst DESIGNERALLCLIENTS=1 
THICKCLIENT=0 THINCLIENTFILE=0 THINCLIENT=0 WEBSERVEREXT=1 SERVER=1 CONFREPOSSERVER=0 CONVERTER77=0 SERVERCLIENT=1 LANGUAGES=RU

Далее необходимо только сменить путь к агенту сервера (C:\Program Files\1cv8\8.3.xx.xxxx\bin\ragent.exe) в реестре.

Подход 2: Пусть все будет стерто, настроим заново

Второй рассмотренный путь - пусть реестр будет перезаписан - отдельными скриптами настроим его заново. Мы в результате выбрали этот путь, так как хотели и новую установку на новый сервер тоже делать скриптами. Все наши настройки при установке сносятся, но мы их восстанавливаем.

$1cversion   = "[ВерсияПлатформы]"
$PathToBin   = 'C:\Program Files\1cv8\'+$1cversion+'\Bin'
$port        = 1540
$regport     = 1541
$range       = "1560:1591"
$HomeCat     = "[ПутьКsrvinfo]"
$PathToBin   = "$PathToBin\ragent.exe"
$SrvcName    = "1C:Enterprise 8.3 Server Agent (x86-64)"
$ImagePath   = "`"$PathToBin`" -srvc -agent -regport $regport -port $port -range $range -debug -d `"$HomeCat`""
$Desctiption = "Агент сервера 1С:Предприятия 8.3"

$username    = "[Пользователь]"
$password    = "[Пароль]"

$secureStringPwd = $password | ConvertTo-SecureString -AsPlainText -Force 
$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $username, $secureStringPwd
    
    $allServices1C = Get-WmiObject win32_service | ?{$_.Name -like '*'} |Select Name, DisplayName, State, PathName | Where-Object { $_.PathName  -Like "*ragent.exe*" };
    $m = $allServices1C | measure
    $m.Count
    if ($m.Count -gt 0) { 
     
    $allServices1C | % {
                $services1C      = $_;
                $serviceExecPath = $services1C.PathName;
                $serviceName     = $services1C.name;
                $serviceExecPathRagent = $services1C.PathName.split('"')[1];
                $platformVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($serviceExecPathRagent).FileVersion
                $NewPath = $services1C.PathName -replace $platformVersion,$1cversion
                Write-Host "Найдена уже установленная служба агента 1с $serviceName"
                try 
                        {
                            if ($services1C.State -eq "Running"){Write-host "Останавливаем сервис $serviceName"; Stop-Service -Name $serviceName -Force}
                            Write-host "Меняем path службы на $NewPath"
                            Set-ItemProperty -Path "HKLM:\System\CurrentControlSet\Services\$serviceName" -Name ImagePath -Value "$NewPath"
                             Write-Host "Запускаем сервис $serviceName "
                             Start-Service -Name $serviceName 
                             sleep(10)
                             if ($services1C.State -eq "Running") { Write-host "Сервис запущен успешно"; write-host "ErrCode 0"}
                             else { Write-Host "Сервис $serviceName не запустился!" ;Write-Host "ErrCode 1"}
                          

                     }catch
                         {
                            Write-Host "Ошибка при изменении службы $serviceName" -ForegroundColor Red
                            Write-Host "Подробно:" -ForegroundColor Red
                            Write-Host $Error[0] -ForegroundColor Red
                            Write-Host "ErrCode 1"
                        } }
    }
    else {
      Write-Host "Устанавливаем службу 1С $SrvcName" 
    try{
        New-Service -Name $SrvcName -BinaryPathName $ImagePath -Description $Desctiption -DisplayName $Desctiption -StartupType Automatic -Credential $creds 
        Start-Service -Name $serviceName;
        Write-Host "Сервис $SrvcName зарегистрирован и запущен!" -ForegroundColor Green
        Write-Host "ErrCode 0" 

    } catch {
     Write-Host "Ошибка при регистрации компоненты!" -ForegroundColor Red
        Write-Host "Подробно:" -ForegroundColor Red
        Write-Host $Error[0] -ForegroundColor Red
        Write-Host "ErrCode 1" -ForegroundColor Red
    }
    
    }

Регистрация COM и консоли администрирования

Это самые простые действия. Для регистрации COM Запускаем
regsvr32 /n /i:user "C:\Program Files\1cv8\8.3.xx.xxxx\bin\comcntr.dll" на PowerShell наш скрипт выглядит так:

$allServices1C = Get-WmiObject win32_service | ?{$_.Name -like '*'} |
    Select Name, DisplayName, State, PathName | 
    Where-Object { $_.PathName  -Like "*ragent.exe*" };

$allServices1C | % {
    
    $services1C = $_;
    $serviceExecPath = $services1C.PathName;
    $serviceExecPathRagent = $services1C.PathName.split('"')[1];
    
	$serviceDirectory = [System.IO.Path]::GetDirectoryName($serviceExecPathRagent);
    $comcntrPath        = "$serviceDirectory\comcntr.dll";
    $regCommand       = "regsvr32.exe /s ""$comcntrPath""";
    $platformVersion  = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($serviceExecPathRagent).FileVersion

    Write-Host "Начало регистрации COM-компоненты 1С:Предприятия";
    Write-Host "Версия платформы: $platformVersion";
    Write-Host "Путь к DLL: ""$comcntrPath""";
    Write-Host "Команда регистрации компоненты: ""$regCommand""";

    try
    {
        cmd /c "$regCommand"
        Write-Host "Регистрация компоненты успешно выполнена!" -ForegroundColor Green
        Write-Host "ErrCode 0"
    } catch
    {
        Write-Host "Ошибка при регистрации компоненты!" -ForegroundColor Red
        Write-Host "Подробно:" -ForegroundColor Red
        Write-Host "ErrCode 1" -ForegroundColor Red
    }
}

Для регистрации консоли
regsvr32 /n /i:user "C:\Program Files\1cv8\8.3.xx.xxxx\bin\radmin.dll" на PowerShell наш скрипт выглядит так:

$allServices1C = Get-WmiObject win32_service | ?{$_.Name -like '*'} |
    Select Name, DisplayName, State, PathName | 
    Where-Object { $_.PathName  -Like "*ragent.exe*" };

$allServices1C | % {
    
    $services1C = $_;
    $serviceExecPath = $services1C.PathName;
    $serviceExecPathRagent = $services1C.PathName.split('"')[1];
    
	$serviceDirectory = [System.IO.Path]::GetDirectoryName($serviceExecPathRagent);
    $radminPath      = "$serviceDirectory\radmin.dll";
    $regCommand       = "regsvr32.exe /s ""$radminPath""";
    $platformVersion  = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($serviceExecPathRagent).FileVersion

    Write-Host "Начало регистрации COM-компоненты 1С:Предприятия";
    Write-Host "Версия платформы: $platformVersion";
    Write-Host "Путь к DLL: ""$radminPath""";
    Write-Host "Команда регистрации компоненты: ""$regCommand""";

    try
    {
        cmd /c "$regCommand"
        Write-Host "Регистрация компоненты успешно выполнена!" -ForegroundColor Green
        Write-Host "ErrCode 0"
    } catch
    {
        Write-Host "Ошибка при регистрации компоненты!" -ForegroundColor Red
        Write-Host "Подробно:" -ForegroundColor Red
        Write-Host "ErrCode 1" -ForegroundColor Red
    }
}

Обновление пути к компоненте wsisapi.dll

 Данное действие тоже достаточно простое, настройка веб публикации 1С систем сводится созданию в IIS приложения состоящего default.vrd и конфигурированием Handler mappings. С последним возникают тонкости. Настройки могут быть заданы как на уровне приложения, так и на уровне сайта или сервера в целом. Мы пошли по наиболее простому пути. В последних версиях платформы 1С утилита публикации (создания приложений) создает конфигурацию на уровне приложения. Так как публикации рождаются и изменяются регулярно в процессе развития систем, то чтобы не наступить на грабли, что в разных местах у нас разные настройки, решили остановиться на одном варианте. Конфигурационный файл web.config должен быть у каждого приложения. Мы проверили все наши публикации и там, где отсутствовал конфигурационный файл, создали его. Теперь в каждой директории приложения имелся файл web.config и задача свелась к замене версии платформы в строке:

scriptProcessor="C:\Program Files\1cv8\8.3.xx.xxxx\bin\wsisapi.dll"
Что мы делаем скриптом:
$result = Get-ChildItem -Path "[АдресПапкиСПубликациями]" -Recurse -ErrorAction SilentlyContinue -Include "web.config"
$1cUpdateV = "[ВерсияПлатформы]"
foreach($f in $result) {
    $fullname = $f.fullname
    $Text = Get-Content $f.FullName -raw 
    $pattern = "(?:C:\\Program Files\\1cv8\\)(?<version>\d+\.\d+\.\d+\.\d+)(?:\\bin\\wsisapi\.dll)"
    $te = $Text -match $pattern 
    if ($Matches.Count -ne 0) {  
       $1cVersionold = $Matches["version"]
       if ($1cVersionold -ne $Version1c) {
        $replaceText = $Text -replace "$1cVersionold","$1cUpdateV"
        Set-Content -Path $fullname -Value $replaceText
           Write-Host "файл $fullname изменен версия платформы старая $1cVersionold новая $1cUpdateV"
       } else { Write-Host "файл $fullname не изменен. Версии совпадают"}
       
       }

}
Write-Host "ErrCode 0"

Надеюсь, этот материал оказался полезным для вас. А как вы решаете проблему обновления нескольких серверов 1С? Делитесь вашими know-how в комментариях.

Комментарии (3)


  1. Sergey-S-Kovalev
    15.10.2021 21:16
    +2

    Я предпочитаю вместо обновления разворачивать новый сервер, так проще откатиться и обеспечить иммутабельность. Ну и быть на актуальной версии не только платформы 1С. Обновление может быть актуальным только, если программные ключи активированы на этом же сервере, но на практике это сильно ограничивает в возможностях по гибкой настройке сервера в зависимости от планируемых нагрузок.

    Серверную часть можно ставить как приложение, без автоматического создания сервиса, а сервис доставлять и настраивать уже отдельно. Это избавляет от ковыряния в ORCA. На моей памяти серверная часть в принципе на ставилась автоматически и этой проблеме уже годы, возможно в последних версиях платформы это починили. Протестирую Ваш код завтра :)

    Компоненты управления сервером 1С тоже ставить особо незачем. Оснасткой можно цепляться по сети. Базы можно прописывать через COM-соединения. Повисшие или не нужные соединения так же можно в любой момент прибить скриптом.

    Статья немного сумбурная, но всеравно спасибо.


    1. langoner
      19.10.2021 19:53

      Удалось протестировать наш код?)


      1. Sergey-S-Kovalev
        26.10.2021 17:01

        Ну раз вопрос возник, то пришлось протестировать ту часть, которая у меня вызвала подозрения:

        msiexec /i “C:\LastVersion\1CEnterprise 8 (x86-64).msi”    /qn 
        TRANSFORMS=adminstallrestart.mst;1049.mst DESIGNERALLCLIENTS=1 
        THICKCLIENT=0 THINCLIENTFILE=0 THINCLIENT=0 WEBSERVEREXT=1 SERVER=1 CONFREPOSSERVER=0 CONVERTER77=0 SERVERCLIENT=1 LANGUAGES=RU

        Ставит платформу, но служба "1C:Enterprise 8.3 Server Agent (x86-64)" не появляется. К счастью 1С не имеет привычки ставить службу под Локальной Системой, ей напрямую ключами нужно указывать имя пользователя и пароль. Как следствие кусок статьи про Orca не нужен.

        Проверял на дистрибутиве 1С windows64full_8_3_20_1549 и под Windows Server 2019 Standard

        Серверная часть как не ставилась автоматически (а мы говорим про дистрибутив содержащий "1CEnterprise 8 Server (x86-64).msi") так и продолжает этого не делать с классической ошибкой: Windows Installer installed the product. Product Name: 1C:Enterprise 8 Server (x86-64). Product Version: 8.3.20.1549. Product Language: 1033. Manufacturer: 1C-Soft. Installation success or error status: 1624.