При автоматизации обслуживания информационных баз 1С системные администраторы часто сталкиваются с проблемой блокировки файлов. Одной из таких задач является сокращение журнала регистрации (метод ReduceEventLogSize). Если в момент запуска скрипта PowerShell открыт Конфигуратор, процедура завершится ошибкой, так как он монопольно удерживает файлы журнала, особенно если используется новый формат .lgd (SQLite). В этой статье мы подробно разберем, как реализовать «умное» закрытие Конфигуратора, которое учитывает наличие несохраненных изменений, чтобы не потерять работу программиста.
Прежде чем приступать к написанию кода, проанализируем ситуацию. Нам нужно не просто «убить» процесс 1cv8.exe, а выполнить проверку: если в Конфигураторе открыт программный модуль или окно метаданных с изменениями, закрывать его нельзя. Рассмотрим основные критерии, которые помогут нам в автоматизации:
*) в заголовке главного окна.System.Diagnostics.Process в среде PowerShell для анализа заголовков и отправки команд на закрытие.Разберем, как с помощью PowerShell найти все запущенные экземпляры Конфигуратора и проверить их состояние. Это критически важный шаг, так как принудительное закрытие процесса с несохраненным кодом приведет к потере работы.
Проанализируем следующий алгоритм: мы перебираем все процессы с именем 1cv8, получаем их заголовки и ищем символ *. Если символ найден, мы выводим предупреждение и останавливаем работу скрипта обслуживания.
$processes = Get-Process -Name "1cv8" -ErrorAction SilentlyContinue
foreach ($proc in $processes) {
$windowTitle = $proc.MainWindowTitle
if ($windowTitle -like "*(Конфигуратор)*") {
if ($windowTitle.Contains("*")) {
Write-Host "Обнаружены несохраненные данные в окне: $windowTitle" -ForegroundColor Red
exit 1 # Прерываем скрипт, так как закрывать нельзя
}
else {
Write-Host "Конфигуратор '$windowTitle' готов к закрытию." -ForegroundColor Green
}
}
}
В данном примере мы используем свойство MainWindowTitle. Обратите внимание, что проверка должна быть точной, чтобы не спутать Конфигуратор с пользовательским режимом «1С:Предприятие», хотя обычно в пользовательском режиме символ * в заголовке главного окна не появляется так часто, как в конфигурационной части.
После того как мы убедились, что несохраненных данных нет, нам нужно попросить программу закрыться. Метод CloseMainWindow() отправляет главному окну сообщение WM_CLOSE. Это эквивалентно нажатию на крестик в углу окна или нажатию Alt+F4.
Рассмотрим подробнее преимущество этого метода: если программа все же решит, что ей есть что сказать пользователю (например, открыто модальное окно), она просто не закроется, и наш скрипт сможет это обработать по таймауту.
$proc = Get-Process -Name "1cv8" | Where-Object { $_.MainWindowTitle -like "*(Конфигуратор)*" }
if ($proc) {
$proc.CloseMainWindow() | Out-Null
# Ждем завершения процесса в течение 30 секунд
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
while ($proc.HasExited -eq $false -and $stopwatch.Elapsed.TotalSeconds -lt 30) {
Start-Sleep -Seconds 1
}
if ($proc.HasExited) {
Write-Host "Конфигуратор успешно закрыт."
} else {
Write-Host "Не удалось закрыть Конфигуратор штатно. Возможно, открыто диалоговое окно." -ForegroundColor Yellow
exit 1
}
}
Использование Stopwatch позволяет нам контролировать время ожидания. Если за 30 секунд процесс не исчез из списка активных, значит, что-то мешает закрытию, и выполнение основной задачи (архивации или сокращения журнала) следует отменить.
Если вы предпочитаете использовать стандартные системные утилиты, можно воспользоваться командой taskkill. Однако здесь есть важный нюанс: никогда не используйте параметр /F, если ваша цель — безопасность данных. Без этого параметра утилита посылает сигнал завершения, который приложение может обработать или отклонить.
Выясним причину, по которой этот метод удобен: он позволяет фильтровать процессы по заголовку окна прямо в командной строке.
# Попытка мягкого закрытия всех окон Конфигуратора
taskkill /IM 1cv8.exe /FI "WINDOWTITLE eq *Конфигуратор*"
if ($LASTEXITCODE -ne 0) {
Write-Host "Команда taskkill не смогла закрыть процесс или процесс не найден."
}
Тем не менее, этот метод менее информативен для PowerShell, чем работа с объектами процесса, так как сложнее программно определить, почему именно процесс не закрылся.
При планировании сокращения журнала регистрации через ReduceEventLogSize важно понимать, с каким типом файлов мы имеем дело. От этого зависит, насколько критично закрытие всех сессий 1С.
1Cv8.lgd блокируется практически любым процессом, который к нему обращается. Если открыт Конфигуратор, он держит дескриптор файла, и любая попытка сжатия или очистки через скрипт завершится неудачей с ошибкой доступа.Проверим, удерживается ли файл журнала конкретным процессом. Для этого в PowerShell можно использовать утилиту Handle от Sysinternals, если она установлена на сервере:
$logFile = "C:\1C_Bases\MyBase\1Cv8Log\1Cv8.lgd"
$handleOut = & handle.exe $logFile
if ($handleOut -match "1cv8.exe") {
Write-Host "Файл журнала заблокирован Конфигуратором!" -ForegroundColor Red
}
Подведем итог и составим оптимальный план действий для вашего скрипта PowerShell:
1cv8.exe. Если процессов нет — сразу переходим к обслуживанию.MainWindowTitle. Ищем символ *. Если он найден — пишем в лог ошибку и прекращаем работу (безопасность превыше всего).CloseMainWindow().COM-соединение или запуск 1С в режиме конфигуратора с соответствующими параметрами командной строки (например, /ReduceEventLogSize).В некоторых случаях, как было отмечено в обсуждении на форуме (сообщение 6), хорошей альтернативой является настройка хранения журнала по периодам. При такой настройке 1С сама разделяет файлы, и блокируется только самый свежий. Это позволяет автоматизировать архивацию старых фрагментов журнала без необходимости закрывать сеансы администраторов и прерывать их работу в Конфигураторе.
Для более продвинутой автоматизации также рекомендуем обратить внимание на OneScript. В его библиотеках существуют готовые обертки над административными функциями 1С, которые позволяют управлять сеансами более элегантно, чем через парсинг заголовков окон Windows.