How to quickly update many 1C servers

Basically, the problem of updating the 1C platform is for the client side. There can be tens or hundreds of client computers, while the number of servers is orders of magnitude smaller. We do not have the problem of updating client machines, clients run on VDI, and there updating is reduced to installing on one virtual machine and cloning it.

After defeating clients, I want to deal with the server side. There are a sufficient number of articles on the Internet on how to update the 1C platform on client machines.

With the server side, everything is ALMOST the same. This is ALMOST what I want to tell you about.

We use Windows for 1C servers, so everything that is written below applies only to installing 1C on Windows.

Updating the server side consists of several steps:

  • Installing the 1C platform on the server

  • Registering components such as COM and the admin console

  • Updating the path to the wsisapi.dll component in the configuration files of the web server, in our case IIS.

A separate issue is the choice of the environment for launching the language and the environment for launching scripts. We wanted to use something new as little as possible, so the choice fell on something that is already everywhere – PowerShell. We have our own system for accounting servers and what services should be launched on them. From it, individual scripts are created for each server, which are launched from a single place.

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

Defeating the server installation

The essence of the entire installation boils down to running 1CEnterprise 8 (x86-64) .msi with the parameters that are in the documentation:

  • DESIGNERALLCLIENTS – all kinds of clients

  • THICKCLIENT – thick client (also allows you to run the configurator)

  • THINCLIENT is a thin client for client-server operation.

  • THINCLIENTFILE – thin client with the ability to work with file infobases

  • SERVER – server part of 1C

  • WEBSERVEREXT – Web Server Extension Components

  • CONFREPOSSERVER – configuration repository server

  • SERVERCLIENT – components for server cluster administration

  • CONVERTER77 – infobase converter from 1C: Enterprise 7.7

  • LANGUAGES – a comma-separated list of interface languages ​​for installation

That is, if we want to install the server part of 1C, then the launch of the installation will look something like this:

msiexec /i “C:LastVersion1CEnterprise 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  

And this is where the problems begin. When installing the server part, the service is registered and launched. At the same time, such startup parameters as the directory of the server files, the user under which the server service will run, cannot be specified. This causes the server service startup parameters configured in the registry to be overwritten to their default values. We tried two approaches to fix this problem:

Approach 1: We will not register and start the service

Let’s try to disable registration and start of the service. Registration and launch will be done in separate scripts. The default launch parameters are not enough. Let’s change the installer itself. Download Windows SDK and install Orca. We open our patient 1CEnterprise 8 (x86-64) .msi and, looking at the InstallExecuteSequence table, we see that many actions, including starting the service, depend on the INSTALLSRVRASSRVC parameter. Most likely, setting it to “0” will help us refuse to register and launch the service. We are looking for where it is installed. The value setting was found in the CustomAction table in the customSetSrvrAsService action. Change Target to 0 and save our transformation file DoNotRegister.mst.

We add it to the installation command, and everything is done without registering and starting the service.

msiexec /i "C:LastVersion1CEnterprise 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

Then you just need to change the path to the server agent (C: Program Files 1cv8 8.3.xx.xxxx bin ragent.exe) in the registry.

Approach 2: Let it all be erased, set up again

The second considered path – let the registry be overwritten – we will configure it again with separate scripts. As a result, we chose this path, since we wanted to make the new installation on the new server scripts too. All our settings are destroyed during installation, but we restore them.

$1cversion   = "[ВерсияПлатформы]"
$PathToBin   = 'C:Program Files1cv8'+$1cversion+'Bin'
$port        = 1540
$regport     = 1541
$range       = "1560:1591"
$HomeCat     = "[ПутьКsrvinfo]"
$PathToBin   = "$PathToBinragent.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:SystemCurrentControlSetServices$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 and Admin Console Registration

These are the simplest steps. To register COM Run
regsvr32 / n / i: user “C: Program Files 1cv8 8.3.xx.xxxx bin comcntr.dll” on PowerShell our script looks like this:

$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        = "$serviceDirectorycomcntr.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
    }
}

To register the console
regsvr32 / n / i: user “C: Program Files 1cv8 8.3.xx.xxxx bin radmin.dll” on PowerShell our script looks like this:

$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      = "$serviceDirectoryradmin.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
    }
}

Updating the path to the component wsisapi.dll

This action is also quite simple, setting up web publishing of 1C systems is reduced to creating an application in IIS consisting of default.vrd and configuring Handler mappings. With the latter, subtleties arise. Settings can be set both at the application level and at the site or server level as a whole. We took the simplest path. In the latest versions of the 1C platform, the publishing (application creation) utility creates a configuration at the application level. Since publications are born and change regularly in the process of systems development, in order not to step on the rake that we have different settings in different places, we decided to stick with one option. Every application must have a web.config configuration file. We checked all our publications and created where the config file was missing. Now in each application directory there was a web.config file and the task was reduced to replacing the platform version in the line:

scriptProcessor="C:Program Files1cv88.3.xx.xxxxbinwsisapi.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"

I hope this material was helpful to you. How do you solve the problem of updating multiple 1C servers? Share your know-how in the comments.

Similar Posts

Leave a Reply