Загрузка данных
# ============================================================
# downloader.ps1 — установка MSI, архивация установленных папок,
# выкладка готовых RAR на Z:\Documents
# ============================================================
# Логика:
# 1. Берём ВСЕ .rar из $localBasePath (без подпапок).
# 2. Для каждого архива:
# - распаковываем во временную рабочую папку;
# - находим .msi и устанавливаем;
# - ждём/убиваем CommonComponents.Catalog.IndexationUtility;
# - запускаем утилиту индексации;
# - находим установленную папку программы;
# - архивируем её через WinRAR в <LocalFolder>\<ArchiveName>;
# - обновляем файл-маркер версии;
# - удаляем ТОЛЬКО временную распаковку.
# 3. Сам .rar НЕ трогаем, $localBasePath НЕ чистим
# (чисткой занимается ftp.ps1 после успешного завершения).
# ============================================================
# --- Проверка прав администратора ---
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
$isAdmin = $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isAdmin) {
Write-Host "ОШИБКА: скрипт запущен без прав администратора!" -ForegroundColor Red
Write-Host "Запустите от имени администратора." -ForegroundColor Red
Start-Sleep -Seconds 5
exit 1
}
Write-Host "=== УСТАНОВКА ПО + АРХИВАЦИЯ + ВЫКЛАДКА НА Z: ===" -ForegroundColor Cyan
Write-Host "Запущено от имени администратора" -ForegroundColor Green
Write-Host ""
# --- Пути ---
# Сюда ftp.ps1 скачал RAR-архивы (плоско, без подпапок)
$localBasePath = "C:\Users\n4200-01-031\Desktop\App"
# Сетевой диск, куда кладём готовые архивы
$networkBasePath = "Z:\Documents"
# Временная папка для распаковки (создаётся/удаляется по ходу)
$workBase = Join-Path $env:TEMP ("downloader_" + [guid]::NewGuid().ToString("N"))
# --- 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
Write-Host "Установите WinRAR или укажите путь в `$winRarPath" -ForegroundColor Red
Start-Sleep -Seconds 10
exit 1
}
Write-Host "Источник RAR: $localBasePath" -ForegroundColor Cyan
Write-Host "Сеть: $networkBasePath" -ForegroundColor Cyan
Write-Host "Рабочая папка: $workBase" -ForegroundColor Cyan
Write-Host "WinRAR: $winRarPath" -ForegroundColor Cyan
Write-Host ""
# --- Проверка источника ---
if (-not (Test-Path $localBasePath)) {
Write-Host "ОШИБКА: папка не найдена: $localBasePath" -ForegroundColor Red
Start-Sleep -Seconds 5
exit 1
}
# --- Собираем все .rar из корня $localBasePath ---
$rarFiles = Get-ChildItem -Path $localBasePath -Filter "*.rar" -File -ErrorAction SilentlyContinue
if ($rarFiles.Count -eq 0) {
Write-Host "В $localBasePath нет .rar архивов — нечего устанавливать." -ForegroundColor Yellow
Start-Sleep -Seconds 5
exit 0
}
Write-Host "Найдено архивов: $($rarFiles.Count)" -ForegroundColor Green
foreach ($r in $rarFiles) {
Write-Host " - $($r.Name) ($([math]::Round($r.Length / 1MB, 2)) MB)" -ForegroundColor Gray
}
Write-Host ""
# --- Соответствие: имя папки на Z: + имя программы + папка установки ---
# Ключ — имя, которое может встретиться в имени архива (KPE, PPK, KOE, KOEIZ).
# KOEIZ должен идти ПЕРЕД KOE, иначе regex поймает "KOE" внутри "KOEIZ".
$programMap = @(
@{ Key = "KOEIZ"; NetworkFolder = "KOEIZ"; ProgramName = "Клиент АИС Налог-3 ОЭ ИЗ версия"; InstallFolder = "Ais3OEIZ" }
@{ Key = "KPE"; NetworkFolder = "KPE"; ProgramName = "Клиент АИС Налог-3 Пром версия"; InstallFolder = "Ais3Prom" }
@{ Key = "PPK"; NetworkFolder = "PPK"; ProgramName = "Клиент АИС Налог-3 ПредПром версия"; InstallFolder = "Ais3PredProm" }
@{ Key = "KOE"; NetworkFolder = "KOE"; ProgramName = "Клиент АИС Налог-3 ОЭ версия"; InstallFolder = "Ais3FB3OE" }
)
# --- Шаблон имени файла-маркера версии (совпадает с ftp.ps1) ---
$versionPattern = '^\d+_\d+_\d+_\d+$'
# ============================================================
# Вспомогательные функции
# ============================================================
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-FolderToRar {
param(
[string]$sourceFolder,
[string]$rarPath
)
Write-Host " Архивация: $sourceFolder" -ForegroundColor Cyan
Write-Host " в: $rarPath" -ForegroundColor Gray
try {
# Убедимся, что родительская папка существует
$parent = Split-Path -Parent $rarPath
if (!(Test-Path $parent)) {
New-Item -ItemType Directory -Path $parent -Force | Out-Null
}
# Удаляем старый архив, если есть
if (Test-Path $rarPath) {
Remove-Item -Path $rarPath -Force -ErrorAction SilentlyContinue
}
# a -r -ep1 : добавить рекурсивно, сохранить только имя верхней папки
$arguments = "a -r -ep1 -o+ -y `"$rarPath`" `"$sourceFolder\`""
$process = Start-Process -FilePath $winRarPath -ArgumentList $arguments -Wait -PassThru -NoNewWindow
# WinRAR: 0 — успех, 1 — предупреждения (всё равно архив создан)
if ($process.ExitCode -eq 0 -or $process.ExitCode -eq 1) {
$sizeMb = [math]::Round((Get-Item $rarPath).Length / 1MB, 2)
Write-Host " Архив создан ($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 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 Install-Msi {
param([string]$msiPath, [string]$programName)
$processToKill = "CommonComponents.Catalog.IndexationUtility"
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
}
function Find-ProgramInstallFolder {
param([string]$installFolder)
$programsPath = "C:\Program Files (x86)"
if (!(Test-Path $programsPath)) { return $null }
$found = Get-ChildItem $programsPath -Directory -ErrorAction SilentlyContinue |
Where-Object { $_.Name -eq $installFolder } | Select-Object -First 1
if (-not $found) {
$found = Get-ChildItem $programsPath -Directory -ErrorAction SilentlyContinue |
Where-Object { $_.Name -like "*$installFolder*" } | Select-Object -First 1
}
if ($found) { return $found.FullName }
return $null
}
function Invoke-IndexationUtility {
param([string]$installFolderPath)
if (-not $installFolderPath) { return }
$exeToRun = "CommonComponents.Catalog.IndexationUtility.exe"
$exePath = Join-Path $installFolderPath "Client" | Join-Path -ChildPath $exeToRun
$exePathRoot = Join-Path $installFolderPath $exeToRun
$finalExe = $null
if (Test-Path $exePath) { $finalExe = $exePath }
elseif (Test-Path $exePathRoot) { $finalExe = $exePathRoot }
if (-not $finalExe) {
Write-Host " Внимание: утилита $exeToRun не найдена в $installFolderPath" -ForegroundColor Yellow
return
}
Write-Host " Запуск утилиты: $finalExe" -ForegroundColor Cyan
try {
$p = Start-Process -FilePath $finalExe -Wait -PassThru -WindowStyle Hidden -ErrorAction Stop
Write-Host " Утилита завершила работу (ExitCode: $($p.ExitCode))" -ForegroundColor Green
}
catch {
Write-Host " ОШИБКА запуска утилиты: $($_.Exception.Message)" -ForegroundColor Red
}
}
# --- Работа с файлом-маркером версии на Z: ---
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
}
}
# --- Определение версии из имени архива (если она там есть) ---
# Ищем в имени шаблон вида 1_2_3_4 — если найдём, используем как имя версии.
function Get-VersionFromArchiveName {
param([string]$archiveName)
if ($archiveName -match '(\d+_\d+_\d+_\d+)') {
return $matches[1]
}
return $null
}
# ============================================================
# MAIN — по одному архиву
# ============================================================
$successCount = 0
$totalCount = $rarFiles.Count
$index = 0
foreach ($rar in $rarFiles) {
$index++
Write-Host ""
Write-Host "=====================================================" -ForegroundColor Magenta
Write-Host ">>> [$index/$totalCount] Архив: $($rar.Name)" -ForegroundColor Magenta
Write-Host "=====================================================" -ForegroundColor Magenta
# --- Определяем, к какой программе относится архив ---
$matched = $null
foreach ($p in $programMap) {
if ($rar.Name -match [regex]::Escape($p.Key)) {
$matched = $p
break
}
}
if (-not $matched) {
Write-Host " Не удалось определить программу по имени архива: $($rar.Name)" -ForegroundColor Red
Write-Host " Пропускаем." -ForegroundColor Red
continue
}
Write-Host " Программа: $($matched.ProgramName)" -ForegroundColor Green
Write-Host " Папка на Z: $($matched.NetworkFolder)" -ForegroundColor Green
Write-Host " Папка установки: $($matched.InstallFolder)" -ForegroundColor Green
# --- Временная папка для распаковки именно этого архива ---
$extractDir = Join-Path $workBase ([System.IO.Path]::GetFileNameWithoutExtension($rar.Name))
if (!(Test-Path $extractDir)) {
New-Item -ItemType Directory -Path $extractDir -Force | Out-Null
}
# --- 1. Распаковка ---
if (-not (Extract-RarArchive -archivePath $rar.FullName -destinationPath $extractDir)) {
Write-Host " Пропускаем $($rar.Name) — распаковка не удалась" -ForegroundColor Red
Remove-Item -Path $extractDir -Recurse -Force -ErrorAction SilentlyContinue
continue
}
# --- 2. Поиск MSI ---
$msiFile = Get-ChildItem -Path $extractDir -Filter "*.msi" -File -Recurse -ErrorAction SilentlyContinue |
Select-Object -First 1
if (-not $msiFile) {
Write-Host " MSI не найден в $($rar.Name) — пропускаем" -ForegroundColor Red
Remove-Item -Path $extractDir -Recurse -Force -ErrorAction SilentlyContinue
continue
}
Write-Host " Найден установщик: $($msiFile.Name)" -ForegroundColor Green
# --- 3. Удаление старой версии ---
$existingPackage = Find-InstalledProgram -exactName $matched.ProgramName
if ($existingPackage) {
Uninstall-Program -displayName $existingPackage.Name -package $existingPackage
} else {
Write-Host " Программа не найдена — будет установлена" -ForegroundColor Green
}
# --- 4. Установка MSI + процесс индексации ---
Install-Msi -msiPath $msiFile.FullName -programName $matched.ProgramName
# --- 5. Поиск установленной папки ---
$installedFolder = Find-ProgramInstallFolder -installFolder $matched.InstallFolder
if (-not $installedFolder) {
Write-Host " Установленная папка '$($matched.InstallFolder)' не найдена — архивация невозможна" -ForegroundColor Red
Remove-Item -Path $extractDir -Recurse -Force -ErrorAction SilentlyContinue
continue
}
Write-Host " Установленная папка: $installedFolder" -ForegroundColor Green
# --- 6. Запуск утилиты индексации ---
Invoke-IndexationUtility -installFolderPath $installedFolder
# --- 7. Архивация установленной папки на Z: ---
$targetNetworkFolder = Join-Path $networkBasePath $matched.NetworkFolder
if (!(Test-Path $targetNetworkFolder)) {
try {
New-Item -ItemType Directory -Path $targetNetworkFolder -Force | Out-Null
Write-Host " Создана сетевая папка: $targetNetworkFolder" -ForegroundColor Gray
} catch {
Write-Host " ОШИБКА создания $targetNetworkFolder : $($_.Exception.Message)" -ForegroundColor Red
Remove-Item -Path $extractDir -Recurse -Force -ErrorAction SilentlyContinue
continue
}
}
# Имя итогового архива: <NetworkFolder>_<версия>.rar
# Если версии в имени архива нет — используем имя исходного архива.
$version = Get-VersionFromArchiveName -archiveName $rar.Name
if ($version) {
$finalRarName = "$($matched.NetworkFolder)_$version.rar"
} else {
$finalRarName = "$($matched.NetworkFolder)_$([System.IO.Path]::GetFileNameWithoutExtension($rar.Name)).rar"
}
$finalRarPath = Join-Path $targetNetworkFolder $finalRarName
if (-not (Compress-FolderToRar -sourceFolder $installedFolder -rarPath $finalRarPath)) {
Write-Host " Не удалось создать архив $finalRarPath" -ForegroundColor Red
Remove-Item -Path $extractDir -Recurse -Force -ErrorAction SilentlyContinue
continue
}
# --- 8. Обновление файла-маркера версии (если известна версия) ---
if ($version) {
$versionFile = Get-VersionFile -folderPath $targetNetworkFolder
Update-VersionFile -folderPath $targetNetworkFolder -latestFolder $version -versionFile $versionFile
} else {
Write-Host " Версия не определена — файл-маркер не обновляем" -ForegroundColor Yellow
}
# --- 9. Удаляем ТОЛЬКО временную распаковку ---
try {
Remove-Item -Path $extractDir -Recurse -Force -ErrorAction Stop
Write-Host " Временная распаковка удалена: $extractDir" -ForegroundColor Gray
} catch {
Write-Host " Не удалось удалить $extractDir : $($_.Exception.Message)" -ForegroundColor Yellow
}
Write-Host " Архив $($rar.Name) обработан (сам файл оставлен)" -ForegroundColor Green
$successCount++
}
# --- Удаляем только общий workBase, если он остался ---
if (Test-Path $workBase) {
try {
Remove-Item -Path $workBase -Recurse -Force -ErrorAction SilentlyContinue
} catch {
# игнорируем
}
}
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
}