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.