Первоначальная настройка системы

Ниже приведен packages.json файл с содержимым где указано все что требуется для скачивания на новые компьютеры.

packages.json
{
  "packages": [
    {
      "name": "System Tools Pack",
      "url": "https://server/files/tools_pack.zip",
      "desc": "Набор служебных утилит",
      "extract": true,
      "target": "tools"
    },
    {
      "name": "Drivers NVMe",
      "url": "https://server/files/nvme_2024.zip",
      "desc": "Драйверы для NVMe-контроллеров",
      "extract": true
    },
    {
      "name": "Portable Notepad++",
      "url": "https://server/files/npp_portable.zip",
      "desc": "Версия 8.6.4",
      "extract": false
    }
  ]
}

packages.zip

universal_installer.bat
@echo off
rem File: universal_ps1_launcher.bat
rem Purpose: launcher for get_remote_id_check.ps1 (finds pwsh or falls back to Windows PowerShell)
rem Author: takraztak
rem ==================================================
 
setlocal
 
:: try PowerShell 7 (pwsh) in Program Files
set "PS_EXE=%ProgramFiles%\PowerShell\7\pwsh.exe"
if exist "%ProgramFiles(x86)%" (
    if not exist "%PS_EXE%" set "PS_EXE=%ProgramFiles(x86)%\PowerShell\7\pwsh.exe"
)
 
:: fallback to Windows PowerShell if pwsh not found
if not exist "%PS_EXE%" set "PS_EXE=%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe"
 
:: final fallback: rely on PATH (just the name)
if not exist "%PS_EXE%" (
    set "PS_EXE=pwsh.exe"
)
 
:: path to the PowerShell script with the same base name as this .bat
set "PS1=%~dp0%~n0.ps1"
 
:: Quote paths and forward all args
"%PS_EXE%" -NoProfile -ExecutionPolicy Bypass -File "%PS1%" %*
 
endlocal
pause
exit /b
universal_installer.ps1
# file: universal_installer.ps1
# Universal package installer:
# - Downloads packages.zip
# - Extracts packages.json next to the script
# - Displays colored menu
# - Downloads selected ZIP archive
# - Extracts or saves according to JSON rules
 
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
 
# URL of the packages.zip archive
$PackagesZipUrl = "https://as-wiki.ru/_media/support/packages.zip"
$PackagesZip    = Join-Path $ScriptDir "packages.zip"
 
Write-Host "Downloading packages.zip..."
Invoke-WebRequest -Uri $PackagesZipUrl -OutFile $PackagesZip -UseBasicParsing
 
 
# ========== UNPACK packages.zip (RELIABLE METHOD) ==========
Write-Host "Unpacking packages.zip..."
 
Add-Type -AssemblyName System.IO.Compression.FileSystem
 
try {
    # Remove old JSON if exists
    $ExistingJson = Join-Path $ScriptDir "packages.json"
    if (Test-Path $ExistingJson) { Remove-Item $ExistingJson -Force }
 
    # Extract all files directly into script directory
    [System.IO.Compression.ZipFile]::ExtractToDirectory($PackagesZip, $ScriptDir, $true)
}
catch {
    Write-Host "ERROR: Failed to unpack packages.zip" -ForegroundColor Red
    Write-Host $_.Exception.Message -ForegroundColor Yellow
    pause
    exit
}
 
 
# ========== LOAD JSON ==========
$JsonPath = Join-Path $ScriptDir "packages.json"
 
if (-not (Test-Path $JsonPath)) {
    Write-Host "ERROR: packages.json not found inside packages.zip" -ForegroundColor Red
    pause
    exit
}
 
$JsonData = Get-Content $JsonPath -Raw | ConvertFrom-Json
$Packages = $JsonData.packages
 
 
# ========== MENU DISPLAY ==========
function Show-Menu {
    Clear-Host
    Write-Host "=== Package Installer ===`n"
 
    $i = 1
    foreach ($pkg in $Packages) {
 
        $line = "{0} - {1} : {2}" -f $i, $pkg.name, $pkg.desc
 
        if ($i % 2 -eq 0) {
            Write-Host $line -ForegroundColor Gray
        } else {
            Write-Host $line -ForegroundColor White
        }
 
        $i++
    }
 
    Write-Host "`n0, 00 - Exit"
}
 
 
# ========== MAIN LOOP ==========
while ($true) {
    Show-Menu
    $choice = Read-Host "Select number"
 
    if ($choice -eq "0" -or $choice -eq "00") { exit }
 
    if (($choice -as [int]) -lt 1 -or ($choice -as [int]) -gt $Packages.Count) {
        Write-Host "Invalid choice." -ForegroundColor Red
        Start-Sleep 1.5
        continue
    }
 
    $Index = [int]$choice - 1
    $Item  = $Packages[$Index]
 
    Write-Host "`nSelected: $($Item.name)"
 
 
    # ========== DOWNLOAD ARCHIVE ==========
    $FileName = Split-Path $Item.url -Leaf
    $ArchivePath = Join-Path $ScriptDir $FileName
 
    Write-Host "Downloading $FileName..."
    Invoke-WebRequest -Uri $Item.url -OutFile $ArchivePath
 
 
 
    # ========== DETERMINE EXTRACTION TARGET ==========
    if ($Item.target) {
        $Target = Join-Path $ScriptDir $Item.target
    } else {
        $Base = [IO.Path]::GetFileNameWithoutExtension($FileName)
        $Target = Join-Path $ScriptDir $Base
    }
 
    if (-not (Test-Path $Target)) {
        New-Item -ItemType Directory -Path $Target | Out-Null
    }
 
 
    # ========== EXTRACT OR JUST SAVE ==========
    if ($Item.extract -eq $true) {
        Write-Host "Extracting to $Target..."
 
        try {
            Add-Type -AssemblyName System.IO.Compression.FileSystem
            [System.IO.Compression.ZipFile]::ExtractToDirectory($ArchivePath, $Target, $true)
        }
        catch {
            Write-Host "ERROR extracting archive" -ForegroundColor Red
            Write-Host $_.Exception.Message -ForegroundColor Yellow
        }
    }
    else {
        Write-Host "Download complete (no extraction)."
    }
 
    Write-Host "`nDone."
    pause
}