Обновить MailBoxBackup_TB.ps1
This commit is contained in:
@@ -1,448 +1,448 @@
|
|||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Скрипт для закрытия Thunderbird и резервного копирования профиля
|
Скрипт для закрытия Thunderbird и резервного копирования профиля
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Выполняет поиск процессов Thunderbird, завершает их, ожидает полного закрытия
|
Выполняет поиск процессов Thunderbird, завершает их, ожидает полного закрытия
|
||||||
и создает копию папки профиля в указанное место. Автоматически создает папки назначения.
|
и создает копию папки профиля в указанное место. Автоматически создает папки назначения.
|
||||||
.NOTES
|
.NOTES
|
||||||
Author:
|
Author: RobinHood
|
||||||
Date: $(Get-Date -Format 'dd.MM.yyyy')
|
Date: $(Get-Date -Format 'dd.MM.yyyy')
|
||||||
#>
|
#>
|
||||||
|
|
||||||
# === НАСТРОЙКИ ===
|
# === НАСТРОЙКИ ===
|
||||||
$ThunderbirdProcessName = "thunderbird" # Имя процесса без .exe
|
$ThunderbirdProcessName = "thunderbird" # Имя процесса без .exe
|
||||||
$SourceProfilePath = "$env:APPDATA\Thunderbird\Profiles" # Стандартный путь к профилям
|
$SourceProfilePath = "$env:APPDATA\Thunderbird\Profiles" # Стандартный путь к профилям
|
||||||
|
|
||||||
# Настройка пути для резервной копии (папка создастся автоматически)
|
# Настройка пути для резервной копии (папка создастся автоматически)
|
||||||
$BackupRoot = "E:\Backups\Thunderbird" # Корневая папка для бэкапов
|
$BackupRoot = "E:\Backups\Thunderbird" # Корневая папка для бэкапов
|
||||||
$BackupDestination = Join-Path -Path $BackupRoot -ChildPath (Get-Date -Format 'yyyy-MM-dd') # Папка с датой
|
$BackupDestination = Join-Path -Path $BackupRoot -ChildPath (Get-Date -Format 'yyyy-MM-dd') # Папка с датой
|
||||||
|
|
||||||
$MaxWaitTimeSeconds = 30 # Максимальное время ожидания закрытия Thunderbird (в секундах)
|
$MaxWaitTimeSeconds = 30 # Максимальное время ожидания закрытия Thunderbird (в секундах)
|
||||||
$CopyRetryCount = 3 # Количество попыток копирования при ошибках
|
$CopyRetryCount = 3 # Количество попыток копирования при ошибках
|
||||||
$MinFreeSpaceMB = 500 # Минимальное свободное место на диске назначения (МБ)
|
$MinFreeSpaceMB = 500 # Минимальное свободное место на диске назначения (МБ)
|
||||||
# =================
|
# =================
|
||||||
|
|
||||||
# Функция для записи лога
|
# Функция для записи лога
|
||||||
function Write-Log {
|
function Write-Log {
|
||||||
param(
|
param(
|
||||||
[string]$Message,
|
[string]$Message,
|
||||||
[string]$Type = "INFO"
|
[string]$Type = "INFO"
|
||||||
)
|
)
|
||||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||||
|
|
||||||
# Цвета для разных типов сообщений
|
# Цвета для разных типов сообщений
|
||||||
switch ($Type) {
|
switch ($Type) {
|
||||||
"SUCCESS" { $color = "Green" }
|
"SUCCESS" { $color = "Green" }
|
||||||
"ERROR" { $color = "Red" }
|
"ERROR" { $color = "Red" }
|
||||||
"WARNING" { $color = "Yellow" }
|
"WARNING" { $color = "Yellow" }
|
||||||
"INFO" { $color = "Cyan" }
|
"INFO" { $color = "Cyan" }
|
||||||
default { $color = "White" }
|
default { $color = "White" }
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "[$timestamp] [$Type] " -NoNewline
|
Write-Host "[$timestamp] [$Type] " -NoNewline
|
||||||
Write-Host "$Message" -ForegroundColor $color
|
Write-Host "$Message" -ForegroundColor $color
|
||||||
}
|
}
|
||||||
|
|
||||||
# Функция для создания папки назначения
|
# Функция для создания папки назначения
|
||||||
function New-BackupFolder {
|
function New-BackupFolder {
|
||||||
param(
|
param(
|
||||||
[string]$FolderPath
|
[string]$FolderPath
|
||||||
)
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (-not (Test-Path $FolderPath)) {
|
if (-not (Test-Path $FolderPath)) {
|
||||||
Write-Log "Папка назначения не существует. Создание: $FolderPath" -Type "INFO"
|
Write-Log "Папка назначения не существует. Создание: $FolderPath" -Type "INFO"
|
||||||
|
|
||||||
# Создаем все папки в пути рекурсивно
|
# Создаем все папки в пути рекурсивно
|
||||||
New-Item -Path $FolderPath -ItemType Directory -Force | Out-Null
|
New-Item -Path $FolderPath -ItemType Directory -Force | Out-Null
|
||||||
|
|
||||||
Write-Log "Папка успешно создана" -Type "SUCCESS"
|
Write-Log "Папка успешно создана" -Type "SUCCESS"
|
||||||
} else {
|
} else {
|
||||||
Write-Log "Папка назначения уже существует: $FolderPath" -Type "INFO"
|
Write-Log "Папка назначения уже существует: $FolderPath" -Type "INFO"
|
||||||
}
|
}
|
||||||
|
|
||||||
return $true
|
return $true
|
||||||
} catch {
|
} catch {
|
||||||
Write-Log "ОШИБКА при создании папки назначения: $_" -Type "ERROR"
|
Write-Log "ОШИБКА при создании папки назначения: $_" -Type "ERROR"
|
||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Функция для проверки свободного места на диске
|
# Функция для проверки свободного места на диске
|
||||||
function Test-FreeSpace {
|
function Test-FreeSpace {
|
||||||
param(
|
param(
|
||||||
[string]$Path,
|
[string]$Path,
|
||||||
[long]$RequiredSpaceMB = 500
|
[long]$RequiredSpaceMB = 500
|
||||||
)
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
# Получаем корневой диск из пути
|
# Получаем корневой диск из пути
|
||||||
$rootPath = Split-Path -Path $Path -Qualifier
|
$rootPath = Split-Path -Path $Path -Qualifier
|
||||||
if ([string]::IsNullOrEmpty($rootPath)) {
|
if ([string]::IsNullOrEmpty($rootPath)) {
|
||||||
$rootPath = $Path[0] + ":"
|
$rootPath = $Path[0] + ":"
|
||||||
}
|
}
|
||||||
|
|
||||||
$drive = Get-PSDrive -Name $rootPath[0] -ErrorAction Stop
|
$drive = Get-PSDrive -Name $rootPath[0] -ErrorAction Stop
|
||||||
$freeSpaceMB = [math]::Round($drive.Free / 1MB, 2)
|
$freeSpaceMB = [math]::Round($drive.Free / 1MB, 2)
|
||||||
|
|
||||||
Write-Log "Свободное место на диске $rootPath : $freeSpaceMB MB" -Type "INFO"
|
Write-Log "Свободное место на диске $rootPath : $freeSpaceMB MB" -Type "INFO"
|
||||||
|
|
||||||
if ($drive.Free -lt ($RequiredSpaceMB * 1MB)) {
|
if ($drive.Free -lt ($RequiredSpaceMB * 1MB)) {
|
||||||
Write-Log "НЕДОСТАТОЧНО МЕСТА! Требуется: $RequiredSpaceMB MB, доступно: $freeSpaceMB MB" -Type "ERROR"
|
Write-Log "НЕДОСТАТОЧНО МЕСТА! Требуется: $RequiredSpaceMB MB, доступно: $freeSpaceMB MB" -Type "ERROR"
|
||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Log "Места достаточно: $freeSpaceMB MB свободно" -Type "SUCCESS"
|
Write-Log "Места достаточно: $freeSpaceMB MB свободно" -Type "SUCCESS"
|
||||||
return $true
|
return $true
|
||||||
} catch {
|
} catch {
|
||||||
Write-Log "Не удалось проверить свободное место: $_" -Type "WARNING"
|
Write-Log "Не удалось проверить свободное место: $_" -Type "WARNING"
|
||||||
return $true # Продолжаем, если не удалось проверить
|
return $true # Продолжаем, если не удалось проверить
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Функция для проверки, запущен ли Thunderbird
|
# Функция для проверки, запущен ли Thunderbird
|
||||||
function Test-ThunderbirdRunning {
|
function Test-ThunderbirdRunning {
|
||||||
$processes = Get-Process -Name $ThunderbirdProcessName -ErrorAction SilentlyContinue
|
$processes = Get-Process -Name $ThunderbirdProcessName -ErrorAction SilentlyContinue
|
||||||
return ($processes.Count -gt 0)
|
return ($processes.Count -gt 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
# Функция для закрытия Thunderbird
|
# Функция для закрытия Thunderbird
|
||||||
function Stop-ThunderbirdGracefully {
|
function Stop-ThunderbirdGracefully {
|
||||||
Write-Log "Поиск запущенных процессов Thunderbird..." -Type "INFO"
|
Write-Log "Поиск запущенных процессов Thunderbird..." -Type "INFO"
|
||||||
|
|
||||||
if (Test-ThunderbirdRunning) {
|
if (Test-ThunderbirdRunning) {
|
||||||
$processCount = (Get-Process -Name $ThunderbirdProcessName -ErrorAction SilentlyContinue).Count
|
$processCount = (Get-Process -Name $ThunderbirdProcessName -ErrorAction SilentlyContinue).Count
|
||||||
Write-Log "Найдено процессов Thunderbird: $processCount. Попытка корректного завершения..." -Type "WARNING"
|
Write-Log "Найдено процессов Thunderbird: $processCount. Попытка корректного завершения..." -Type "WARNING"
|
||||||
|
|
||||||
# Пытаемся закрыть окна Thunderbird (более мягкий способ)
|
# Пытаемся закрыть окна Thunderbird (более мягкий способ)
|
||||||
$thunderbirdWindows = Get-Process -Name $ThunderbirdProcessName | Where-Object { $_.MainWindowTitle -ne "" }
|
$thunderbirdWindows = Get-Process -Name $ThunderbirdProcessName | Where-Object { $_.MainWindowTitle -ne "" }
|
||||||
|
|
||||||
if ($thunderbirdWindows) {
|
if ($thunderbirdWindows) {
|
||||||
foreach ($proc in $thunderbirdWindows) {
|
foreach ($proc in $thunderbirdWindows) {
|
||||||
$windowTitle = if ($proc.MainWindowTitle) { $proc.MainWindowTitle } else { "Без заголовка" }
|
$windowTitle = if ($proc.MainWindowTitle) { $proc.MainWindowTitle } else { "Без заголовка" }
|
||||||
Write-Log "Закрытие окна: $windowTitle"
|
Write-Log "Закрытие окна: $windowTitle"
|
||||||
$proc.CloseMainWindow() | Out-Null
|
$proc.CloseMainWindow() | Out-Null
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Write-Log "Нет видимых окон Thunderbird, но процессы запущены" -Type "WARNING"
|
Write-Log "Нет видимых окон Thunderbird, но процессы запущены" -Type "WARNING"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Даем время на закрытие
|
# Даем время на закрытие
|
||||||
$waitCounter = 0
|
$waitCounter = 0
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
while ((Test-ThunderbirdRunning) -and ($waitCounter -lt $MaxWaitTimeSeconds)) {
|
while ((Test-ThunderbirdRunning) -and ($waitCounter -lt $MaxWaitTimeSeconds)) {
|
||||||
Start-Sleep -Seconds 1
|
Start-Sleep -Seconds 1
|
||||||
$waitCounter++
|
$waitCounter++
|
||||||
|
|
||||||
# Простой индикатор прогресса
|
# Простой индикатор прогресса
|
||||||
$progress = [math]::Round(($waitCounter / $MaxWaitTimeSeconds) * 100)
|
$progress = [math]::Round(($waitCounter / $MaxWaitTimeSeconds) * 100)
|
||||||
Write-Host "`rОжидание закрытия Thunderbird: $progress% " -NoNewline
|
Write-Host "`rОжидание закрытия Thunderbird: $progress% " -NoNewline
|
||||||
}
|
}
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
|
|
||||||
# Если всё ещё запущен - принудительно завершаем
|
# Если всё ещё запущен - принудительно завершаем
|
||||||
if (Test-ThunderbirdRunning) {
|
if (Test-ThunderbirdRunning) {
|
||||||
Write-Log "Thunderbird не закрылся за отведенное время. Принудительное завершение..." -Type "ERROR"
|
Write-Log "Thunderbird не закрылся за отведенное время. Принудительное завершение..." -Type "ERROR"
|
||||||
|
|
||||||
$remainingProcesses = Get-Process -Name $ThunderbirdProcessName -ErrorAction SilentlyContinue
|
$remainingProcesses = Get-Process -Name $ThunderbirdProcessName -ErrorAction SilentlyContinue
|
||||||
foreach ($proc in $remainingProcesses) {
|
foreach ($proc in $remainingProcesses) {
|
||||||
try {
|
try {
|
||||||
Stop-Process -Id $proc.Id -Force
|
Stop-Process -Id $proc.Id -Force
|
||||||
Write-Log "Процесс PID $($proc.Id) принудительно завершен" -Type "WARNING"
|
Write-Log "Процесс PID $($proc.Id) принудительно завершен" -Type "WARNING"
|
||||||
} catch {
|
} catch {
|
||||||
Write-Log "Не удалось завершить процесс PID $($proc.Id): $_" -Type "ERROR"
|
Write-Log "Не удалось завершить процесс PID $($proc.Id): $_" -Type "ERROR"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Start-Sleep -Seconds 3
|
Start-Sleep -Seconds 3
|
||||||
} else {
|
} else {
|
||||||
Write-Log "Thunderbird успешно закрыт" -Type "SUCCESS"
|
Write-Log "Thunderbird успешно закрыт" -Type "SUCCESS"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Write-Log "Thunderbird не запущен" -Type "INFO"
|
Write-Log "Thunderbird не запущен" -Type "INFO"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Финальная проверка
|
# Финальная проверка
|
||||||
if (Test-ThunderbirdRunning) {
|
if (Test-ThunderbirdRunning) {
|
||||||
Write-Log "ВНИМАНИЕ: Некоторые процессы Thunderbird всё еще запущены!" -Type "ERROR"
|
Write-Log "ВНИМАНИЕ: Некоторые процессы Thunderbird всё еще запущены!" -Type "ERROR"
|
||||||
|
|
||||||
# Показываем оставшиеся процессы
|
# Показываем оставшиеся процессы
|
||||||
Get-Process -Name $ThunderbirdProcessName -ErrorAction SilentlyContinue |
|
Get-Process -Name $ThunderbirdProcessName -ErrorAction SilentlyContinue |
|
||||||
ForEach-Object { Write-Log " - PID: $($_.Id), Запущен: $($_.StartTime)" -Type "ERROR" }
|
ForEach-Object { Write-Log " - PID: $($_.Id), Запущен: $($_.StartTime)" -Type "ERROR" }
|
||||||
|
|
||||||
Write-Log "Продолжаем копирование, но некоторые файлы могут быть заблокированы" -Type "WARNING"
|
Write-Log "Продолжаем копирование, но некоторые файлы могут быть заблокированы" -Type "WARNING"
|
||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
|
|
||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
|
|
||||||
# Функция для получения размера папки
|
# Функция для получения размера папки
|
||||||
function Get-FolderSize {
|
function Get-FolderSize {
|
||||||
param([string]$Path)
|
param([string]$Path)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (Test-Path $Path) {
|
if (Test-Path $Path) {
|
||||||
$size = (Get-ChildItem $Path -Recurse -ErrorAction SilentlyContinue |
|
$size = (Get-ChildItem $Path -Recurse -ErrorAction SilentlyContinue |
|
||||||
Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum
|
Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum
|
||||||
if ($size) {
|
if ($size) {
|
||||||
return [math]::Round($size / 1MB, 2)
|
return [math]::Round($size / 1MB, 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
# Игнорируем ошибки при подсчете размера
|
# Игнорируем ошибки при подсчете размера
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# Функция для копирования профиля
|
# Функция для копирования профиля
|
||||||
function Copy-ThunderbirdProfile {
|
function Copy-ThunderbirdProfile {
|
||||||
param(
|
param(
|
||||||
[string]$Source,
|
[string]$Source,
|
||||||
[string]$Destination
|
[string]$Destination
|
||||||
)
|
)
|
||||||
|
|
||||||
Write-Log "Начало копирования профиля..." -Type "INFO"
|
Write-Log "Начало копирования профиля..." -Type "INFO"
|
||||||
Write-Log " Источник: $Source" -Type "INFO"
|
Write-Log " Источник: $Source" -Type "INFO"
|
||||||
Write-Log " Назначение: $Destination" -Type "INFO"
|
Write-Log " Назначение: $Destination" -Type "INFO"
|
||||||
|
|
||||||
# Проверяем существование исходной папки
|
# Проверяем существование исходной папки
|
||||||
if (-not (Test-Path $Source)) {
|
if (-not (Test-Path $Source)) {
|
||||||
Write-Log "Папка профиля НЕ НАЙДЕНА: $Source" -Type "ERROR"
|
Write-Log "Папка профиля НЕ НАЙДЕНА: $Source" -Type "ERROR"
|
||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
|
|
||||||
# Получаем размер исходной папки
|
# Получаем размер исходной папки
|
||||||
$sourceSizeMB = Get-FolderSize -Path $Source
|
$sourceSizeMB = Get-FolderSize -Path $Source
|
||||||
Write-Log "Размер исходной папки: ~$sourceSizeMB MB" -Type "INFO"
|
Write-Log "Размер исходной папки: ~$sourceSizeMB MB" -Type "INFO"
|
||||||
|
|
||||||
# Проверяем свободное место
|
# Проверяем свободное место
|
||||||
$requiredSpace = [math]::Max($MinFreeSpaceMB, $sourceSizeMB + 100) # +100 МБ запас
|
$requiredSpace = [math]::Max($MinFreeSpaceMB, $sourceSizeMB + 100) # +100 МБ запас
|
||||||
if (-not (Test-FreeSpace -Path $Destination -RequiredSpaceMB $requiredSpace)) {
|
if (-not (Test-FreeSpace -Path $Destination -RequiredSpaceMB $requiredSpace)) {
|
||||||
Write-Log "Недостаточно места для копирования. Операция отменена." -Type "ERROR"
|
Write-Log "Недостаточно места для копирования. Операция отменена." -Type "ERROR"
|
||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
|
|
||||||
# СОЗДАЕМ ПАПКУ НАЗНАЧЕНИЯ (ключевое изменение!)
|
# СОЗДАЕМ ПАПКУ НАЗНАЧЕНИЯ (ключевое изменение!)
|
||||||
if (-not (New-BackupFolder -FolderPath $Destination)) {
|
if (-not (New-BackupFolder -FolderPath $Destination)) {
|
||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
|
|
||||||
# Получаем список всех профилей в папке Profiles
|
# Получаем список всех профилей в папке Profiles
|
||||||
$profiles = Get-ChildItem -Path $Source -Directory -ErrorAction SilentlyContinue
|
$profiles = Get-ChildItem -Path $Source -Directory -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
if ($profiles.Count -eq 0) {
|
if ($profiles.Count -eq 0) {
|
||||||
Write-Log "В папке Profiles не найдено профилей!" -Type "WARNING"
|
Write-Log "В папке Profiles не найдено профилей!" -Type "WARNING"
|
||||||
Write-Log "Проверяем наличие файлов напрямую..." -Type "INFO"
|
Write-Log "Проверяем наличие файлов напрямую..." -Type "INFO"
|
||||||
|
|
||||||
# Если нет подпапок, возможно копируем содержимое самой папки Profiles
|
# Если нет подпапок, возможно копируем содержимое самой папки Profiles
|
||||||
$files = Get-ChildItem -Path $Source -File
|
$files = Get-ChildItem -Path $Source -File
|
||||||
if ($files.Count -gt 0) {
|
if ($files.Count -gt 0) {
|
||||||
Write-Log "Найдены файлы в корне папки Profiles, копируем их" -Type "INFO"
|
Write-Log "Найдены файлы в корне папки Profiles, копируем их" -Type "INFO"
|
||||||
|
|
||||||
# Пытаемся скопировать содержимое папки Profiles
|
# Пытаемся скопировать содержимое папки Profiles
|
||||||
$robocopyArgs = @(
|
$robocopyArgs = @(
|
||||||
"`"$Source`"",
|
"`"$Source`"",
|
||||||
"`"$Destination`"",
|
"`"$Destination`"",
|
||||||
"/E", # Копировать подпапки, включая пустые
|
"/E", # Копировать подпапки, включая пустые
|
||||||
"/COPY:DAT", # Копировать данные, атрибуты, временные метки
|
"/COPY:DAT", # Копировать данные, атрибуты, временные метки
|
||||||
"/R:3", # Retry count
|
"/R:3", # Retry count
|
||||||
"/W:5", # Wait time
|
"/W:5", # Wait time
|
||||||
"/NP", # No Progress
|
"/NP", # No Progress
|
||||||
"/NJH", # No Job Header
|
"/NJH", # No Job Header
|
||||||
"/NJS" # No Job Summary
|
"/NJS" # No Job Summary
|
||||||
)
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$robocopyResult = Start-Process -FilePath "robocopy.exe" -ArgumentList $robocopyArgs -Wait -PassThru -NoNewWindow
|
$robocopyResult = Start-Process -FilePath "robocopy.exe" -ArgumentList $robocopyArgs -Wait -PassThru -NoNewWindow
|
||||||
|
|
||||||
if ($robocopyResult.ExitCode -ge 8) {
|
if ($robocopyResult.ExitCode -ge 8) {
|
||||||
throw "Robocopy завершился с ошибкой. Код: $($robocopyResult.ExitCode)"
|
throw "Robocopy завершился с ошибкой. Код: $($robocopyResult.ExitCode)"
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Log "Файлы скопированы" -Type "SUCCESS"
|
Write-Log "Файлы скопированы" -Type "SUCCESS"
|
||||||
return $true
|
return $true
|
||||||
|
|
||||||
} catch {
|
} catch {
|
||||||
Write-Log "Ошибка при копировании: $_" -Type "ERROR"
|
Write-Log "Ошибка при копировании: $_" -Type "ERROR"
|
||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Write-Log "Папка Profiles пуста" -Type "WARNING"
|
Write-Log "Папка Profiles пуста" -Type "WARNING"
|
||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Копируем каждый профиль с повторами при ошибках
|
# Копируем каждый профиль с повторами при ошибках
|
||||||
$attempt = 1
|
$attempt = 1
|
||||||
$allCopied = $false
|
$allCopied = $false
|
||||||
|
|
||||||
while ($attempt -le $CopyRetryCount -and -not $allCopied) {
|
while ($attempt -le $CopyRetryCount -and -not $allCopied) {
|
||||||
try {
|
try {
|
||||||
Write-Log "Попытка копирования #$attempt из $CopyRetryCount..."
|
Write-Log "Попытка копирования #$attempt из $CopyRetryCount..."
|
||||||
|
|
||||||
$successCount = 0
|
$successCount = 0
|
||||||
$failCount = 0
|
$failCount = 0
|
||||||
|
|
||||||
foreach ($profile in $profiles) {
|
foreach ($profile in $profiles) {
|
||||||
$profileName = $profile.Name
|
$profileName = $profile.Name
|
||||||
$sourceProfilePath = $profile.FullName
|
$sourceProfilePath = $profile.FullName
|
||||||
$destProfilePath = Join-Path -Path $Destination -ChildPath $profileName
|
$destProfilePath = Join-Path -Path $Destination -ChildPath $profileName
|
||||||
|
|
||||||
Write-Log " Копирование профиля: $profileName"
|
Write-Log " Копирование профиля: $profileName"
|
||||||
|
|
||||||
# Используем Robocopy для надежного копирования
|
# Используем Robocopy для надежного копирования
|
||||||
$robocopyArgs = @(
|
$robocopyArgs = @(
|
||||||
"`"$sourceProfilePath`"",
|
"`"$sourceProfilePath`"",
|
||||||
"`"$destProfilePath`"",
|
"`"$destProfilePath`"",
|
||||||
"/MIR", # Mirror (точная копия)
|
"/MIR", # Mirror (точная копия)
|
||||||
"/R:3", # Retry count (3 повтора при ошибке)
|
"/R:3", # Retry count (3 повтора при ошибке)
|
||||||
"/W:5", # Wait time between retries (5 сек)
|
"/W:5", # Wait time between retries (5 сек)
|
||||||
"/NP", # No Progress (чтобы не засорять вывод)
|
"/NP", # No Progress (чтобы не засорять вывод)
|
||||||
"/NJH", # No Job Header
|
"/NJH", # No Job Header
|
||||||
"/NJS" # No Job Summary
|
"/NJS" # No Job Summary
|
||||||
)
|
)
|
||||||
|
|
||||||
Write-Log " Команда: robocopy $sourceProfilePath $destProfilePath /MIR /R:3 /W:5" -Type "INFO"
|
Write-Log " Команда: robocopy $sourceProfilePath $destProfilePath /MIR /R:3 /W:5" -Type "INFO"
|
||||||
|
|
||||||
$robocopyResult = Start-Process -FilePath "robocopy.exe" -ArgumentList $robocopyArgs -Wait -PassThru -NoNewWindow
|
$robocopyResult = Start-Process -FilePath "robocopy.exe" -ArgumentList $robocopyArgs -Wait -PassThru -NoNewWindow
|
||||||
|
|
||||||
# Robocopy возвращает коды: 0-7 - успех, 8+ - ошибка
|
# Robocopy возвращает коды: 0-7 - успех, 8+ - ошибка
|
||||||
if ($robocopyResult.ExitCode -ge 8) {
|
if ($robocopyResult.ExitCode -ge 8) {
|
||||||
Write-Log " Robocopy завершился с ошибкой. Код: $($robocopyResult.ExitCode)" -Type "ERROR"
|
Write-Log " Robocopy завершился с ошибкой. Код: $($robocopyResult.ExitCode)" -Type "ERROR"
|
||||||
$failCount++
|
$failCount++
|
||||||
} else {
|
} else {
|
||||||
Write-Log " Профиль $profileName скопирован (код: $($robocopyResult.ExitCode))" -Type "SUCCESS"
|
Write-Log " Профиль $profileName скопирован (код: $($robocopyResult.ExitCode))" -Type "SUCCESS"
|
||||||
$successCount++
|
$successCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($failCount -eq 0) {
|
if ($failCount -eq 0) {
|
||||||
$allCopied = $true
|
$allCopied = $true
|
||||||
Write-Log "Все профили успешно скопированы! ($successCount профилей)" -Type "SUCCESS"
|
Write-Log "Все профили успешно скопированы! ($successCount профилей)" -Type "SUCCESS"
|
||||||
} else {
|
} else {
|
||||||
Write-Log "Скопировано: $successCount, Ошибок: $failCount" -Type "WARNING"
|
Write-Log "Скопировано: $successCount, Ошибок: $failCount" -Type "WARNING"
|
||||||
|
|
||||||
if ($attempt -lt $CopyRetryCount) {
|
if ($attempt -lt $CopyRetryCount) {
|
||||||
Write-Log "Повторная попытка через 5 секунд..." -Type "INFO"
|
Write-Log "Повторная попытка через 5 секунд..." -Type "INFO"
|
||||||
Start-Sleep -Seconds 5
|
Start-Sleep -Seconds 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch {
|
} catch {
|
||||||
Write-Log "Ошибка при копировании (попытка $attempt): $_" -Type "ERROR"
|
Write-Log "Ошибка при копировании (попытка $attempt): $_" -Type "ERROR"
|
||||||
$failCount = $profiles.Count
|
$failCount = $profiles.Count
|
||||||
}
|
}
|
||||||
|
|
||||||
$attempt++
|
$attempt++
|
||||||
}
|
}
|
||||||
|
|
||||||
return ($allCopied -or ($successCount -gt 0))
|
return ($allCopied -or ($successCount -gt 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
# Функция для создания информационного файла о бэкапе
|
# Функция для создания информационного файла о бэкапе
|
||||||
function New-BackupInfoFile {
|
function New-BackupInfoFile {
|
||||||
param(
|
param(
|
||||||
[string]$BackupPath,
|
[string]$BackupPath,
|
||||||
[string]$SourcePath
|
[string]$SourcePath
|
||||||
)
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$infoFile = Join-Path -Path $BackupPath -ChildPath "_backup_info.txt"
|
$infoFile = Join-Path -Path $BackupPath -ChildPath "_backup_info.txt"
|
||||||
|
|
||||||
$computerInfo = @(
|
$computerInfo = @(
|
||||||
"# Информация о резервной копии Thunderbird",
|
"# Информация о резервной копии Thunderbird",
|
||||||
"Дата создания: $(Get-Date -Format 'dd.MM.yyyy HH:mm:ss')",
|
"Дата создания: $(Get-Date -Format 'dd.MM.yyyy HH:mm:ss')",
|
||||||
"Компьютер: $env:COMPUTERNAME",
|
"Компьютер: $env:COMPUTERNAME",
|
||||||
"Пользователь: $env:USERNAME",
|
"Пользователь: $env:USERNAME",
|
||||||
"Исходная папка: $SourcePath",
|
"Исходная папка: $SourcePath",
|
||||||
"Размер исходной папки: $(Get-FolderSize -Path $SourcePath) MB",
|
"Размер исходной папки: $(Get-FolderSize -Path $SourcePath) MB",
|
||||||
"---",
|
"---",
|
||||||
"Создано скриптом: $($MyInvocation.MyCommand.Path)"
|
"Создано скриптом: $($MyInvocation.MyCommand.Path)"
|
||||||
)
|
)
|
||||||
|
|
||||||
$computerInfo | Out-File -FilePath $infoFile -Encoding UTF8
|
$computerInfo | Out-File -FilePath $infoFile -Encoding UTF8
|
||||||
Write-Log "Создан информационный файл: _backup_info.txt" -Type "INFO"
|
Write-Log "Создан информационный файл: _backup_info.txt" -Type "INFO"
|
||||||
|
|
||||||
} catch {
|
} catch {
|
||||||
Write-Log "Не удалось создать информационный файл: $_" -Type "WARNING"
|
Write-Log "Не удалось создать информационный файл: $_" -Type "WARNING"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# === ОСНОВНАЯ ЧАСТЬ СКРИПТА ===
|
# === ОСНОВНАЯ ЧАСТЬ СКРИПТА ===
|
||||||
|
|
||||||
Clear-Host
|
Clear-Host
|
||||||
Write-Log "===================================================" -Type "INFO"
|
Write-Log "===================================================" -Type "INFO"
|
||||||
Write-Log " РЕЗЕРВНОЕ КОПИРОВАНИЕ ПРОФИЛЯ THUNDERBIRD" -Type "INFO"
|
Write-Log " РЕЗЕРВНОЕ КОПИРОВАНИЕ ПРОФИЛЯ THUNDERBIRD" -Type "INFO"
|
||||||
Write-Log "===================================================" -Type "INFO"
|
Write-Log "===================================================" -Type "INFO"
|
||||||
Write-Log ""
|
Write-Log ""
|
||||||
|
|
||||||
# 1. Проверяем и создаем корневую папку для бэкапов, если нужно
|
# 1. Проверяем и создаем корневую папку для бэкапов, если нужно
|
||||||
Write-Log "Проверка корневой папки для бэкапов: $BackupRoot" -Type "INFO"
|
Write-Log "Проверка корневой папки для бэкапов: $BackupRoot" -Type "INFO"
|
||||||
New-BackupFolder -FolderPath $BackupRoot | Out-Null
|
New-BackupFolder -FolderPath $BackupRoot | Out-Null
|
||||||
Write-Log ""
|
Write-Log ""
|
||||||
|
|
||||||
# 2. Проверяем наличие исходной папки
|
# 2. Проверяем наличие исходной папки
|
||||||
if (-not (Test-Path $SourceProfilePath)) {
|
if (-not (Test-Path $SourceProfilePath)) {
|
||||||
Write-Log "Исходная папка не найдена: $SourceProfilePath" -Type "ERROR"
|
Write-Log "Исходная папка не найдена: $SourceProfilePath" -Type "ERROR"
|
||||||
Write-Log "Проверьте путь и права доступа" -Type "INFO"
|
Write-Log "Проверьте путь и права доступа" -Type "INFO"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# 3. Закрываем Thunderbird
|
# 3. Закрываем Thunderbird
|
||||||
Write-Log "Этап 1: Закрытие Thunderbird" -Type "INFO"
|
Write-Log "Этап 1: Закрытие Thunderbird" -Type "INFO"
|
||||||
Write-Log "------------------------------" -Type "INFO"
|
Write-Log "------------------------------" -Type "INFO"
|
||||||
$closed = Stop-ThunderbirdGracefully
|
$closed = Stop-ThunderbirdGracefully
|
||||||
Write-Log ""
|
Write-Log ""
|
||||||
|
|
||||||
# 4. Небольшая пауза для гарантии
|
# 4. Небольшая пауза для гарантии
|
||||||
Start-Sleep -Seconds 2
|
Start-Sleep -Seconds 2
|
||||||
|
|
||||||
# 5. Копируем профили
|
# 5. Копируем профили
|
||||||
Write-Log "Этап 2: Копирование профилей" -Type "INFO"
|
Write-Log "Этап 2: Копирование профилей" -Type "INFO"
|
||||||
Write-Log "-----------------------------" -Type "INFO"
|
Write-Log "-----------------------------" -Type "INFO"
|
||||||
$copySuccess = Copy-ThunderbirdProfile -Source $SourceProfilePath -Destination $BackupDestination
|
$copySuccess = Copy-ThunderbirdProfile -Source $SourceProfilePath -Destination $BackupDestination
|
||||||
Write-Log ""
|
Write-Log ""
|
||||||
|
|
||||||
# 6. Создаем информационный файл (если копирование успешно)
|
# 6. Создаем информационный файл (если копирование успешно)
|
||||||
if ($copySuccess) {
|
if ($copySuccess) {
|
||||||
New-BackupInfoFile -BackupPath $BackupDestination -SourcePath $SourceProfilePath
|
New-BackupInfoFile -BackupPath $BackupDestination -SourcePath $SourceProfilePath
|
||||||
|
|
||||||
# 7. Итог
|
# 7. Итог
|
||||||
Write-Log "===================================================" -Type "SUCCESS"
|
Write-Log "===================================================" -Type "SUCCESS"
|
||||||
Write-Log " РЕЗЕРВНОЕ КОПИРОВАНИЕ УСПЕШНО ЗАВЕРШЕНО" -Type "SUCCESS"
|
Write-Log " РЕЗЕРВНОЕ КОПИРОВАНИЕ УСПЕШНО ЗАВЕРШЕНО" -Type "SUCCESS"
|
||||||
Write-Log "===================================================" -Type "SUCCESS"
|
Write-Log "===================================================" -Type "SUCCESS"
|
||||||
Write-Log "Папка с резервной копией: $BackupDestination" -Type "INFO"
|
Write-Log "Папка с резервной копией: $BackupDestination" -Type "INFO"
|
||||||
|
|
||||||
# Показываем содержимое папки с бэкапом
|
# Показываем содержимое папки с бэкапом
|
||||||
if (Test-Path $BackupDestination) {
|
if (Test-Path $BackupDestination) {
|
||||||
$items = Get-ChildItem -Path $BackupDestination
|
$items = Get-ChildItem -Path $BackupDestination
|
||||||
Write-Log "Содержимое папки с бэкапом:" -Type "INFO"
|
Write-Log "Содержимое папки с бэкапом:" -Type "INFO"
|
||||||
foreach ($item in $items) {
|
foreach ($item in $items) {
|
||||||
$itemSize = if ($item.PSIsContainer) {
|
$itemSize = if ($item.PSIsContainer) {
|
||||||
"<папка>"
|
"<папка>"
|
||||||
} else {
|
} else {
|
||||||
"$([math]::Round($item.Length / 1KB, 2)) KB"
|
"$([math]::Round($item.Length / 1KB, 2)) KB"
|
||||||
}
|
}
|
||||||
Write-Log " - $($item.Name) ($itemSize)" -Type "INFO"
|
Write-Log " - $($item.Name) ($itemSize)" -Type "INFO"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Предложение открыть папку
|
# Предложение открыть папку
|
||||||
$openFolder = Read-Host "`nОткрыть папку с резервной копией? (Y/N)"
|
$openFolder = Read-Host "`nОткрыть папку с резервной копией? (Y/N)"
|
||||||
if ($openFolder -eq "Y" -or $openFolder -eq "y") {
|
if ($openFolder -eq "Y" -or $openFolder -eq "y") {
|
||||||
Invoke-Item $BackupDestination
|
Invoke-Item $BackupDestination
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Write-Log "===================================================" -Type "ERROR"
|
Write-Log "===================================================" -Type "ERROR"
|
||||||
Write-Log " РЕЗЕРВНОЕ КОПИРОВАНИЕ ЗАВЕРШИЛОСЬ С ОШИБКАМИ" -Type "ERROR"
|
Write-Log " РЕЗЕРВНОЕ КОПИРОВАНИЕ ЗАВЕРШИЛОСЬ С ОШИБКАМИ" -Type "ERROR"
|
||||||
Write-Log "===================================================" -Type "ERROR"
|
Write-Log "===================================================" -Type "ERROR"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Для запуска с параметрами командной строки (раскомментируйте если нужно):
|
# Для запуска с параметрами командной строки (раскомментируйте если нужно):
|
||||||
# param(
|
# param(
|
||||||
# [string]$BackupPath = "D:\Backups\Thunderbird\$(Get-Date -Format 'yyyy-MM-dd')"
|
# [string]$BackupPath = "D:\Backups\Thunderbird\$(Get-Date -Format 'yyyy-MM-dd')"
|
||||||
# )
|
# )
|
||||||
# $BackupDestination = $BackupPath
|
# $BackupDestination = $BackupPath
|
||||||
Reference in New Issue
Block a user