Загрузка данных


# ============================================================
#  downloader.ps1 — установка MSI из RAR-архивов
# ============================================================
#  Логика:
#   1. Берём ВСЕ .rar из $localBasePath (без подпапок).
#   2. Для каждого архива:
#        - распаковываем во временную рабочую папку;
#        - находим .msi и устанавливаем;
#        - ждём/убиваем CommonComponents.Catalog.IndexationUtility;
#        - запускаем утилиту индексации;
#        - удаляем ТОЛЬКО временную распаковку.
#   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 "=== УСТАНОВКА ПО ИЗ RAR-АРХИВОВ ===" -ForegroundColor Cyan
Write-Host "Запущено от имени администратора" -ForegroundColor Green
Write-Host ""

# --- Пути ---
# Сюда ftp.ps1 скачал RAR-архивы (плоско, без подпапок)
$localBasePath = "C:\Users\n4200-01-031\Desktop\App"

# Временная папка для распаковки (создаётся/удаляется по ходу)
$workBase = Join-Path $env:TEMP ("downloader_" + [guid]::NewGuid().ToString("N"))

# --- WinRAR (нужен для распаковки .rar) ---
$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 "Рабочая папка:  $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 ""

# ============================================================
#  Вспомогательные функции
# ============================================================

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 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"
    $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
}

function Invoke-IndexationUtility {
    param([string]$programName)

    $exeToRun = "CommonComponents.Catalog.IndexationUtility.exe"
    $programsPath = "C:\Program Files (x86)"

    # Пытаемся найти папку программы по известным именам
    $candidates = @("Ais3Prom", "Ais3PredProm", "Ais3FB3OE", "Ais3OEIZ")

    foreach ($installFolder in $candidates) {
        $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) { continue }

        $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 ($finalExe) {
            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
            }
            return
        }
    }

    Write-Host "  Внимание: утилита $exeToRun не найдена ни в одной из папок: $($candidates -join ', ')" -ForegroundColor Yellow
}

# ============================================================
#  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

    # --- Временная папка для распаковки именно этого архива ---
    $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. Имя программы (для поиска/удаления старой версии) ---
    $programNameMap = @{
        "KPE"   = "Клиент АИС Налог-3 Пром версия"
        "PPK"   = "Клиент АИС Налог-3 ПредПром версия"
        "KOE"   = "Клиент АИС Налог-3 ОЭ версия"
        "KOEIZ" = "Клиент АИС Налог-3 ОЭ ИЗ версия"
    }

    $programName = $null
    foreach ($key in $programNameMap.Keys) {
        if ($rar.Name -match [regex]::Escape($key)) {
            $programName = $programNameMap[$key]
            break
        }
    }

    if ($programName) {
        # --- Удаление старой версии ---
        $existingPackage = Find-InstalledProgram -exactName $programName
        if ($existingPackage) {
            Uninstall-Program -displayName $existingPackage.Name -package $existingPackage
        } else {
            Write-Host "  Программа не найдена — будет установлена" -ForegroundColor Green
        }
    } else {
        Write-Host "  Имя программы не определено по имени архива — пропускаем удаление старой версии" -ForegroundColor Yellow
    }

    # --- 4. Установка MSI + процесс индексации ---
    Install-Msi -msiPath $msiFile.FullName -programName $programName

    # --- 5. Запуск утилиты индексации ---
    Invoke-IndexationUtility -programName $programName

    # --- 6. Удаляем ТОЛЬКО временную распаковку ---
    try {
        Remove-Item -Path $extractDir -Recurse -Force -ErrorAction Stop
        Write-Host "  Временная распаковка удалена: $extractDir" -ForegroundColor Gray
    } catch {
        Write-Host "  Не удалось удалить $extractDir : $($_.Exception.Message)" -ForegroundColor Yellow
    }

    # ВАЖНО: $rar не удаляем, $localBasePath не чистим
    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
}