Загрузка данных
ftp.ps1
# ============================================================
# ftp.ps1 — скачивание архивов с FTP и запуск downloader.ps1
# ============================================================
# Логика:
# 1. Проверяем версии папок на FTP (маркер версии = имя папки).
# 2. Скачиваем RAR-архивы из EKP только для изменившихся версий.
# 3. Сохраняем архивы во временную локальную папку.
# 4. Вызываем downloader.ps1 — он устанавливает MSI,
# архивирует установленные папки и кладёт результат на Z:\Documents.
# 5. Удаляем локальные архивы после успешной обработки.
# ============================================================
# --- Настройки FTP ---
$ftpHost = "n5001-fap.dpc.tax.nalog.ru"
$ftpPath = "/AisNalog3"
$ftpUser = "anonymous"
$ftpPassword = ""
# --- Временная локальная папка (только для скачивания) ---
$localBasePath = "C:\Users\n4200-01-031\Desktop\App"
# --- Сетевая папка (куда downloader кладёт готовые архивы) ---
$networkBasePath = "Z:\Documents"
# --- Соответствие удалённых папок локальным ---
$folderMapping = @{
"AisNalog3_PROM" = "KPE"
"AisNalog3_PPK" = "PPK"
"OE" = "KOE"
"OE_IZ" = "KOEIZ"
}
# --- Шаблон имени файла-маркера версии ---
$versionPattern = '^\d+_\d+_\d+_\d+$'
# --- Путь к downloader.ps1 (рядом с этим скриптом) ---
$scriptDir = if ($PSScriptRoot) { $PSScriptRoot } else { Split-Path -Parent $PSCommandPath }
$downloader = Join-Path $scriptDir "downloader.ps1"
# --- Параметры скорости ---
$BufferSize = 16MB
$ProgressEveryMs = 300
$ShowSpeed = $true
# ============================================================
# Вспомогательные функции
# ============================================================
function Show-ProgressLine {
param(
[string]$FileName,
[int64]$Downloaded,
[int64]$Total,
[int]$Width = 30
)
if ($Total -gt 0) {
$percent = [math]::Floor(($Downloaded / $Total) * 100)
if ($percent -gt 100) { $percent = 100 }
$mbNow = [math]::Round($Downloaded / 1MB, 1)
$mbTotal = [math]::Round($Total / 1MB, 1)
$filled = [math]::Floor($Width * $percent / 100)
if ($filled -gt $Width) { $filled = $Width }
$empty = $Width - $filled
$bar = ("*" * $filled) + ("." * $empty)
Write-Host ("`r {0} : [{1}] {2}% {3}/{4} MB" -f $FileName, $bar, $percent, $mbNow, $mbTotal) -NoNewline -ForegroundColor Cyan
}
else {
$mbNow = [math]::Round($Downloaded / 1MB, 1)
Write-Host ("`r {0} : {1} MB" -f $FileName, $mbNow) -NoNewline -ForegroundColor Cyan
}
}
function Get-FtpFoldersWithDates {
param([string]$ftpPath)
$folders = @{}
try {
$uri = "ftp://$ftpHost$ftpPath/"
$request = [System.Net.FtpWebRequest]::Create($uri)
$request.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectoryDetails
$request.Credentials = New-Object System.Net.NetworkCredential($ftpUser, $ftpPassword)
$request.UseBinary = $true
$request.UsePassive = $true
$request.EnableSsl = $false
$request.KeepAlive = $false
$request.Timeout = 30000
$response = $request.GetResponse()
$stream = $response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($stream)
$listing = $reader.ReadToEnd()
$reader.Close(); $response.Close()
$lines = $listing -split "`r?`n" | Where-Object { $_ -ne "" }
foreach ($line in $lines) {
$isDirectory = $false
$folderName = $null
$dateTime = $null
if ($line -match "^d.*\s+(\S+)$") {
$folderName = $matches[1]
$isDirectory = $true
if ($line -match "(\w{3})\s+(\d{1,2})\s+(\d{2}:\d{2})") {
$month = $matches[1]; $day = $matches[2]; $time = $matches[3]
$currentYear = (Get-Date).Year
try {
$dateTime = [DateTime]::ParseExact("$month $day $currentYear $time", "MMM d yyyy HH:mm", [System.Globalization.CultureInfo]::InvariantCulture)
} catch {
try {
$dateTime = [DateTime]::ParseExact("$month $day $currentYear $time", "MMM dd yyyy HH:mm", [System.Globalization.CultureInfo]::InvariantCulture)
} catch { $dateTime = $null }
}
}
}
elseif ($line -match "<DIR>\s+(\S+)$") {
$folderName = $matches[1]
$isDirectory = $true
if ($line -match "(\d{2}-\d{2}-\d{2})\s+(\d{2}:\d{2}[AP]M)") {
try {
$dateTime = [DateTime]::ParseExact("$($matches[1]) $($matches[2])", "MM-dd-yy hh:mmtt", [System.Globalization.CultureInfo]::InvariantCulture)
} catch { $dateTime = $null }
}
}
if ($isDirectory -and $folderName -and $folderName -ne "." -and $folderName -ne "..") {
if ($dateTime) { $folders[$folderName] = $dateTime }
else { $folders[$folderName] = [DateTime]::MinValue }
}
}
return $folders
}
catch {
Write-Host " Ошибка при получении списка папок: $_" -ForegroundColor Red
return @{}
}
}
function Get-FtpFileList {
param([string]$ftpPath)
$items = @()
try {
$uri = "ftp://$ftpHost$ftpPath/"
$request = [System.Net.FtpWebRequest]::Create($uri)
$request.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectory
$request.Credentials = New-Object System.Net.NetworkCredential($ftpUser, $ftpPassword)
$request.UseBinary = $true
$request.UsePassive = $true
$request.EnableSsl = $false
$request.KeepAlive = $false
$request.Timeout = 30000
$response = $request.GetResponse()
$stream = $response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($stream)
$listing = $reader.ReadToEnd()
$reader.Close(); $response.Close()
$lines = $listing -split "`r?`n" | Where-Object { $_ -ne "" }
foreach ($line in $lines) { $items += $line.Trim() }
return $items
}
catch {
Write-Host " Ошибка при получении списка файлов: $_" -ForegroundColor Red
return @()
}
}
function Get-FtpFileSize {
param(
[string]$remoteUri,
[string]$ftpDirPath,
[string]$fileName
)
try {
$request = [System.Net.FtpWebRequest]::Create($remoteUri)
$request.Method = [System.Net.WebRequestMethods+Ftp]::GetFileSize
$request.Credentials = New-Object System.Net.NetworkCredential($ftpUser, $ftpPassword)
$request.UseBinary = $true
$request.UsePassive = $true
$request.EnableSsl = $false
$request.KeepAlive = $false
$request.Timeout = 30000
$response = $request.GetResponse()
$size = $response.ContentLength
$response.Close()
if ($size -gt 0) { return [int64]$size }
}
catch {}
try {
$uri = "ftp://$ftpHost$ftpDirPath/"
$request = [System.Net.FtpWebRequest]::Create($uri)
$request.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectoryDetails
$request.Credentials = New-Object System.Net.NetworkCredential($ftpUser, $ftpPassword)
$request.UseBinary = $true
$request.UsePassive = $true
$request.EnableSsl = $false
$request.KeepAlive = $false
$request.Timeout = 30000
$response = $request.GetResponse()
$stream = $response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($stream)
$listing = $reader.ReadToEnd()
$reader.Close(); $response.Close()
$lines = $listing -split "`r?`n" | Where-Object { $_ -ne "" }
foreach ($line in $lines) {
if ($line -match ("\s" + [regex]::Escape($fileName) + "\s*$")) {
if ($line -match "^\d{2}-\d{2}-\d{2}\s+\d{2}:\d{2}[AP]M\s+(\d+)\s+") {
return [int64]$matches[1]
}
if ($line -match "^-.*\s+(\d+)\s+\w{3}\s+\d{1,2}\s+(\d{2}:\d{2}|\d{4})\s+") {
return [int64]$matches[1]
}
}
}
}
catch {}
return -1
}
function Get-VersionFile {
param([string]$folderPath)
if (!(Test-Path $folderPath)) { return $null }
$files = Get-ChildItem -Path $folderPath -File -Force -ErrorAction SilentlyContinue
foreach ($f in $files) {
if ($f.BaseName -match $versionPattern) { return $f }
}
return $null
}
function Update-VersionFile {
param(
[string]$folderPath,
[string]$latestFolder,
[System.IO.FileInfo]$versionFile
)
try {
if ($versionFile) {
if ($versionFile.BaseName -eq $latestFolder) { return }
$extension = $versionFile.Extension
if ([string]::IsNullOrEmpty($extension)) { $extension = ".txt" }
$newName = "$latestFolder$extension"
Rename-Item -Path $versionFile.FullName -NewName $newName -Force
Write-Host " Файл версии переименован: $($versionFile.Name) -> $newName" -ForegroundColor Green
}
else {
$newName = "$latestFolder.txt"
$newPath = Join-Path $folderPath $newName
New-Item -ItemType File -Path $newPath -Force | Out-Null
Write-Host " Создан файл версии: $newName" -ForegroundColor Green
}
}
catch {
Write-Host " Ошибка при обновлении файла версии: $_" -ForegroundColor Red
}
}
function Download-FtpFile {
param(
[string]$remoteUri,
[string]$localPath,
[string]$ftpDirPath = "",
[string]$fileName = ""
)
try {
if (-not $fileName) { $fileName = Split-Path $localPath -Leaf }
$knownSize = Get-FtpFileSize -remoteUri $remoteUri -ftpDirPath $ftpDirPath -fileName $fileName
$resumeOffset = 0
if (Test-Path $localPath) {
$resumeOffset = (Get-Item $localPath).Length
if ($knownSize -gt 0 -and $resumeOffset -ge $knownSize) {
Write-Host " Локальный файл уже полностью скачан ($([math]::Round($resumeOffset / 1MB, 2)) MB)." -ForegroundColor Green
return $true
}
if ($resumeOffset -gt 0) {
$mbHave = [math]::Round($resumeOffset / 1MB, 2)
$mbAll = if ($knownSize -gt 0) { [math]::Round($knownSize / 1MB, 2) } else { "?" }
Write-Host " Найден недокачанный файл: $mbHave / $mbAll MB. Пробуем докачать." -ForegroundColor Yellow
}
}
$request = [System.Net.FtpWebRequest]::Create($remoteUri)
$request.Method = [System.Net.WebRequestMethods+Ftp]::DownloadFile
$request.Credentials = New-Object System.Net.NetworkCredential($ftpUser, $ftpPassword)
$request.UseBinary = $true
$request.UsePassive = $true
$request.EnableSsl = $false
$request.KeepAlive = $false
$request.Timeout = 60000
$resumeSupported = $false
if ($resumeOffset -gt 0) {
try {
$request.ContentOffset = $resumeOffset
$resumeSupported = $true
} catch {
Write-Host " Сервер не поддерживает докачку: $($_.Exception.Message)" -ForegroundColor Yellow
$resumeSupported = $false
}
}
$response = $null
try {
$response = $request.GetResponse()
} catch {
if ($resumeSupported) {
Write-Host " Докачка не удалась, начинаем с нуля..." -ForegroundColor Yellow
if (Test-Path $localPath) { Remove-Item $localPath -Force -ErrorAction SilentlyContinue }
$resumeOffset = 0
$request = [System.Net.FtpWebRequest]::Create($remoteUri)
$request.Method = [System.Net.WebRequestMethods+Ftp]::DownloadFile
$request.Credentials = New-Object System.Net.NetworkCredential($ftpUser, $ftpPassword)
$request.UseBinary = $true
$request.UsePassive = $true
$request.EnableSsl = $false
$request.KeepAlive = $false
$request.Timeout = 60000
$response = $request.GetResponse()
} else { throw }
}
$remaining = $response.ContentLength
if ($remaining -le 0) { $remaining = $knownSize - $resumeOffset }
$totalBytes = if ($knownSize -gt 0) { $knownSize } else { $resumeOffset + $remaining }
$ftpStream = $response.GetResponseStream()
if ($resumeOffset -gt 0 -and $resumeSupported) {
$localStream = [System.IO.File]::Open($localPath, [System.IO.FileMode]::Append, [System.IO.FileAccess]::Write, [System.IO.FileShare]::None)
} else {
$localStream = [System.IO.File]::Create($localPath)
$resumeOffset = 0
}
$buffer = New-Object Byte[] $BufferSize
$bytesRead = $ftpStream.Read($buffer, 0, $BufferSize)
$downloaded = $resumeOffset
$lastRender = [DateTime]::MinValue
$lastMb = -1
$width = 30
$speedSw = $null
$speedStartBytes = 0
if ($ShowSpeed) {
$speedSw = [System.Diagnostics.Stopwatch]::StartNew()
$speedStartBytes = $downloaded
}
while ($bytesRead -gt 0) {
$localStream.Write($buffer, 0, $bytesRead)
$downloaded += $bytesRead
$bytesRead = $ftpStream.Read($buffer, 0, $BufferSize)
$now = Get-Date
if (($now - $lastRender).TotalMilliseconds -lt $ProgressEveryMs) { continue }
$lastRender = $now
if ($totalBytes -gt 0) {
Show-ProgressLine -FileName $fileName -Downloaded $downloaded -Total $totalBytes -Width $width
} else {
$mbNow = [math]::Floor($downloaded / 1MB)
if ($mbNow -eq $lastMb) { continue }
$lastMb = $mbNow
Show-ProgressLine -FileName $fileName -Downloaded $downloaded -Total 0 -Width $width
}
}
$localStream.Close()
$ftpStream.Close()
$response.Close()
if ($totalBytes -gt 0) {
Show-ProgressLine -FileName $fileName -Downloaded $totalBytes -Total $totalBytes -Width $width
}
Write-Host ""
if ($ShowSpeed -and $speedSw) {
$speedSw.Stop()
$sec = $speedSw.Elapsed.TotalSeconds
if ($sec -gt 0) {
$bytesTransferred = $downloaded - $speedStartBytes
$speedMBs = [math]::Round(($bytesTransferred / 1MB) / $sec, 2)
Write-Host (" Скорость скачивания: {0} MB/s" -f $speedMBs) -ForegroundColor Yellow
}
}
$fileSize = [math]::Round($downloaded / 1MB, 2)
if ($resumeOffset -gt 0) {
Write-Host (" Файл докачан: {0} ({1} MB)" -f $localPath, $fileSize) -ForegroundColor Green
} else {
Write-Host (" Файл скачан: {0} ({1} MB)" -f $localPath, $fileSize) -ForegroundColor Green
}
return $true
}
catch {
Write-Host ""
Write-Host " Ошибка при скачивании: $_" -ForegroundColor Red
return $false
}
}
# ============================================================
# Фаза 1: скачивание архивов с FTP
# ============================================================
function Invoke-DownloadPhase {
param([hashtable]$mapping)
$plan = @()
foreach ($remoteFolder in $mapping.Keys) {
$localFolder = $mapping[$remoteFolder]
Write-Host ""
Write-Host (">> [Скачивание] {0} -> {1}" -f $remoteFolder, $localFolder) -ForegroundColor Magenta
$remoteBasePath = "$ftpPath/$remoteFolder"
$networkFolder = Join-Path $networkBasePath $localFolder
if (!(Test-Path $localBasePath)) {
New-Item -ItemType Directory -Path $localBasePath -Force | Out-Null
Write-Host " Создана временная папка: $localBasePath" -ForegroundColor Gray
}
if (!(Test-Path $networkFolder)) {
New-Item -ItemType Directory -Path $networkFolder -Force | Out-Null
Write-Host " Создана сетевая папка: $networkFolder" -ForegroundColor Gray
}
Write-Host " Получение списка папок из: ftp://$ftpHost$remoteBasePath/" -ForegroundColor Gray
$foldersWithDates = Get-FtpFoldersWithDates -ftpPath $remoteBasePath
if ($foldersWithDates.Count -eq 0) {
Write-Host " В папке $remoteFolder нет подпапок" -ForegroundColor Red
return $null
}
Write-Host " Найдено папок: $($foldersWithDates.Count)" -ForegroundColor Gray
$latestFolder = $null
$latestDate = [DateTime]::MinValue
foreach ($folder in $foldersWithDates.Keys) {
$date = $foldersWithDates[$folder]
if ($date -gt $latestDate) {
$latestDate = $date
$latestFolder = $folder
}
}
if (-not $latestFolder) {
Write-Host " Не удалось определить самую новую папку" -ForegroundColor Red
return $null
}
Write-Host " Самая новая папка: $latestFolder ($($latestDate.ToString('dd.MM.yyyy HH:mm')))" -ForegroundColor Green
# === Проверка версии ===
$versionFile = Get-VersionFile -folderPath $networkFolder
if ($versionFile) {
Write-Host " Файл версии на сети: $($versionFile.Name)" -ForegroundColor Gray
if ($versionFile.BaseName -eq $latestFolder) {
Write-Host " Версия актуальна ($($versionFile.BaseName) = $latestFolder). Пропускаем." -ForegroundColor Green
continue
} else {
Write-Host " Версия неактуальна ($($versionFile.BaseName) <> $latestFolder). Забираем архив." -ForegroundColor Yellow
}
} else {
Write-Host " Файл версии на сети не найден. Забираем архив." -ForegroundColor Yellow
}
$ekpPath = "$remoteBasePath/$latestFolder/EKP"
Write-Host " Проверка EKP: ftp://$ftpHost$ekpPath/" -ForegroundColor Gray
$ekpFiles = Get-FtpFileList -ftpPath $ekpPath
if ($ekpFiles.Count -eq 0) {
Write-Host " Папка EKP пуста или не существует" -ForegroundColor Red
return $null
}
Write-Host " Найдено файлов в EKP: $($ekpFiles.Count)" -ForegroundColor Gray
$archives = @()
foreach ($file in $ekpFiles) {
if ($file -match "\.rar$") { $archives += $file }
}
if ($archives.Count -eq 0) {
Write-Host " В EKP не найдено RAR архивов" -ForegroundColor Red
return $null
}
$archiveToDownload = $archives[0]
Write-Host " Выбран архив: $archiveToDownload" -ForegroundColor Gray
$localFilePath = Join-Path $localBasePath $archiveToDownload
# --- Проверяем локальный файл ---
if (Test-Path $localFilePath) {
$localInfo = Get-Item $localFilePath
if ($localInfo.LastWriteTime -lt (Get-Date).AddDays(-1)) {
Write-Host " Удаляем устаревший локальный файл: $localFilePath" -ForegroundColor Gray
Remove-Item $localFilePath -Force -ErrorAction SilentlyContinue
}
}
$downloadUri = "ftp://$ftpHost$ekpPath/$archiveToDownload"
Write-Host " Скачивание: $archiveToDownload" -ForegroundColor Cyan
if (-not (Download-FtpFile -remoteUri $downloadUri -localPath $localFilePath -ftpDirPath $ekpPath -fileName $archiveToDownload)) {
Write-Host " Не удалось скачать архив $archiveToDownload" -ForegroundColor Red
return $null
}
$plan += [PSCustomObject]@{
RemoteFolder = $remoteFolder
LocalFolder = $localFolder
LatestFolder = $latestFolder
NetworkFolder = $networkFolder
VersionFile = $versionFile
ArchiveName = $archiveToDownload
LocalFilePath = $localFilePath
}
}
return ,$plan
}
# ============================================================
# MAIN
# ============================================================
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "FTP-хост: $ftpHost" -ForegroundColor Yellow
Write-Host "FTP-путь: $ftpPath" -ForegroundColor Yellow
Write-Host "Временная: $localBasePath" -ForegroundColor Yellow
Write-Host "Сетевая: $networkBasePath" -ForegroundColor Yellow
Write-Host "Downloader: $downloader" -ForegroundColor Yellow
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
if (!(Test-Path $networkBasePath)) {
Write-Host "ВНИМАНИЕ: сетевой путь недоступен: $networkBasePath" -ForegroundColor Red
Write-Host ""
}
if (!(Test-Path $downloader)) {
Write-Host "ОШИБКА: downloader.ps1 не найден: $downloader" -ForegroundColor Red
Read-Host "ENTER для закрытия"
exit 1
}
# --- ФАЗА 1: скачивание ---
Write-Host "Шаг 1 - скачивание с FTP" -ForegroundColor Cyan
$plan = Invoke-DownloadPhase -mapping $folderMapping
if ($null -eq $plan) {
Write-Host ""
Write-Host "Фаза скачивания завершилась с ошибкой." -ForegroundColor Red
Read-Host "ENTER для закрытия"
exit 1
}
if ($plan.Count -eq 0) {
Write-Host ""
Write-Host "Все версии актуальны — нечего скачивать и устанавливать." -ForegroundColor Green
Write-Host ""
Read-Host "ENTER для закрытия"
exit 0
}
Write-Host ""
Write-Host "Скачано архивов: $($plan.Count). Передаём управление downloader.ps1..." -ForegroundColor Green
Write-Host ""
# --- ФАЗА 2: вызов downloader.ps1 ---
# downloader сам разберётся, какие папки в $localBasePath обрабатывать,
# установит MSI, заархивирует результат и положит в $networkBasePath.
$dlArgs = @(
"-NoProfile",
"-ExecutionPolicy", "Bypass",
"-File", "`"$downloader`""
)
Write-Host "Запуск: powershell.exe $($dlArgs -join ' ')" -ForegroundColor Cyan
$dlProc = Start-Process powershell.exe -ArgumentList $dlArgs -Wait -PassThru -NoNewWindow
if ($dlProc.ExitCode -ne 0) {
Write-Host ""
Write-Host "downloader.ps1 завершился с кодом $($dlProc.ExitCode)." -ForegroundColor Red
Read-Host "ENTER для закрытия"
exit $dlProc.ExitCode
}
Write-Host ""
Write-Host "downloader.ps1 успешно завершён (код 0)." -ForegroundColor Green
# --- ФАЗА 3: очистка временной папки ---
Write-Host ""
Write-Host "Шаг 3 - очистка временной папки" -ForegroundColor Cyan
foreach ($item in $plan) {
if (Test-Path $item.LocalFilePath) {
try {
Remove-Item -Path $item.LocalFilePath -Force -ErrorAction Stop
Write-Host " Удалён: $($item.LocalFilePath)" -ForegroundColor Gray
} catch {
Write-Host " Не удалось удалить $($item.LocalFilePath): $($_.Exception.Message)" -ForegroundColor Yellow
}
}
}
Write-Host ""
Write-Host "Скрипт завершён." -ForegroundColor Cyan
#Start-Sleep -Seconds 10
exit 0
downloader.ps1
# ============================================================
# downloader.ps1 — установка MSI, архивация папок, выкладка на Z:
# ============================================================
# Вызывается из ftp.ps1 после скачивания архивов.
# Для каждой папки из $localBasePath:
# 1. Распаковывает RAR.
# 2. Находит MSI и устанавливает.
# 3. Ждёт/убивает CommonComponents.Catalog.IndexationUtility.
# 4. Запускает утилиту индексации.
# 5. Архивирует установленную папку программы в RAR.
# 6. Кладёт RAR в $networkBasePath\<LocalFolder>\.
# 7. Обновляет файл-маркер версии.
# ============================================================
# --- Проверка прав администратора ---
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
$isAdmin = $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isAdmin) {
Write-Host "ОШИБКА: скрипт запущен без прав администратора!" -ForegroundColor Red
Start-Sleep -Seconds 5
exit 1
}
Write-Host "=== УСТАНОВКА / ПЕРЕУСТАНОВКА ПО + АРХИВАЦИЯ ===" -ForegroundColor Cyan
Write-Host "Запущено от имени администратора" -ForegroundColor Green
Write-Host ""
# --- Пути ---
$localBasePath = "C:\Users\n4200-01-031\Desktop\App" # сюда ftp.ps1 скачал RAR
$networkBasePath = "Z:\Documents" # сюда кладём готовые архивы
$baseDir = if ($PSScriptRoot) { $PSScriptRoot } else { Split-Path -Parent $PSCommandPath }
if (-not $baseDir) { $baseDir = Get-Location }
$workBase = $baseDir
# --- WinRAR ---
$winRarPath = "C:\Program Files\WinRAR\WinRAR.exe"
if (!(Test-Path $winRarPath)) { $winRarPath = "C:\Program Files (x86)\WinRAR\WinRAR.exe" }
if (!(Test-Path $winRarPath)) {
Write-Host "ОШИБКА: WinRAR не найден!" -ForegroundColor Red
Start-Sleep -Seconds 10
exit 1
}
Write-Host "Источник RAR: $localBasePath" -ForegroundColor Cyan
Write-Host "Рабочая папка: $workBase" -ForegroundColor Cyan
Write-Host "Сеть: $networkBasePath" -ForegroundColor Cyan
Write-Host "WinRAR: $winRarPath" -ForegroundColor Cyan
Write-Host ""
# --- Список программ ---
$programs = @(
@{ LocalFolder = "KPE"; Name = "Клиент АИС Налог-3 Пром версия"; InstallFolder = "Ais3Prom" }
@{ LocalFolder = "PPK"; Name = "Клиент АИС Налог-3 ПредПром версия"; InstallFolder = "Ais3PredProm" }
@{ LocalFolder = "KOE"; Name = "Клиент АИС Налог-3 ОЭ версия"; InstallFolder = "Ais3FB3OE" }
@{ LocalFolder = "KOEIZ"; Name = "Клиент АИС Налог-3 ОЭ ИЗ версия"; InstallFolder = "Ais3OEIZ" }
)
# ============================================================
# Вспомогательные функции
# ============================================================
function Find-InstalledProgram {
param([string]$exactName)
Write-Host "Поиск программы: $exactName" -ForegroundColor Cyan
$foundPackage = Get-Package -Name $exactName -ErrorAction SilentlyContinue | Select-Object -First 1
if (-not $foundPackage) {
$foundPackage = Get-Package -Name "*$exactName*" -ErrorAction SilentlyContinue | Select-Object -First 1
}
if ($foundPackage) {
Write-Host "Найдена: $($foundPackage.Name) (v$($foundPackage.Version))" -ForegroundColor Green
} else {
Write-Host "Не найдена" -ForegroundColor Gray
}
return $foundPackage
}
function Uninstall-Program {
param([string]$displayName, $package)
Write-Host "Удаление: $displayName" -ForegroundColor Yellow
try {
Uninstall-Package -InputObject $package -Force -ErrorAction Stop
Write-Host "Удаление успешно" -ForegroundColor Green
Start-Sleep -Seconds 3
}
catch {
Write-Host "Ошибка удаления: $($_.Exception.Message)" -ForegroundColor Red
}
}
function Clear-WorkFolder {
param([string]$FolderPath)
if (-not (Test-Path $FolderPath)) { return }
Write-Host "Очистка рабочей папки (кроме *.ps1): $FolderPath" -ForegroundColor Cyan
Get-ChildItem -Path $FolderPath -Force -ErrorAction SilentlyContinue |
Where-Object { $_.Extension -ne ".ps1" } |
ForEach-Object {
Write-Host " Удаление: $($_.FullName)" -ForegroundColor Gray
Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
}
}
function Extract-RarArchive {
param([string]$archivePath, [string]$destinationPath)
Write-Host "Распаковка: $archivePath" -ForegroundColor Cyan
Write-Host " в: $destinationPath" -ForegroundColor Gray
try {
$arguments = "x -o+ -y `"$archivePath`" `"$destinationPath\`""
$process = Start-Process -FilePath $winRarPath -ArgumentList $arguments -Wait -PassThru -NoNewWindow
if ($process.ExitCode -eq 0) {
Write-Host "Распаковка успешна!" -ForegroundColor Green
return $true
} else {
Write-Host "Ошибка распаковки! Код: $($process.ExitCode)" -ForegroundColor Red
return $false
}
}
catch {
Write-Host "Ошибка распаковки: $($_.Exception.Message)" -ForegroundColor Red
return $false
}
}
function Compress-ProgramFolder {
param(
[string]$sourceFolder, # полный путь к папке программы
[string]$rarPath, # полный путь к выходному .rar
[string]$baseFolderName # имя папки для сохранения внутри архива
)
Write-Host "Архивация: $sourceFolder -> $rarPath" -ForegroundColor Cyan
try {
# WinRAR: a -r -ep1 <rar> <папка>
# -ep1 — исключить базовый путь, сохранить только имя папки
$parent = Split-Path -Parent $sourceFolder
$leaf = Split-Path -Leaf $sourceFolder
$arguments = "a -r -ep1 -o+ -y -ibck `"$rarPath`" `"$sourceFolder\`""
$process = Start-Process -FilePath $winRarPath -ArgumentList $arguments -Wait -PassThru -NoNewWindow
# Код 0 — успех, код 1 — предупреждения (всё равно считаем успехом)
if ($process.ExitCode -eq 0 -or $process.ExitCode -eq 1) {
$sizeMb = [math]::Round((Get-Item $rarPath).Length / 1MB, 2)
Write-Host "Архив создан: $rarPath ($sizeMb MB)" -ForegroundColor Green
return $true
} else {
Write-Host "Ошибка архивации! Код: $($process.ExitCode)" -ForegroundColor Red
return $false
}
}
catch {
Write-Host "Ошибка архивации: $($_.Exception.Message)" -ForegroundColor Red
return $false
}
}
function Install-Program {
param(
[string]$msiPath,
[string]$programName,
[string]$installFolder
)
$processToKill = "CommonComponents.Catalog.IndexationUtility"
$exeToRun = "CommonComponents.Catalog.IndexationUtility.exe"
Write-Host "Установка MSI: $msiPath" -ForegroundColor Cyan
$installArguments = "/i `"$msiPath`" /quiet"
$installProcess = Start-Process -FilePath "msiexec.exe" `
-ArgumentList $installArguments -PassThru -WindowStyle Hidden
Write-Host "Установка запущена (PID: $($installProcess.Id))" -ForegroundColor Green
# --- Ожидание процесса индексации ---
$targetProcess = $null
$timeout = 1000
$elapsed = 0
Write-Host "Ожидание $processToKill..." -ForegroundColor Cyan
while ($elapsed -lt $timeout) {
$targetProcess = Get-Process -Name $processToKill -ErrorAction SilentlyContinue
if ($targetProcess) {
Write-Host "Процесс обнаружен! PID: $($targetProcess.Id)" -ForegroundColor Green
Write-Host "Завершение..." -ForegroundColor Yellow
Stop-Process -Id $targetProcess.Id -Force
Write-Host "Процесс завершён." -ForegroundColor Green
break
}
Start-Sleep -Seconds 2
$elapsed += 2
}
if (-not $targetProcess) {
Write-Host "Внимание: процесс $processToKill не обнаружен" -ForegroundColor Red
}
Write-Host "Ожидание завершения установки..." -ForegroundColor Cyan
Wait-Process -Id $installProcess.Id -ErrorAction SilentlyContinue
Write-Host "Установка MSI завершена." -ForegroundColor Green
Start-Sleep -Seconds 3
# --- Поиск папки программы ---
$programsPath = "C:\Program Files (x86)"
$programFolder = $null
if (Test-Path $programsPath) {
$programFolder = Get-ChildItem $programsPath -Directory -ErrorAction SilentlyContinue |
Where-Object { $_.Name -eq $installFolder } | Select-Object -First 1
if (-not $programFolder) {
$programFolder = Get-ChildItem $programsPath -Directory -ErrorAction SilentlyContinue |
Where-Object { $_.Name -like "*$installFolder*" } | Select-Object -First 1
}
}
if (-not $programFolder) {
Write-Host "Внимание: папка '$installFolder' не найдена" -ForegroundColor Yellow
return $null
}
Write-Host "Папка программы: $($programFolder.FullName)" -ForegroundColor Green
# --- Запуск утилиты индексации ---
$exePath = Join-Path $programFolder.FullName "Client" | Join-Path -ChildPath $exeToRun
$exePathRoot = Join-Path $programFolder.FullName $exeToRun
$finalExe = $null
if (Test-Path $exePath) { $finalExe = $exePath }
elseif (Test-Path $exePathRoot) { $finalExe = $exePathRoot }
if (-not $finalExe) {
Write-Host "Внимание: утилита $exeToRun не найдена" -ForegroundColor Red
return $programFolder.FullName
}
Write-Host "Запуск утилиты: $finalExe" -ForegroundColor Cyan
try {
$utilityProcess = Start-Process -FilePath $finalExe -Wait -PassThru -WindowStyle Hidden -ErrorAction Stop
Write-Host "Утилита завершила работу (ExitCode: $($utilityProcess.ExitCode))" -ForegroundColor Green
}
catch {
Write-Host "ОШИБКА запуска утилиты: $($_.Exception.Message)" -ForegroundColor Red
}
return $programFolder.FullName
}
# ============================================================
# Обработка одной программы
# ============================================================
function Process-Program {
param(
[string]$localFolder,
[string]$programName,
[string]$installFolder
)
Write-Host ""
Write-Host "=====================================================" -ForegroundColor Magenta
Write-Host ">>> $programName (папка $localFolder)" -ForegroundColor Magenta
Write-Host "=====================================================" -ForegroundColor Magenta
# 1. Ищем RAR в локальной папке (ftp.ps1 уже скачал)
$sourceFolder = Join-Path $localBasePath $localFolder
if (-not (Test-Path $sourceFolder)) {
Write-Host "Папка-источник не найдена: $sourceFolder" -ForegroundColor Red
return $false
}
$rarFiles = Get-ChildItem -Path $sourceFolder -Filter "*.rar" -File -Recurse -ErrorAction SilentlyContinue
if ($rarFiles.Count -eq 0) {
Write-Host "В $localFolder не найдено .rar" -ForegroundColor Red
return $false
}
$rarToUse = $rarFiles | Select-Object -First 1
Write-Host "Найден архив: $($rarToUse.Name)" -ForegroundColor Green
# 2. Чистим рабочую папку от предыдущих распаковок
Clear-WorkFolder -FolderPath $workBase
# 3. Копируем RAR локально
$localRarPath = Join-Path $workBase $rarToUse.Name
Write-Host "Копирование: $($rarToUse.FullName) -> $localRarPath" -ForegroundColor Cyan
try {
Copy-Item -Path $rarToUse.FullName -Destination $localRarPath -Force -ErrorAction Stop
$sizeMb = [math]::Round((Get-Item $localRarPath).Length / 1MB, 2)
Write-Host "Скопировано ($sizeMb MB)" -ForegroundColor Green
}
catch {
Write-Host "ОШИБКА копирования: $($_.Exception.Message)" -ForegroundColor Red
return $false
}
# 4. Распаковка
if (-not (Extract-RarArchive -archivePath $localRarPath -destinationPath $workBase)) {
Write-Host "Распаковка не удалась" -ForegroundColor Red
return $false
}
# 5. Поиск MSI
$msiFile = Get-ChildItem -Path $workBase -Filter "*.msi" -File -Recurse -ErrorAction SilentlyContinue |
Select-Object -First 1
if (-not $msiFile) {
Write-Host "MSI не найден" -ForegroundColor Red
return $false
}
Write-Host "Найден установщик: $($msiFile.Name)" -ForegroundColor Green
# 6. Удаление старой версии
$existingPackage = Find-InstalledProgram -exactName $programName
if ($existingPackage) {
Uninstall-Program -displayName $existingPackage.Name -package $existingPackage
} else {
Write-Host "Программа не найдена, будет установлена" -ForegroundColor Green
}
# 7. Установка MSI + утилита индексации
$installedFolder = Install-Program -msiPath $msiFile.FullName -programName $programName -installFolder $installFolder
if (-not $installedFolder -or -not (Test-Path $installedFolder)) {
Write-Host "Не удалось определить папку установки — пропускаем архивацию" -ForegroundColor Red
Clear-WorkFolder -FolderPath $workBase
return $false
}
# 8. Архивация установленной папки
$targetNetworkFolder = Join-Path $networkBasePath $localFolder
if (!(Test-Path $targetNetworkFolder)) {
New-Item -ItemType Directory -Path $targetNetworkFolder -Force | Out-Null
Write-Host "Создана сетевая папка: $targetNetworkFolder" -ForegroundColor Gray
}
# Определяем имя итогового RAR.
# Используем имя исходного RAR (или можно взять имя папки версии).
$finalRarName = "Installed_$localFolder.rar"
$finalRarPath = Join-Path $targetNetworkFolder $finalRarName
if (-not (Compress-ProgramFolder -sourceFolder $installedFolder -rarPath $finalRarPath -baseFolderName (Split-Path -Leaf $installedFolder))) {
Clear-WorkFolder -FolderPath $workBase
return $false
}
# 9. Чистим рабочую папку
Clear-WorkFolder -FolderPath $workBase
# 10. Чистим локальный RAR из sourceFolder (ftp.ps1 уже отработал)
try {
Remove-Item -Path $rarToUse.FullName -Force -ErrorAction Stop
Write-Host "Локальный RAR удалён: $($rarToUse.FullName)" -ForegroundColor Gray
} catch {
Write-Host "Не удалось удалить локальный RAR: $($_.Exception.Message)" -ForegroundColor Yellow
}
Write-Host "Программа '$programName' обработана." -ForegroundColor Green
Write-Host "---------------------------------------------------" -ForegroundColor Gray
return $true
}
# ============================================================
# MAIN
# ============================================================
Write-Host ""
Write-Host "=====================================================" -ForegroundColor Cyan
Write-Host "НАЧАЛО ОБРАБОТКИ" -ForegroundColor Cyan
Write-Host "=====================================================" -ForegroundColor Cyan
$successCount = 0
$totalCount = $programs.Count
foreach ($program in $programs) {
$ok = Process-Program `
-localFolder $program.LocalFolder `
-programName $program.Name `
-installFolder $program.InstallFolder
if ($ok) { $successCount++ }
}
Write-Host ""
Write-Host "=====================================================" -ForegroundColor Green
Write-Host "ЗАВЕРШЕНО: $successCount из $totalCount" -ForegroundColor Green
Write-Host "=====================================================" -ForegroundColor Green
if ($successCount -eq $totalCount) {
exit 0
} else {
exit 1
}
watcher.ps1
# ============================================================
# watcher.ps1 — наблюдение за Z:\Documents и распаковка RAR
# ============================================================
# Логика:
# - Следим за 4 папками: KPE, PPK, KOE, KOEIZ в $watchRoot.
# - При появлении нового/изменённого .rar:
# * ждём стабилизации размера;
# * распаковываем RAR в папку рядом со скриптом ($PSScriptRoot);
# * помечаем файл как обработанный (.rar.done).
# - Архиватор: WinRAR (приоритет) -> 7-Zip -> ошибка.
# ============================================================
# --- Права администратора ---
if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
Write-Host "Требуются права администратора. Перезапуск..." -ForegroundColor Yellow
Start-Process PowerShell -Verb RunAs -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`""
exit
}
Write-Host "=== WATCHER: наблюдение за Z:\Documents ===" -ForegroundColor Cyan
Write-Host "Запущено от имени администратора" -ForegroundColor Green
Write-Host ""
# --- Пути ---
$watchRoot = "Z:\Documents"
$targetDirs = @("KPE", "PPK", "KOE", "KOEIZ")
# --- Куда распаковывать ---
$scriptDir = if ($PSScriptRoot) { $PSScriptRoot } else { Split-Path -Parent $PSCommandPath }
if (-not $scriptDir) { $scriptDir = Get-Location }
$extractBase = $scriptDir
# --- Lock-файл ---
$lockFile = Join-Path $extractBase "watcher.processing.lock"
# ============================================================
# Поиск архиватора: WinRAR -> 7-Zip -> ошибка
# ============================================================
function Find-Archiver {
$result = @{
Type = $null # "WinRAR" | "7Zip"
Path = $null
ExeName = $null
}
# --- 1. WinRAR ---
$winRarCandidates = @(
"C:\Program Files\WinRAR\WinRAR.exe"
"C:\Program Files (x86)\WinRAR\WinRAR.exe"
)
# также попробуем найти в PATH
$winRarInPath = Get-Command "WinRAR.exe" -ErrorAction SilentlyContinue
if ($winRarInPath) { $winRarCandidates += $winRarInPath.Source }
foreach ($p in $winRarCandidates) {
if ($p -and (Test-Path $p)) {
$result.Type = "WinRAR"
$result.Path = $p
$result.ExeName = "WinRAR.exe"
return $result
}
}
# --- 2. 7-Zip ---
$sevenZipCandidates = @(
"C:\Program Files\7-Zip\7z.exe"
"C:\Program Files (x86)\7-Zip\7z.exe"
"C:\Program Files\7-Zip\7za.exe"
"C:\Program Files (x86)\7-Zip\7za.exe"
)
# также попробуем найти в PATH
foreach ($name in @("7z.exe", "7za.exe")) {
$inPath = Get-Command $name -ErrorAction SilentlyContinue
if ($inPath) { $sevenZipCandidates += $inPath.Source }
}
foreach ($p in $sevenZipCandidates) {
if ($p -and (Test-Path $p)) {
$result.Type = "7Zip"
$result.Path = $p
$result.ExeName = Split-Path -Leaf $p
return $result
}
}
return $result # Type = $null -> ничего не нашли
}
$archiver = Find-Archiver
if (-not $archiver.Type) {
Write-Host "=====================================================" -ForegroundColor Red
Write-Host "ОШИБКА: не найден ни WinRAR, ни 7-Zip!" -ForegroundColor Red
Write-Host "=====================================================" -ForegroundColor Red
Write-Host "Проверьте, что установлен один из архиваторов:" -ForegroundColor Yellow
Write-Host " - WinRAR: C:\Program Files\WinRAR\WinRAR.exe" -ForegroundColor Gray
Write-Host " C:\Program Files (x86)\WinRAR\WinRAR.exe" -ForegroundColor Gray
Write-Host " - 7-Zip: C:\Program Files\7-Zip\7z.exe" -ForegroundColor Gray
Write-Host " C:\Program Files (x86)\7-Zip\7z.exe" -ForegroundColor Gray
Write-Host " - или добавьте WinRAR.exe / 7z.exe в PATH" -ForegroundColor Gray
Write-Host ""
Read-Host "ENTER для выхода"
exit 1
}
Write-Host "Наблюдаем за: $watchRoot" -ForegroundColor Cyan
Write-Host "Подпапки: $($targetDirs -join ', ')" -ForegroundColor Cyan
Write-Host "Распаковка в: $extractBase" -ForegroundColor Cyan
Write-Host "Архиватор: $($archiver.Type) -> $($archiver.Path)" -ForegroundColor Cyan
Write-Host ""
if (-not (Test-Path $watchRoot)) {
Write-Host "ОШИБКА: путь не существует: $watchRoot" -ForegroundColor Red
Read-Host "ENTER для выхода"
exit 1
}
# ============================================================
# Распаковка через выбранный архиватор
# ============================================================
function Invoke-ExtractArchive {
param(
[string]$ArchivePath,
[string]$TargetDir,
[hashtable]$Archiver
)
if ($Archiver.Type -eq "WinRAR") {
# WinRAR: x -o+ -y "<archive>" "<dest>\"
$args = "x -o+ -y `"$ArchivePath`" `"$TargetDir\`""
}
elseif ($Archiver.Type -eq "7Zip") {
# 7-Zip: x -y -o"<dest>" "<archive>"
$args = "x -y -o`"$TargetDir`" `"$ArchivePath`""
}
else {
return @{ Success = $false; Message = "Неизвестный архиватор" }
}
try {
$process = Start-Process -FilePath $Archiver.Path `
-ArgumentList $args `
-Wait -PassThru -NoNewWindow
# WinRAR: 0 — успех, 1 — предупреждения (считаем успехом)
# 7-Zip: 0 — успех, 1 — предупреждения (считаем успехом)
if ($process.ExitCode -eq 0 -or $process.ExitCode -eq 1) {
return @{ Success = $true; ExitCode = $process.ExitCode }
} else {
return @{
Success = $false
ExitCode = $process.ExitCode
Message = "Код возврата: $($process.ExitCode)"
}
}
}
catch {
return @{ Success = $false; Message = $_.Exception.Message }
}
}
# ============================================================
# Ожидание стабилизации файла
# ============================================================
function Wait-FileStable {
param(
[string]$Path,
[int]$StableSeconds = 3,
[int]$TimeoutSeconds = 300
)
$elapsed = 0
$lastSize = -1
$stableStart = $null
while ($elapsed -lt $TimeoutSeconds) {
if (-not (Test-Path $Path)) { return $false }
try {
$size = (Get-Item $Path).Length
} catch {
Start-Sleep -Milliseconds 500
$elapsed += 0.5
continue
}
if ($size -ne $lastSize) {
$lastSize = $size
$stableStart = Get-Date
} else {
if ($stableStart -and ((Get-Date) - $stableStart).TotalSeconds -ge $StableSeconds) {
return $true
}
}
Start-Sleep -Milliseconds 500
$elapsed += 0.5
}
return $false
}
# ============================================================
# Обработка одного RAR
# ============================================================
function Invoke-ExtractRar {
param(
[string]$RarPath,
[string]$TargetDir
)
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "ОБНАРУЖЕН АРХИВ" -ForegroundColor Green
Write-Host "Файл: $RarPath" -ForegroundColor Yellow
Write-Host "Время: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Yellow
Write-Host "========================================" -ForegroundColor Cyan
# --- Lock ---
if (Test-Path $lockFile) {
Write-Host "Обработка уже идёт (lock). Пропускаем." -ForegroundColor Yellow
return
}
try {
New-Item -ItemType File -Path $lockFile -Force -ErrorAction Stop | Out-Null
} catch {
Write-Host "ОШИБКА создания lock: $($_.Exception.Message)" -ForegroundColor Red
return
}
try {
# --- Ждём стабилизации размера ---
Write-Host "Ожидание завершения записи файла..." -ForegroundColor Gray
if (-not (Wait-FileStable -Path $RarPath -StableSeconds 3 -TimeoutSeconds 300)) {
Write-Host "Файл не стабилизировался — пропускаем" -ForegroundColor Red
return
}
if (-not (Test-Path $RarPath)) {
Write-Host "Файл исчез до распаковки" -ForegroundColor Red
return
}
$sizeMb = [math]::Round((Get-Item $RarPath).Length / 1MB, 2)
Write-Host "Размер: $sizeMb MB" -ForegroundColor Gray
if (!(Test-Path $TargetDir)) {
New-Item -ItemType Directory -Path $TargetDir -Force | Out-Null
Write-Host "Создана папка: $TargetDir" -ForegroundColor Gray
}
Write-Host "Распаковка в: $TargetDir (через $($archiver.Type))" -ForegroundColor Cyan
$res = Invoke-ExtractArchive -ArchivePath $RarPath -TargetDir $TargetDir -Archiver $archiver
if ($res.Success) {
Write-Host "Распаковка успешна!" -ForegroundColor Green
# --- Помечаем обработанный RAR ---
try {
$doneName = $RarPath + ".done"
if (Test-Path $doneName) { Remove-Item $doneName -Force -ErrorAction SilentlyContinue }
Move-Item -Path $RarPath -Destination $doneName -Force -ErrorAction Stop
Write-Host "Файл помечен как обработанный: $doneName" -ForegroundColor Gray
} catch {
Write-Host "Не удалось переименовать: $($_.Exception.Message)" -ForegroundColor Yellow
}
} else {
Write-Host "Ошибка распаковки: $($res.Message)" -ForegroundColor Red
}
}
finally {
Remove-Item $lockFile -Force -ErrorAction SilentlyContinue
Write-Host "Lock снят" -ForegroundColor Gray
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
}
}
# ============================================================
# Настройка FileSystemWatcher для каждой подпапки
# ============================================================
$watchers = @()
$jobs = @()
foreach ($sub in $targetDirs) {
$fullPath = Join-Path $watchRoot $sub
if (-not (Test-Path $fullPath)) {
try {
New-Item -ItemType Directory -Path $fullPath -Force | Out-Null
Write-Host "Создана папка: $fullPath" -ForegroundColor Gray
} catch {
Write-Host "Не удалось создать $fullPath : $($_.Exception.Message)" -ForegroundColor Red
continue
}
}
$w = New-Object System.IO.FileSystemWatcher
$w.Path = $fullPath
$w.Filter = "*.rar"
$w.NotifyFilter = [System.IO.NotifyFilters]::FileName -bor [System.IO.NotifyFilters]::LastWrite -bor [System.IO.NotifyFilters]::Size
$w.EnableRaisingEvents = $true
$w.IncludeSubdirectories = $false
$action = {
$path = $Event.SourceEventArgs.FullPath
Invoke-ExtractRar -RarPath $path -TargetDir $extractBase
}
$job = Register-ObjectEvent -InputObject $w -EventName "Created" -Action $action
$jobs += $job
$watchers += $w
Write-Host "Наблюдаем: $fullPath" -ForegroundColor Gray
}
# --- Стартовый проход по уже существующим .rar ---
Write-Host ""
Write-Host "Стартовый проход по существующим .rar..." -ForegroundColor Cyan
foreach ($sub in $targetDirs) {
$fullPath = Join-Path $watchRoot $sub
if (Test-Path $fullPath) {
$existing = Get-ChildItem -Path $fullPath -Filter "*.rar" -File -ErrorAction SilentlyContinue
foreach ($f in $existing) {
Invoke-ExtractRar -RarPath $f.FullName -TargetDir $extractBase
}
}
}
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Наблюдатель запущен!" -ForegroundColor Green
Write-Host "Архиватор: $($archiver.Type) ($($archiver.Path))" -ForegroundColor Yellow
Write-Host "Для остановки нажмите Ctrl+C" -ForegroundColor Red
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
# --- Держим скрипт запущенным ---
try {
while ($true) { Start-Sleep -Seconds 1 }
}
finally {
Write-Host ""
Write-Host "Остановка watcher..." -ForegroundColor Yellow
foreach ($job in $jobs) {
Unregister-Event -SubscriptionId $job.Id -ErrorAction SilentlyContinue
}
foreach ($w in $watchers) {
$w.EnableRaisingEvents = $false
$w.Dispose()
}
Remove-Item $lockFile -Force -ErrorAction SilentlyContinue
Write-Host "Остановлен." -ForegroundColor Red
}