Тестировалось на релизах 8.3.10 (32 бита) и 8.3.16 (64 бита). Файловый и клиент-серверный варианты. Толстый клиент, регламентное задание.
Требования: сеанс 1С, в котором выполняется данный функционал, должен быть запущен от имени локального администратора. В случае использования в регламентном задании - от имени админа должна быть запущена служба 1С. При работе с файловым вариантом базы дополнительно потребуется запуск на компьютере, с непосредственным расположением базы данных. Пользователь 1С должен обладать административными правами.
Некоторые специфические данные возможно придется указать непосредственно в самой обработке (например имя кластера или время срабатывания).
Обработку, точнее ее процедуру "ВыполнитьОбработку" можно вызывать, например после обмена. Либо как процедуру в регламентном задании. А можно выдернуть нужное и оформить в виде "батника", скрипта или любом другом.
ДЛЯ ИСПОЛЬЗОВАНИЯ ТРЕБУЕТСЯ ПЕРЕОПРЕДЕЛИТЬ НАЗНАЧЕНИЕ ПЕРЕМЕННЫХ, ОПИСАННЫХ В БЛОКЕ "ЗДЕСЬ ЗАДАЮТСЯ ПАРАМЕТРЫ".
Процедура ВыполнитьОбработку() Экспорт
//---------------ЗДЕСЬ ЗАДАЮТСЯ ПАРАМЕТРЫ-----------------------------------------------
//ТУТ МЕНЯЕМ ПАРАМЕТРЫ ДЛЯ РАБОТЫ В КЛИЕНТ-СЕРВЕРНОМ ВАРИАНТЕ, если необходимо
ИмяКластера = "Локальный кластер";
АдминистраторКластера = "";
ПарольАдминистратораКластера = "";
//каталог для записи выгрузки БД и логов
КаталогДляБекапа = "C:\TEMP\";
Роль = Метаданные.Роли.Администратор; //тут заменить на свою роль
//время для запуска
ТекущийЧас = Час(ТекущаяДата());
//Если ТекущийЧас >= 8 И ТекущийЧас <= 21 Тогда
// возврат;
//КонецЕсли;
//---------------ЗДЕСЬ НИЧЕГО НЕ МЕНЯТЬ-----------------------------------------------
Если НЕ КонфигурацияИзменена() Тогда
Возврат;
КонецЕсли;
//определим тип платформы 1с
СистемнаяИнформация = Новый СистемнаяИнформация;
лпТипПлатформы = СокрЛП(СистемнаяИнформация.ТипПлатформы);
//определим разрядность ОС
WshShell = Новый COMОбъект("WScript.Shell");
Разрядность = ?(Найти(WshShell.Environment("SYSTEM").item("PROCESSOR_ARCHITECTURE"), "64") > 0, 64, 32);
//определение пути запуска powershell
Если Разрядность = 64 И лпТипПлатформы = "Windows x86" Тогда
PS = "C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe";
Иначе
PS = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe";
Конецесли;
//файл выгрузки
ФайлВыгрузки = КаталогДляБекапа + "Base.dt";
//файл логов
ФайлЛогов = КаталогДляБекапа + "Log_Execute_ANR_"+Формат(ТекущаяДата(),"ДФ=ддММгггг")+".txt";
//файл скрипта
ФайлСкрипта = КаталогВременныхФайлов()+"Автообновление.ps1";
//ПРОВЕРКА НА ПОВТОРНЫЙ ЗАПУСК
Файл = Новый Файл(ФайлЛогов);
Если Файл.Существует() Тогда
возврат;
Иначе
Текст = Новый ТекстовыйДокумент;
Текст.ДобавитьСтроку("Команда запуска скрипта: "+PS+" -ExecutionPolicy RemoteSigned -File " + ФайлСкрипта);
Текст.Записать(ФайлЛогов,"windows-1251");
КонецЕсли;
//определение файла запуска 1с
ИсполняемыйФайл = КаталогПрограммы()+"1cv8s.exe";
//создание пользователя для выполнения операций
Если ПользователиИнформационнойБазы.НайтиПоИмени("СервисныйПользователь_АвтообновлениеКонфигурации") = Неопределено Тогда
НовыйПользователь = ПользователиИнформационнойБазы.СоздатьПользователя();
НовыйПользователь.Имя = "СервисныйПользователь_АвтообновлениеКонфигурации";
НовыйПользователь.ПолноеИмя = "СервисныйПользователь_АвтообновлениеКонфигурации";
НовыйПользователь.АутентификацияСтандартная = Истина;
НовыйПользователь.Пароль = "iddqd";
НовыйПользователь.Роли.Добавить(Роль);
НовыйПользователь.ПоказыватьВСпискеВыбора = Ложь;
НовыйПользователь.Записать();
КонецЕсли;
//объект для записи скрипта
Текст = Новый ТекстовыйДокумент;
//определение типа БД
СтрокаСоединения = СтрокаСоединенияИнформационнойБазы();
//создание файла-скрипта
Если Найти(СтрокаСоединения,"Srvr=") = 0 Тогда //это файловая база
//переменные
КаталогИБ = УНФ.ОпциональныйБэкСлеш_(НСтр(СтрокаСоединения, "File"));
ПараметрыБекап = " DESIGNER /F""" + КаталогИБ + """ /NСервисныйПользователь_АвтообновлениеКонфигурации /Piddqd /DumpIB """ + ФайлВыгрузки + """ /Out """ + КаталогДляБекапа + "Log_Dump_ANR.txt""";
ПараметрыАпдейт = " DESIGNER /F""" + КаталогИБ + """ /NСервисныйПользователь_АвтообновлениеКонфигурации /Piddqd /UpdateDBCfg /Out """ + КаталогДляБекапа + "Log_Update_ANR.txt""";
//запись в файл
Текст.ДобавитьСтроку("$ИсполняемыйФайл = """ + ИсполняемыйФайл + """");
Текст.ДобавитьСтроку("$КаталогИБ = """ + КаталогИБ + """");
Текст.ДобавитьСтроку("$ПараметрыБекап = '" + ПараметрыБекап + "'");
Текст.ДобавитьСтроку("$ПараметрыАпдейт = '" + ПараметрыАпдейт + "'");
Текст.ДобавитьСтроку("$ФайлВыгрузки = '" + ФайлВыгрузки + "'");
Текст.ДобавитьСтроку("$ФайлЛогов = '" + ФайлЛогов + "'");
Текст.ДобавитьСтроку("");
Текст.ДобавитьСтроку("(Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Скрипт запущен""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку("");
Текст.ДобавитьСтроку("(Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Отключаем сетевые соединения""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку("net files | where {$_.Contains($КаталогИБ)} | foreach {$_.Split( ' ' )[0]} | foreach {net file $_ /close}");
Текст.ДобавитьСтроку("(Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Отключили сетевые соединения""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку("");
Текст.ДобавитьСтроку("(Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Завершаем процессы 1cv8""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку("Get-WmiObject -Class Win32_Process -Filter ""Name like '1cv8%'"" | Foreach-Object {$_.Terminate()}");
Текст.ДобавитьСтроку("(Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Завершили процессы 1cv8""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку("");
Текст.ДобавитьСтроку("(Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Выполняем бекап базы""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку("$procid = (Start-Process $ИсполняемыйФайл -ArgumentList $ПараметрыБекап -Passthru).id");
Текст.ДобавитьСтроку("$countchild = 1");
Текст.ДобавитьСтроку("while ($countchild -ne 0)");
Текст.ДобавитьСтроку(" {");
Текст.ДобавитьСтроку(" $pr = Get-WmiObject Win32_Process -Filter ""ParentProcessId='$procid' or ProcessId='$procid'"" | measure");
Текст.ДобавитьСтроку(" $countchild = $pr.Count");
Текст.ДобавитьСтроку(" Start-Sleep 10");
Текст.ДобавитьСтроку(" }");
Текст.ДобавитьСтроку("(Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Выполнили бекап базы""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку("");
Текст.ДобавитьСтроку("Start-Sleep 10");
Текст.ДобавитьСтроку("$isfile = Test-Path $ФайлВыгрузки");
Текст.ДобавитьСтроку("if ($isfile -eq ""True"")");
Текст.ДобавитьСтроку(" {");
Текст.ДобавитьСтроку(" (Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Выполняем обновление конфигурации""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку(" Start-Process $ИсполняемыйФайл -ArgumentList $ПараметрыАпдейт");
Текст.ДобавитьСтроку(" (Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Выполнили обновление конфигурации""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку(" }");
Текст.ДобавитьСтроку("else");
Текст.ДобавитьСтроку(" {");
Текст.ДобавитьСтроку(" (Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Файл бекапа не найден. Обновление не выполнено""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку(" }");
Текст.Записать(ФайлСкрипта);
Иначе //клиент-серверный вариант
//регистрация COM из "правильной" папки
Если Разрядность = 64 И лпТипПлатформы = "Windows x86" Тогда
ПутьРегистратора = "C:\Windows\SysWOW64\regsvr32.exe";
Иначе
ПутьРегистратора = "C:\Windows\System32\regsvr32.exe";
Конецесли;
WshShell.Run(ПутьРегистратора + " /s """+КаталогПрограммы()+"comcntr.dll""");
Попытка
Коннектор = Новый COMОбъект("v83.COMConnector");
Исключение
//нет объекта - нет пруфа
возврат;
КонецПопытки;
Коннектор = Неопределено;
//переменные
ИмяСервера = Сред(СтрокаСоединения, 7, Найти(СтрокаСоединения, ";")-8);
ИмяБазы = Сред(СтрокаСоединения, Найти(СтрокаСоединения, "Ref=")+5, СтрДлина(СтрокаСоединения)-СтрДлина(ИмяСервера)-15);
ПараметрыБекап = " DESIGNER /S""" + ИмяСервера + "\" + ИмяБазы + """ /NСервисныйПользователь_АвтообновлениеКонфигурации /Piddqd /DumpIB """ + ФайлВыгрузки + """ /UC iddqd /Out """ + КаталогДляБекапа + "Log_Dump_ANR.txt""";
ПараметрыАпдейт = " DESIGNER /S""" + ИмяСервера + "\" + ИмяБазы + """ /NСервисныйПользователь_АвтообновлениеКонфигурации /Piddqd /UpdateDBCfg /UC iddqd /Out """ + КаталогДляБекапа + "Log_Update_ANR.txt""";
//запись в файл
Текст.ДобавитьСтроку("$ИсполняемыйФайл = """ + ИсполняемыйФайл + """");
Текст.ДобавитьСтроку("$ИмяСервера = """+ИмяСервера+"""");
Текст.ДобавитьСтроку("$ИмяКластера = """+ИмяКластера+"""");
Текст.ДобавитьСтроку("$АдминистраторКластера = """+АдминистраторКластера+"""");
Текст.ДобавитьСтроку("$ПарольАдминистратораКластера = """+ПарольАдминистратораКластера+"""");
Текст.ДобавитьСтроку("$ИмяБазы = """+ИмяБазы+"""");
Текст.ДобавитьСтроку("$АдминистраторИБ = 'СервисныйПользователь_АвтообновлениеКонфигурации'");
Текст.ДобавитьСтроку("$ПарольАдминистратораИБ = 'iddqd'");
Текст.ДобавитьСтроку("$ПараметрыБекап = '" + ПараметрыБекап + "'");
Текст.ДобавитьСтроку("$ПараметрыАпдейт = '" + ПараметрыАпдейт + "'");
Текст.ДобавитьСтроку("$ФайлВыгрузки = '" + ФайлВыгрузки + "'");
Текст.ДобавитьСтроку("$ФайлЛогов = '" + ФайлЛогов + "'");
Текст.ДобавитьСтроку("");
Текст.ДобавитьСтроку("(Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Скрипт запущен""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку("");
Текст.ДобавитьСтроку("$Коннектор = New-Object -COMObject ""V83.COMConnector""");
Текст.ДобавитьСтроку("(Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Создание СОМ-соединения с сервером""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку("");
Текст.ДобавитьСтроку("$Агент = $Коннектор.ConnectAgent($ИмяСервера)");
Текст.ДобавитьСтроку("(Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Подключение к серверу""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку("");
Текст.ДобавитьСтроку("$Кластеры = $Агент.GetClusters()");
Текст.ДобавитьСтроку("foreach ($Кластер in $Кластеры) {if ($ИмяКластера.ToUpper() -eq $Кластер.ClusterName.ToUpper()) {break}}");
Текст.ДобавитьСтроку("$Агент.Authenticate($Кластер, $АдминистраторКластера, $ПарольАдминистратораКластера)");
Текст.ДобавитьСтроку("(Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Аутентификация в кластере""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку("");
Текст.ДобавитьСтроку("$Процессы = $Агент.GetWorkingProcesses($Кластер)");
Текст.ДобавитьСтроку("Foreach ($Процесс in $Процессы)");
Текст.ДобавитьСтроку(" {");
Текст.ДобавитьСтроку(" $Порт = $Процесс.MainPort");
Текст.ДобавитьСтроку(" $РабПроц = $Коннектор.ConnectWorkingProcess($ИмяСервера + "":"" + $Порт)");
Текст.ДобавитьСтроку(" $РабПроц.AddAuthentication($АдминистраторИБ, $ПарольАдминистратораИБ)");
Текст.ДобавитьСтроку(" $Базы = $РабПроц.GetInfoBases()");
Текст.ДобавитьСтроку(" $БазаНайдена = $false");
Текст.ДобавитьСтроку(" Foreach ($База in $Базы) {if ($База.Name.ToUpper() -eq $ИмяБазы.ToUpper()) {$БазаНайдена = $true; break}}");
Текст.ДобавитьСтроку(" if ($БазаНайдена -eq $false) {continue}");
Текст.ДобавитьСтроку("");
Текст.ДобавитьСтроку("(Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Нашли базу""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку("");
Текст.ДобавитьСтроку(" $База.SessionsDenied = $True");
Текст.ДобавитьСтроку(" $ЗапускРегЗаданий = $База.ScheduledJobsDenied");
Текст.ДобавитьСтроку(" $База.ScheduledJobsDenied = $True");
Текст.ДобавитьСтроку(" $База.PermissionCode = ""iddqd""");
Текст.ДобавитьСтроку(" $РабПроц.UpdateInfoBase($База)");
Текст.ДобавитьСтроку("(Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Установили блокировки на базу""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку("");
Текст.ДобавитьСтроку("(Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Отключаем соединения с базой""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку(" $СоединенияБазы = $РабПроц.GetInfoBaseConnections($База) | Foreach {if ($_.AppID -ne ""COMConsole"") {$РабПроц.Disconnect($_)}}");
Текст.ДобавитьСтроку("(Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Отключили соединения с базой""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку("");
Текст.ДобавитьСтроку(" }");
Текст.ДобавитьСтроку("(Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Выполняем бекап базы""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку("$procid = (Start-Process $ИсполняемыйФайл -ArgumentList $ПараметрыБекап -Passthru).id");
Текст.ДобавитьСтроку("$countchild = 1");
Текст.ДобавитьСтроку("while ($countchild -ne 0)");
Текст.ДобавитьСтроку(" {");
Текст.ДобавитьСтроку(" $pr = Get-WmiObject Win32_Process -Filter ""ParentProcessId='$procid' or ProcessId='$procid'"" | measure");
Текст.ДобавитьСтроку(" $countchild = $pr.Count");
Текст.ДобавитьСтроку(" Start-Sleep 10");
Текст.ДобавитьСтроку(" }");
Текст.ДобавитьСтроку("(Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Выполнили бекап базы""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку("");
Текст.ДобавитьСтроку("Start-Sleep 10");
Текст.ДобавитьСтроку("$isfile = Test-Path $ФайлВыгрузки");
Текст.ДобавитьСтроку("if ($isfile -eq ""True"")");
Текст.ДобавитьСтроку(" {");
Текст.ДобавитьСтроку(" (Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Выполняем обновление конфигурации""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку(" Start-Process $ИсполняемыйФайл -ArgumentList $ПараметрыАпдейт");
Текст.ДобавитьСтроку(" (Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Выполнили обновление конфигурации""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку(" }");
Текст.ДобавитьСтроку("else");
Текст.ДобавитьСтроку(" {");
Текст.ДобавитьСтроку(" (Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Файл бекапа не найден. Обновление не выполнено""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку(" }");
Текст.ДобавитьСтроку("$Процессы = $Агент.GetWorkingProcesses($Кластер)");
Текст.ДобавитьСтроку("Foreach ($Процесс in $Процессы)");
Текст.ДобавитьСтроку(" {");
Текст.ДобавитьСтроку(" $Порт = $Процесс.MainPort");
Текст.ДобавитьСтроку(" $РабПроц = $Коннектор.ConnectWorkingProcess($ИмяСервера + "":"" + $Порт)");
Текст.ДобавитьСтроку(" $РабПроц.AddAuthentication($АдминистраторИБ, $ПарольАдминистратораИБ)");
Текст.ДобавитьСтроку(" $Базы = $РабПроц.GetInfoBases()");
Текст.ДобавитьСтроку(" $БазаНайдена = $false");
Текст.ДобавитьСтроку(" Foreach ($База in $Базы) {if ($База.Name.ToUpper() -eq $ИмяБазы.ToUpper()) {$БазаНайдена = $true; break}}");
Текст.ДобавитьСтроку(" if ($БазаНайдена -eq $false) {continue}");
Текст.ДобавитьСтроку("");
Текст.ДобавитьСтроку(" $База.SessionsDenied = $False");
Текст.ДобавитьСтроку(" $База.ScheduledJobsDenied = $ЗапускРегЗаданий");
Текст.ДобавитьСтроку(" $База.PermissionCode = """"");
Текст.ДобавитьСтроку(" $РабПроц.UpdateInfoBase($База)");
Текст.ДобавитьСтроку("(Get-Date -UFormat ""%d.%m.%Y %T"").ToString() + "" Сняли блокировки с базы""| Add-Content $ФайлЛогов");
Текст.ДобавитьСтроку(" }");
Текст.Записать(ФайлСкрипта);
КонецЕсли;
Текст = Неопределено;
WshShell.Run(PS+" -ExecutionPolicy RemoteSigned -File " + ФайлСкрипта,0,Ложь);
КонецПроцедуры