cmdlets/Clear-Cache1C.ps1

. $PSScriptRoot\CommonUtils.ps1
. $PSScriptRoot\Parse-iBases.ps1

$global:MaxSizeCache   = 1MB*100 # выделять цветом папки с кэшом превышающий MaxSizeCache
$global:MaxLengthName  = 45
$global:MaxLengthSize  = 13
$global:TotalCacheSize = 0

#----------------------------------------------------------------------------------------
# Очищает кэш 1С
function Clear-Cache1C
{
<#
    .SYNOPSIS
        Очищает кэш платформы 1С.
    .DESCRIPTION
        Выводит пронумерованный список баз с размером кэша для каждой базы
        и дожидается выбора баз для очистки кэша.
        По умолчанию очищается только каталог кэша метаданных.
        Для ОС Windows C:\Users\NameUser\AppData\Local\1C\1Cv8.
        Параметр UserSettings позволяет очистить каталог кэша настроек пользователя.
        Для ОС Windows C:\Users\NameUser\AppData\Roaming\1C\1Cv8.
    .PARAMETER UserSettings
        Очистить кэш настроек пользователя.
        Псевдоним: us
    .PARAMETER Force
        Очистить кэш у всех баз не спрашивая.
    .PARAMETER Wait
        После выполнения дождаться нажатия любой клавиши.
#>

[CmdletBinding()]
param(
    [Alias("us")][switch]$UserSettings, # работать с каталогом пользовательских настроек
    [switch]$Force, # True = очистить кэш метаданных у всех баз не спрашивая
    [switch]$Wait
)
    $DirCache1C = Get-DirectoryCache1C -UserSettings:$UserSettings
    $iBases = Get-ListBase $DirCache1C -UserSettings:$UserSettings -Force:$Force

    if ($Force){
        # удалить кэш баз
        Remove-Cache1C $DirCache1C $UserSettings $iBases
    } else {
        # показать меню и дождаться выбора пользователя
        $Menu =
        "`n[1,2,3] - для очистки кэша укажите номера баз (Пустая строка = Все номера) `n"+
        "[любой символ не цифра] - завершить работу`n"+
        "Ваш выбор"
        [System.String]$InputUser = Read-Host $Menu
        if ($InputUser -eq '') {
            Remove-Cache1C $DirCache1C $UserSettings $iBases
        } elseif($InputUser -match '\d+') {
            $Indexes = Get-Indexes $InputUser
            if ($Indexes.Length -gt 0) {
                Remove-Cache1C $DirCache1C $UserSettings $iBases $Indexes
            }
        }
    }# if ($Force)
    if ($Wait) { Wait-PressAnyKey }
}# end of Clear-Cache1C

#----------------------------------------------------------------------------------------
# Функция каталог кэша 1С
function Get-DirectoryCache1C
{
<#
    .SYNOPSIS
        Возвращает каталог хранения кэша платформы 1С.
    .DESCRIPTION
        По умолчанию возвращает каталог хранения кэша метаданных.
        Если задан параметр UserSettings, то возвращает каталог хранения кэша настроек пользователя.
        Если в каталоге кэша обнаружен файл location.cfg,
        то каталог хранения будет прочитан из файла (параметр location).
        По умолчанию для ОС Windows платформы 1С версии 8.3 кэш хранится в каталогах:
         - кэш метаданных в C:\Users\NameUser\AppData\Local\1C\1Cv8
         - кэш настроек пользователя в C:\Users\NameUser\AppData\Roaming\1C\1Cv8
    .PARAMETER UserSettings
        Вернуть каталог кэша настроек пользователя.
        Псевдоним: us
#>

[CmdletBinding()]
param(
    [Alias("us")][switch]$UserSettings # работать с каталогом пользовательских настроек
)
    $ChacheDir = $env:LOCALAPPDATA + '\1C\1cv8'
    if ($UserSettings){$ChacheDir = $env:APPDATA + '\1C\1cv8'}
    if (Test-Path "$ChacheDir\location.cfg"){
        switch -Regex -File "$ChacheDir\location.cfg" {
            "^location=(.*)$" {
                Write-Verbose ("location = '{0}'" -f $matches[1])
                $ChacheDir = $matches[1]
            }
        }
    }
    $ChacheDir
}# end Get-DirectoryCache1C

#----------------------------------------------------------------------------------------
# Функция получает и выводит список баз и размер кэша каждой базы
function Get-ListBase
{
[CmdletBinding()]
param(
    [string]$DirCache1C, # каталог хранения кэша
    [Alias("us")][switch]$UserSettings, # работать с каталогом пользовательских настроек
    [switch]$Force # True = очистить кэш метаданных у всех баз не спрашивая
)
    $NameDirCache1C = "`nОчистка кэша метаданных: $DirCache1C`n"
    $NameTotalSize = "Суммарный размер кэша метаданных"
    if ($UserSettings){
        $NameDirCache1C = "`nОчистка кэша настроек пользователя: $DirCache1C`n"
        $NameTotalSize = "Суммарный размер кэша настроек пользователя"
    }
    Write-Host $NameDirCache1C
    $global:TotalCacheSize = 0
    $iBases = @()
    $i = 0
    Parse-iBases | foreach{
        $DirCacheBase = "{0}\{1}" -f $DirCache1C, $_.ID
        $CacheSize = 0
        if(Test-Path -path $DirCacheBase) {
            $CacheSize = (dir $DirCacheBase -recurse -Force | measure -Property Length -Sum).Sum
        }
        if ([Math]::Floor($CacheSize/1mb) -gt 0){
            $global:TotalCacheSize +=$CacheSize
            $_['Cache'] = $DirCacheBase
            $_['CacheSize'] = $CacheSize
            $iBases += $_
            if (!$Force){
                $msg = Get-Message $_['Name'] $CacheSize ($i+=1)
                if($CacheSize -ge $global:MaxSizeCache){
                    Write-Host $msg -ForegroundColor Yellow # покрасить строку базы
                } else {
                    Write-Host $msg # вывести без окраски
                }
            }# end if (!$Force)
        }# if ($CacheSize -gt 0)
    }
    if (!$Force){
        Write-Host (Get-Message $NameTotalSize $global:TotalCacheSize " ") -ForegroundColor White
    }
    $iBases    
}# end Get-ListBase

#----------------------------------------------------------------------------------------
# Получает массив индексов из строки заданной пользователем
function Get-Indexes($TextNumbers)
{
    $Indexes = @()
    $Numbers = $TextNumbers -Replace "[\D]","," -split ","
    foreach($Number in $Numbers) {
        if ($Number.Trim() -ne '') { $Indexes += [Convert]::ToInt32($Number.Trim())-1 }
    }
    $Indexes
}# end Get-Indexes

#----------------------------------------------------------------------------------------
# Удаляет каталоги кэша баз данных
function Remove-Cache1C($DirCache1C, $UserSettings, $Bases, $Indexes = $null)
{
    Write-Verbose "DebugPreference = $DebugPreference"
    $msg = "`nОчистка кэша метаданных: $DirCache1C"
    if ($UserSettings){$msg = "`nОчистка кэша настроек пользователя: $DirCache1C"}
    Write-Host $msg -ForegroundColor White

    $TotalDelete = 0
    if ($Indexes -eq $null){
        foreach($Base in $Bases){ $TotalDelete = $TotalDelete + (Remove-CacheBase $Base) }
    } else {
        foreach($Index in $Indexes){ 
            if ($Index -lt $Base.Length){ $TotalDelete = $TotalDelete + (Remove-CacheBase $Bases[$Index]) }
        }
    }
    Write-Host (Get-Message "Всего удалено:" $TotalDelete) -ForegroundColor White
    if ($Indexes -ne $null){
        Write-Host (Get-Message "Осталось:" ($global:TotalCacheSize - $TotalDelete)) -ForegroundColor White
    }
}# end Remove-Cache1C

#----------------------------------------------------------------------------------------
# Удаляет каталоги кэша переданной базы данных
function Remove-CacheBase($iBase)
{
    $CachseSize = 0
    try{
        If ($DebugPreference -eq 'SilentlyContinue') {
            Remove-Item $iBase['Cache'] -Recurse
            $CachseSize = $iBase['CacheSize']
        }
        Write-Host (Get-Message $iBase['Name'] $CachseSize) -ForegroundColor Yellow

    } catch [System.Exception] {
        # НЕ РАБОТАЕТ если файл заблокирован другим процессом!!!
        Write-Warning 'При удалении возникла ошибка. Возможно кэш заблокирован другим процессом или не существует.'
    }
    $CachseSize # вернем размер удаленного
}# end Remove-CacheBase

#----------------------------------------------------------------------------------------
# Получает строку сообщения с заданными параметрами
function Get-Message($Name, $Size, $Number = $null)
{
    if ($Number -eq $null) {
        $msg = "{0}.{1} MB" -f 
                $Name.PadRight($global:MaxLengthName + 1,'.'), 
                ("{0:n0}" -f ($Size/1mb)).PadLeft($global:MaxLengthSize,'.')
    } else {
        $msg = "{0} {1}.{2} MB" -f 
                $Number.ToString().PadRight(2,' '), 
                $Name.PadRight($global:MaxLengthName + 1,'.'), 
                ("{0:n0}" -f ($Size/1mb)).PadLeft($global:MaxLengthSize,'.')
    }
    $msg
}# end Get-Message