Как корректно закрыть Конфигуратор 1С через PowerShell перед сокращением журнала регистрации?

Системный администратор 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При автоматизации обслуживания информационных баз 1С системные администраторы часто сталкиваются с проблемой блокировки файлов. Одной из таких задач является сокращение журнала регистрации (метод ReduceEventLogSize). Если в момент запуска скрипта PowerShell открыт Конфигуратор, процедура завершится ошибкой, так как он монопольно удерживает файлы журнала, особенно если используется новый формат .lgd (SQLite). В этой статье мы подробно разберем, как реализовать «умное» закрытие Конфигуратора, которое учитывает наличие несохраненных изменений, чтобы не потерять работу программиста.

Анализ проблемы и выбор стратегии

Прежде чем приступать к написанию кода, проанализируем ситуацию. Нам нужно не просто «убить» процесс 1cv8.exe, а выполнить проверку: если в Конфигураторе открыт программный модуль или окно метаданных с изменениями, закрывать его нельзя. Рассмотрим основные критерии, которые помогут нам в автоматизации:

  1. Признак изменения данных: В платформе 1С:Предприятие принято визуальное обозначение модификации — символ «звездочка» (астериск *) в заголовке главного окна.
  2. Метод взаимодействия: Мы будем использовать объектную модель System.Diagnostics.Process в среде PowerShell для анализа заголовков и отправки команд на закрытие.
  3. Безопасное завершение: Вместо принудительного прерывания (Kill) мы используем стандартные сообщения Windows, которые инициируют штатный выход из программы.

Способ 1. Проверка заголовка окна на наличие несохраненных данных

Разберем, как с помощью 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С:Предприятие», хотя обычно в пользовательском режиме символ * в заголовке главного окна не появляется так часто, как в конфигурационной части.

Способ 2. Мягкое закрытие через CloseMainWindow

После того как мы убедились, что несохраненных данных нет, нам нужно попросить программу закрыться. Метод 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 секунд процесс не исчез из списка активных, значит, что-то мешает закрытию, и выполнение основной задачи (архивации или сокращения журнала) следует отменить.

Способ 3. Использование Taskkill без флага принуждения

Если вы предпочитаете использовать стандартные системные утилиты, можно воспользоваться командой taskkill. Однако здесь есть важный нюанс: никогда не используйте параметр /F, если ваша цель — безопасность данных. Без этого параметра утилита посылает сигнал завершения, который приложение может обработать или отклонить.

Выясним причину, по которой этот метод удобен: он позволяет фильтровать процессы по заголовку окна прямо в командной строке.


# Попытка мягкого закрытия всех окон Конфигуратора
taskkill /IM 1cv8.exe /FI "WINDOWTITLE eq *Конфигуратор*"
if ($LASTEXITCODE -ne 0) {
    Write-Host "Команда taskkill не смогла закрыть процесс или процесс не найден."
}

Тем не менее, этот метод менее информативен для PowerShell, чем работа с объектами процесса, так как сложнее программно определить, почему именно процесс не закрылся.

Особенности работы с журналами в разных форматах

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

  1. Старый формат (.lgf, .lgp): Журнал представляет собой текстовые файлы. В этом режиме блокируется только файл текущего периода (дня или часа). Теоретически, старые файлы можно перемещать или архивировать даже при открытом Конфигураторе, но штатная процедура сокращения все равно потребует отсутствия блокировок на всей структуре журнала.
  2. Новый формат (.lgd): Это база данных SQLite. Файл 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:

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

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

← На главную