Crmgo Blog

Optymalizacja starego komputera: centrum multimedialne dla TV na Windows 10

Optymalizacja starego komputera: centrum multimedialne dla TV na Windows 10

Jak zoptymalizować Windows 10 na słabym PC (E1-2100, 4 GB, HDD) do oglądania filmów na telewizorze: skrypt Optimize-MoviePC.ps1, rollback przez -Restore i ustawienia przeglądarki.

Optymalizacja starego komputera: centrum multimedialne dla TV na Windows 10

Stary laptop lub jednostka centralna kurzy się bezczynnie? Można go zamienić w prosty centrum multimedialne dla telewizora: filmy, YouTube i serwisy VOD przez HDMI. Główny problem to słaby sprzęt: Windows 10 obciąża procesor, pamięć i dysk zadaniami w tle, a wideo zaczyna się zacinać. W tym artykule omawiamy, jak odchudzić Windows 10 do oglądania filmów za pomocą skryptu PowerShell Optimize-MoviePC.ps1 oraz jak skonfigurować przeglądarkę, aby stary komputer jako centrum multimedialne działał bez zacięć.

Dla kogo jest ten artykuł

Skrypt powstał z myślą o bardzo słabym PC: procesor AMD E1-2100 (2 rdzenie, 1,0 GHz), układ graficzny Radeon HD 8210, 4 GB pamięci RAM i zwykły dysk twardy (HDD). Jeśli masz podobną konfigurację i wideo na YouTube zacina się nawet w niskiej jakości — to jest właśnie twój przypadek. Cel: zachować Wi-Fi, przeglądarkę i odtwarzanie wideo, a wyłączyć wszystko, co działa w tle i powoduje zamarzanie obrazu.

Ważne: skrypt nie był testowany na rzeczywistej maszynie autora artykułu. Działa tylko w Windows 10, wymaga PowerShell 5.1 i uprawnień administratora. Przed uruchomieniem sam tworzy kopie zapasowe, ale stosuj go świadomie i na własne ryzyko.

Co robi skrypt

Najpierw — kopie zapasowe

  • Tworzy punkt przywracania systemu (jeśli Windows na to pozwala).
  • Tworzy folder backup\ obok skryptu: listę stanów usług services-before.csv, eksporty potrzebnych kluczy rejestru (.reg) i dziennik last-run.log.

Usługi

  • Wyłącza telemetrię i diagnostykę (DiagTrack, WerSvc, DPS i in.), drukowanie i faks (Spooler), dostęp zdalny (RDP, RemoteRegistry, WinRM), Xbox, lokalizację, czujniki, karty inteligentne i biometrię, wykrywanie sieci i udostępnianie (SSDP, UPnP, LanmanServer), indeksowanie wyszukiwania (WSearch), SysMain/Superfetch, Hyper-V i wiele działających w tle usług użytkownika.
  • Usługi Windows Update przechodzą w tryb ręczny (nie są wyłączane): powiadomienie przed pobraniem, bez automatycznego restartu przy zalogowanym użytkowniku; Delivery Optimization jest wyłączane.
  • Wymusza pozostawienie włączonych sieci i Wi-Fi, dźwięku (w tym MMCSS), Bluetooth, kluczowych usług Windows i ochrony (Defender, zapora).

Harmonogram zadań, interfejs, reklamy

  • Wyłącza zadania w tle: ocena zgodności, CEIP, opinie, mapy, raporty o błędach, WinSAT, kontrola rodzicielska itp.
  • Efekty wizualne — „najlepsza wydajność": bez animacji, przezroczystości i Aero Peek (ClearType zostaje zachowany). Wyłącza powiadomienia i „Wiadomości i zainteresowania".
  • Wyłącza podpowiedzi, reklamowy identyfikator, Bing/Cortana w wyszukiwaniu, telemetrię, os czasu i Game DVR.

Pamięć, dysk, zasilanie

  • Wyłącza kompresję pamięci i łączenie stron, prefetch/superfetch; ustawia stały plik wymiany 6 GB (4 GB przy braku miejsca); wyłącza hibernację i szybkie uruchamianie.
  • Włącza plan „Wysoka wydajność": bez uśpienia i wyłączania dysku, procesor 100%, karta Wi-Fi na maksymalnej wydajności, bez wybiórczego wstrzymywania USB; monitor gaśnie po 20 minutach (z zasilania sieciowego).
  • Podnosi priorytet multimediów (MMCSS) dla dźwięku i odtwarzania.

Autostart i Defender

  • Wpisy autostartu są oznaczane jako wyłączone (nie usuwane), skróty z folderu „Autostart" są przenoszone do backup\startup-shortcuts. OneDrive jest zatrzymywany, synchronizacja wyłączana polityką — pliki nie są usuwane.
  • Defender pozostaje włączony, ale z niskim priorytetem (obciążenie podczas skanowania 5%); do wyjątków dodawane są tylko foldery pamięci podręcznej przeglądarek.

Na końcu skrypt pokazuje podsumowanie, przypomina o restarcie, radzi raz w miesiącu uruchamiać defrag C: /O i podaje zalecenia dotyczące przeglądarki.

Czego skrypt NIE rusza

  • Twoich dokumentów, zdjęć, pobranych plików i profili przeglądarek.
  • Sterowników, Windows Defender i zapory.
  • Wi-Fi, DHCP, DNS, dźwięku i Bluetooth.
  • Windows Update (tylko przełącza w tryb ręczny), usługi defragmentacji, RunOnce.
  • Nie usuwa wartości rejestru i nigdy sam nie restartuje komputera.

Jak uruchomić: krok po kroku

  1. Umieść Optimize-MoviePC.ps1 w osobnym folderze. Podwójne kliknięcie pliku nie zadziała.
  2. Otwórz Windows PowerShell jako administrator (Start → prawy klik na PowerShell → „Uruchom jako administrator").
  3. Zezwól na uruchamianie skryptów tylko dla bieżącego okna:
    Set-ExecutionPolicy -Scope Process Bypass -Force
  4. Przejdź do folderu ze skryptem (jeśli w ścieżce są spacje — ujmij ją w cudzysłów):
    cd "C:\ścieżka\do\folderu"
  5. Uruchom:
    .\Optimize-MoviePC.ps1
  6. Poczekaj na podsumowanie i zrestartuj komputer, gdy nie oglądasz filmu.

⬇ Pobierz Optimize-MoviePC.ps1

Pokaż pełny kod skryptu Optimize-MoviePC.ps1
#Requires -Version 5.1
# =============================================================================
# RUN AS ADMINISTRATOR.
# Запускать от имени администратора.
#
# Правый клик по «Windows PowerShell» -> «Запуск от имени администратора», затем:
#   Set-ExecutionPolicy -Scope Process Bypass -Force
#   cd C:\путь\к\папке
#   .\Optimize-MoviePC.ps1
#
# Откат типов запуска служб и сохранённых веток реестра:
#   .\Optimize-MoviePC.ps1 -Restore
#
# Для чего скрипт
#   Слабый ПК: AMD E1-2100 (2 ядра, 1,0 ГГц, Radeon HD 8210), 4 ГБ RAM, HDD.
#   Нужны только Wi-Fi, браузер и воспроизведение видео.
#
# Чего скрипт НЕ делает
#   - не удаляет документы, фото, загрузки, папку OneDrive и профили браузера;
#   - не трогает драйверы (AMD, Realtek, Wi-Fi и любые другие);
#   - не отключает службы, которых нет в списках ниже;
#   - не отключает Защитник Windows и брандмауэр;
#   - не выключает Wi-Fi, DHCP, DNS, звук и планировщик мультимедиа;
#   - не перезагружает компьютер сам.
#
# Запускайте из той учётной записи, которой смотрите кино, и эта учётка должна
# быть администратором. Иначе личные настройки рабочего стола попадут не в тот профиль.
# Службы (они общие для всего ПК) настраиваются в любом случае.
#
# После выполнения нужна обычная перезагрузка, когда фильм не идёт.
# Рекомендация по браузеру — в конце этого файла и в browser-recommendation.txt.
# =============================================================================

param(
    [switch]$Restore
)

$ErrorActionPreference = "Continue"

if (-not $PSScriptRoot) {
    $PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
}

# Имена автозагрузки, которые нельзя гасить: обновления браузера и значок защиты.
$script:StartupKeepPattern = "(?i)(SecurityHealth|WindowsDefender|Windows Defender|Defender|update|updater|Maintenance|MozillaMaintenance)"

$script:DisabledOk = 0
$script:DisabledFail = 0

function Test-IsAdministrator {
    $identity = [Security.Principal.WindowsIdentity]::GetCurrent()
    $principal = New-Object Security.Principal.WindowsPrincipal($identity)
    return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}

function Set-ServiceStartupSafe {
    param(
        [Parameter(Mandatory = $true)][string]$Name,
        [Parameter(Mandatory = $true)][ValidateSet("Automatic", "Manual", "Disabled", "Boot", "System")][string]$StartupType
    )
    try {
        Set-Service -Name $Name -StartupType $StartupType -ErrorAction Stop
        return $true
    }
    catch {
        $map = @{
            Automatic = "auto"
            Manual    = "demand"
            Disabled  = "disabled"
            Boot      = "boot"
            System    = "system"
        }
        & sc.exe config $Name start= $map[$StartupType] | Out-Null
        if ($LASTEXITCODE -eq 0) {
            return $true
        }
        Write-Warning "  Не удалось сменить тип запуска ${Name}: $($_.Exception.Message)"
        return $false
    }
}

function Disable-ExtraService {
    param([Parameter(Mandatory = $true)][string]$Name)

    $found = @(Get-Service -Name $Name -ErrorAction SilentlyContinue | Where-Object { $_ })
    if ($found.Count -eq 0) {
        Write-Host "  [нет такой службы] $Name" -ForegroundColor DarkGray
        return
    }

    foreach ($svc in $found) {
        try {
            if ($svc.Status -ne "Stopped") {
                Stop-Service -Name $svc.Name -Force -ErrorAction SilentlyContinue
            }
            if (Set-ServiceStartupSafe -Name $svc.Name -StartupType Disabled) {
                $script:DisabledOk++
                Write-Host "  [выкл] $($svc.Name)" -ForegroundColor Green
            }
            else {
                $script:DisabledFail++
            }
        }
        catch {
            $script:DisabledFail++
            Write-Warning "  $($svc.Name): $($_.Exception.Message)"
        }
    }
}

function Repair-ServiceIfDisabled {
    param(
        [Parameter(Mandatory = $true)][string]$Name,
        [ValidateSet("Automatic", "Manual")][string]$StartupType = "Automatic",
        [switch]$Start
    )

    try {
        $svc = Get-Service -Name $Name -ErrorAction SilentlyContinue
        if (-not $svc) {
            Write-Host "  [нет такой службы] $Name" -ForegroundColor DarkGray
            return
        }

        if ($svc.StartType -eq "Disabled") {
            if (Set-ServiceStartupSafe -Name $Name -StartupType $StartupType) {
                Write-Host "  [восстановлено] $Name была выключена -> $StartupType" -ForegroundColor Yellow
            }
        }
        else {
            Write-Host "  [оставляем] $Name ($($svc.StartType))" -ForegroundColor Cyan
        }

        if ($Start) {
            $svc = Get-Service -Name $Name -ErrorAction SilentlyContinue
            if ($svc -and $svc.Status -ne "Running" -and $svc.StartType -ne "Disabled") {
                & sc.exe start $Name | Out-Null
                if ($LASTEXITCODE -eq 0 -or $LASTEXITCODE -eq 1056) {
                    Write-Host "  [запуск] $Name" -ForegroundColor Cyan
                }
                else {
                    Write-Warning "  Служба $Name не запустилась (код $LASTEXITCODE). После перезагрузки проверьте звук и Wi-Fi."
                }
            }
        }
    }
    catch {
        Write-Warning "  $Name : $($_.Exception.Message)"
    }
}

function Set-ManualService {
    param([Parameter(Mandatory = $true)][string]$Name)
    $svc = Get-Service -Name $Name -ErrorAction SilentlyContinue
    if (-not $svc) {
        Write-Host "  [нет такой службы] $Name" -ForegroundColor DarkGray
        return
    }
    if (Set-ServiceStartupSafe -Name $Name -StartupType Manual) {
        Write-Host "  [вручную] $Name" -ForegroundColor Green
    }
}

function Set-RegDword {
    param(
        [Parameter(Mandatory = $true)][string]$Path,
        [Parameter(Mandatory = $true)][string]$Name,
        [Parameter(Mandatory = $true)][int]$Value
    )
    if (-not (Test-Path -LiteralPath $Path)) {
        New-Item -Path $Path -Force | Out-Null
    }
    New-ItemProperty -LiteralPath $Path -Name $Name -Value $Value -PropertyType DWord -Force | Out-Null
}

function Set-RegString {
    param(
        [Parameter(Mandatory = $true)][string]$Path,
        [Parameter(Mandatory = $true)][string]$Name,
        [Parameter(Mandatory = $true)][string]$Value
    )
    if (-not (Test-Path -LiteralPath $Path)) {
        New-Item -Path $Path -Force | Out-Null
    }
    New-ItemProperty -LiteralPath $Path -Name $Name -Value $Value -PropertyType String -Force | Out-Null
}

function Export-RegKey {
    param(
        [Parameter(Mandatory = $true)][string]$Key,
        [Parameter(Mandatory = $true)][string]$File
    )
    $full = Join-Path $script:BackupDir $File
    & reg.exe export $Key $full /y 2>&1 | Out-Null
    if ($LASTEXITCODE -eq 0) {
        Write-Host "  [копия реестра] $Key" -ForegroundColor DarkGray
    }
}

function Disable-StartupRunKey {
    param(
        [Parameter(Mandatory = $true)][string]$RunKey,
        [Parameter(Mandatory = $true)][string]$ApprovedKey
    )
    if (-not (Test-Path -LiteralPath $RunKey)) {
        return
    }
    if (-not (Test-Path -LiteralPath $ApprovedKey)) {
        New-Item -Path $ApprovedKey -Force | Out-Null
    }

    $item = Get-Item -LiteralPath $RunKey
    foreach ($valueName in @($item.GetValueNames())) {
        if ([string]::IsNullOrWhiteSpace($valueName)) {
            continue
        }
        if ($valueName -match $script:StartupKeepPattern) {
            Write-Host "  [автозагрузка оставлена] $valueName" -ForegroundColor Cyan
            continue
        }
        # 0x03 в первом байте — «Отключено» в диспетчере задач. Саму команду не удаляем.
        $disabled = [byte[]](0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
        New-ItemProperty -LiteralPath $ApprovedKey -Name $valueName -Value $disabled -PropertyType Binary -Force | Out-Null
        Write-Host "  [автозагрузка выкл] $valueName" -ForegroundColor Green
    }
}

function Suspend-StartupFolder {
    param(
        [Parameter(Mandatory = $true)][string]$SourceFolder,
        [Parameter(Mandatory = $true)][string]$BackupFolder
    )
    if (-not (Test-Path -LiteralPath $SourceFolder)) {
        return
    }
    New-Item -ItemType Directory -Path $BackupFolder -Force | Out-Null
    Get-ChildItem -LiteralPath $SourceFolder -Force | Where-Object { -not $_.PSIsContainer } | ForEach-Object {
        if ($_.Name -eq "desktop.ini") {
            return
        }
        if ($_.Name -match $script:StartupKeepPattern) {
            Write-Host "  [папка автозагрузки оставлена] $($_.Name)" -ForegroundColor Cyan
            return
        }
        Move-Item -LiteralPath $_.FullName -Destination (Join-Path $BackupFolder $_.Name) -Force
        Write-Host "  [ярлык убран в backup] $($_.Name)" -ForegroundColor Green
    }
}

function Restore-StartupFolder {
    param(
        [Parameter(Mandatory = $true)][string]$BackupFolder,
        [Parameter(Mandatory = $true)][string]$SourceFolder
    )
    if (-not (Test-Path -LiteralPath $BackupFolder)) {
        return
    }
    if (-not (Test-Path -LiteralPath $SourceFolder)) {
        New-Item -ItemType Directory -Path $SourceFolder -Force | Out-Null
    }
    Get-ChildItem -LiteralPath $BackupFolder -Force | Where-Object { -not $_.PSIsContainer } | ForEach-Object {
        $dest = Join-Path $SourceFolder $_.Name
        if (Test-Path -LiteralPath $dest) {
            Write-Host "  [ярлык уже на месте] $($_.Name)" -ForegroundColor DarkGray
            return
        }
        Move-Item -LiteralPath $_.FullName -Destination $dest
        Write-Host "  [ярлык возвращён] $($_.Name)" -ForegroundColor Green
    }
}

function Invoke-Restore {
    $backup = Join-Path $PSScriptRoot "backup"
    if (-not (Test-Path -LiteralPath $backup)) {
        Write-Host "Папка backup не найдена. Откатывать нечего." -ForegroundColor Yellow
        Write-Host "Если точка восстановления создалась, откройте: Панель управления -> Восстановление -> Запуск восстановления системы."
        return
    }

    Write-Host "Возвращаем типы запуска служб из backup\services-before.csv ..." -ForegroundColor Cyan
    $csv = Join-Path $backup "services-before.csv"
    if (Test-Path -LiteralPath $csv) {
        $rows = Import-Csv -LiteralPath $csv
        foreach ($row in $rows) {
            $type = switch ($row.StartMode) {
                "Auto" { "Automatic" }
                "Manual" { "Manual" }
                "Disabled" { "Disabled" }
                "Boot" { "Boot" }
                "System" { "System" }
                default { $null }
            }
            if (-not $type -or [string]::IsNullOrWhiteSpace($row.Name)) {
                continue
            }
            if (Set-ServiceStartupSafe -Name $row.Name -StartupType $type) {
                Write-Host "  [служба] $($row.Name) -> $type" -ForegroundColor DarkGray
            }
        }
    }
    else {
        Write-Warning "Файл services-before.csv не найден. Типы запуска служб не восстановлены."
    }

    Write-Host "Возвращаем сохранённые ветки реестра ..." -ForegroundColor Cyan
    Get-ChildItem -LiteralPath $backup -Filter "*.reg" -ErrorAction SilentlyContinue | ForEach-Object {
        & reg.exe import $_.FullName | Out-Null
        if ($LASTEXITCODE -eq 0) {
            Write-Host "  [реестр] $($_.Name)" -ForegroundColor DarkGray
        }
        else {
            Write-Warning "  Не удалось импортировать $($_.Name)"
        }
    }

    $userStartup = [Environment]::GetFolderPath("Startup")
    $commonStartup = Join-Path $env:ProgramData "Microsoft\Windows\Start Menu\Programs\Startup"
    Restore-StartupFolder -BackupFolder (Join-Path $backup "startup-shortcuts\user") -SourceFolder $userStartup
    Restore-StartupFolder -BackupFolder (Join-Path $backup "startup-shortcuts\common") -SourceFolder $commonStartup

    Write-Host ""
    Write-Host "Откат служб, реестра и ярлыков автозагрузки выполнен." -ForegroundColor Green
    Write-Host "Сжатие памяти этим откатом не включается. Если нужно вернуть его:" -ForegroundColor Yellow
    Write-Host "  Enable-MMAgent -MemoryCompression -PageCombining"
    Write-Host "Гибернация этим откатом не включается. Если нужно вернуть её: powercfg -h on"
    Write-Host "Перезагрузите компьютер."
}

function Set-FixedPageFile {
    # Фиксированный файл подкачки не разрастается посреди фильма.
    # Рост pagefile.sys на HDD — это длинная пауза картинки.
    # Размер не больше 6144 МБ: на почти полном диске файл не трогаем.
    $mmPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management"
    $pageName = "$env:SystemDrive\pagefile.sys"

    $freeMb = 0
    $disk = Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='$env:SystemDrive'" -ErrorAction SilentlyContinue
    if ($disk) {
        $freeMb = [int64]($disk.FreeSpace / 1MB)
    }

    $existingMb = 0
    $settingsPreview = @(Get-CimInstance Win32_PageFileSetting -ErrorAction SilentlyContinue | Where-Object { $_ })
    foreach ($entry in $settingsPreview) {
        $current = 0
        if ($entry.InitialSize) { $current = [int]$entry.InitialSize }
        if ($current -gt $existingMb) { $existingMb = $current }
    }

    $targetMb = 0
    $growTo6144 = 6144 - $existingMb
    if ($growTo6144 -lt 0) { $growTo6144 = 0 }
    $growTo4096 = 4096 - $existingMb
    if ($growTo4096 -lt 0) { $growTo4096 = 0 }

    if ($freeMb -ge ($growTo6144 + 2048)) {
        $targetMb = 6144
    }
    elseif ($freeMb -ge ($growTo4096 + 1536)) {
        $targetMb = 4096
    }
    elseif ($existingMb -ge 2048 -and $existingMb -le 6144) {
        $targetMb = $existingMb
        Write-Host "  Мало свободного места ($freeMb МБ). Фиксируем уже существующий файл подкачки: $targetMb МБ." -ForegroundColor Yellow
    }
    else {
        Write-Warning "  На диске $($env:SystemDrive) свободно около $freeMb МБ. Файл подкачки не меняем, чтобы не забить диск."
        return
    }

    $pageSpec = "$pageName $targetMb $targetMb"
    $previousAuto = $true
    $previousFiles = $null
    try {
        $previousFiles = (Get-ItemProperty -LiteralPath $mmPath -Name PagingFiles -ErrorAction SilentlyContinue).PagingFiles
        $cs = Get-CimInstance Win32_ComputerSystem
        $previousAuto = [bool]$cs.AutomaticManagedPagefile

        if ($previousAuto) {
            Set-CimInstance -InputObject $cs -Property @{ AutomaticManagedPagefile = $false } -ErrorAction Stop
        }

        $settings = @(Get-CimInstance Win32_PageFileSetting -ErrorAction SilentlyContinue | Where-Object { $_ })
        $match = $settings | Where-Object { $_.Name -eq $pageName } | Select-Object -First 1
        if ($match) {
            Set-CimInstance -InputObject $match -Property @{ InitialSize = $targetMb; MaximumSize = $targetMb } -ErrorAction Stop
        }
        else {
            Set-WmiInstance -Class Win32_PageFileSetting -Arguments @{
                Name        = $pageName
                InitialSize = $targetMb
                MaximumSize = $targetMb
            } -ErrorAction Stop | Out-Null
        }

        New-ItemProperty -LiteralPath $mmPath -Name PagingFiles -Value @($pageSpec) -PropertyType MultiString -Force | Out-Null
        New-ItemProperty -LiteralPath $mmPath -Name ClearPageFileAtShutdown -Value 0 -PropertyType DWord -Force | Out-Null
        Write-Host "  [ок] Файл подкачки зафиксирован: $targetMb МБ на $pageName (после перезагрузки)." -ForegroundColor Green
    }
    catch {
        Write-Warning "  Файл подкачки оставлен как был: $($_.Exception.Message)"
        try {
            if ($null -ne $previousFiles) {
                New-ItemProperty -LiteralPath $mmPath -Name PagingFiles -Value $previousFiles -PropertyType MultiString -Force | Out-Null
            }
            if ($previousAuto) {
                $cs2 = Get-CimInstance Win32_ComputerSystem
                Set-CimInstance -InputObject $cs2 -Property @{ AutomaticManagedPagefile = $true } -ErrorAction SilentlyContinue
            }
        }
        catch {
            Write-Warning "  Не удалось автоматически вернуть прежний файл подкачки. После перезагрузки откройте: Система -> Дополнительно -> Быстродействие -> Дополнительно -> Виртуальная память."
        }
    }
}

function Protect-NeededServices {
    Write-Host ""
    Write-Host "Нужные службы (если какая-то была выключена раньше — включаем обратно)" -ForegroundColor Cyan

    # Сеть и Wi-Fi. Без этого браузер не откроет страницу.
    @(
        "WlanSvc",   # WLAN AutoConfig — сам Wi-Fi
        "Wcmsvc",    # диспетчер подключений
        "Dhcp",      # адрес от роутера
        "Dnscache",  # DNS-клиент
        "NlaSvc",    # определяет, что сеть есть
        "nsi",       # сетевой стек, от него зависит DHCP
        "netprofm",  # профили сетей
        "Netman",
        "NcbService",
        "EventSystem"
    ) | ForEach-Object {
        Repair-ServiceIfDisabled -Name $_ -StartupType Automatic -Start
    }

    # Эти службы обычно сами стартуют по запросу. Главное — не держать их в «Отключена».
    @(
        "WinHttpAutoProxySvc", # автонастройка прокси, её спрашивают браузеры
        "VaultSvc",            # сохранённые пароли Wi-Fi
        "RmSvc",               # радиоадаптер, режим полёта
        "Eaphost",             # WPA-Enterprise / 802.1X, если такая сеть
        "NetSetupSvc",
        "QWAVE"                # служба качества аудио/видео, по требованию
    ) | ForEach-Object {
        Repair-ServiceIfDisabled -Name $_ -StartupType Manual
    }

    # Звук и планировщик мультимедиа. Без них ролик будет немой или дёрганый.
    @(
        "Audiosrv",
        "AudioEndpointBuilder",
        "MMCSS"
    ) | ForEach-Object {
        Repair-ServiceIfDisabled -Name $_ -StartupType Automatic -Start
    }

    # Bluetooth оставляем: часто кино смотрят в беспроводных наушниках.
    Repair-ServiceIfDisabled -Name "bthserv" -StartupType Automatic -Start
    @(
        "BTAGService",
        "BthAvctpSvc",
        "DeviceAssociationService"
    ) | ForEach-Object {
        Repair-ServiceIfDisabled -Name $_ -StartupType Manual
    }

    # Каркас Windows. Эти службы не оптимизируют отключением — без них система неживая.
    @(
        "RpcSs",
        "DcomLaunch",
        "RpcEptMapper",
        "LSM",
        "SamSs",
        "ProfSvc",
        "UserManager",
        "Power",
        "PlugPlay",
        "Winmgmt",
        "EventLog",
        "Schedule",
        "SystemEventsBroker",
        "gpsvc",
        "CoreMessagingRegistrar",
        "BrokerInfrastructure",
        "StateRepository",
        "TextInputManagementService",
        "Appinfo",
        "ShellHWDetection",
        "FontCache",
        "Themes",
        "CryptSvc",
        "KeyIso",
        "camsvc",
        "StorSvc",
        "sppsvc",
        "AppXSvc",
        "ClipSVC",
        "TokenBroker",
        "TimeBrokerSvc",
        "msiserver",
        "TrustedInstaller",
        "VSS",
        "swprv",
        "defragsvc",
        "W32Time",
        "DsmSvc",
        "hidserv"
    ) | ForEach-Object {
        $startType = "Automatic"
        if ($_ -in @("KeyIso", "camsvc", "StorSvc", "AppXSvc", "ClipSVC", "TokenBroker", "TimeBrokerSvc", "msiserver", "TrustedInstaller", "VSS", "swprv", "defragsvc", "W32Time", "DsmSvc", "hidserv")) {
            $startType = "Manual"
        }
        Repair-ServiceIfDisabled -Name $_ -StartupType $startType
    }

    # Защита интернет-сессии. На слабом ПК она стоит ресурсов, но без неё смотреть кино в браузере рискованно.
    @(
        "WinDefend",
        "WdNisSvc",
        "SecurityHealthService",
        "wscsvc",
        "BFE",
        "mpssvc"
    ) | ForEach-Object {
        Repair-ServiceIfDisabled -Name $_ -StartupType Automatic -Start
    }
}

# --- Проверка прав -----------------------------------------------------------
if ($env:OS -ne "Windows_NT") {
    Write-Host "Этот скрипт предназначен только для Windows 10. Здесь он ничего не меняет." -ForegroundColor Red
    exit 1
}

if (-not (Test-IsAdministrator)) {
    Write-Host "Скрипт не запущен от имени администратора." -ForegroundColor Red
    Write-Host "Откройте PowerShell через «Запуск от имени администратора» и выполните:"
    Write-Host "  Set-ExecutionPolicy -Scope Process Bypass -Force"
    Write-Host "  & '$PSCommandPath'"
    exit 1
}

if ($Restore) {
    Invoke-Restore
    exit 0
}

$script:BackupDir = Join-Path $PSScriptRoot "backup"
New-Item -ItemType Directory -Path $script:BackupDir -Force | Out-Null
try {
    Start-Transcript -LiteralPath (Join-Path $script:BackupDir "last-run.log") -Force | Out-Null
}
catch {
    Write-Warning "Журнал транскрипта не включился: $($_.Exception.Message)"
}

try {
    Write-Host "Оптимизация Windows 10 для кино в браузере." -ForegroundColor White
    Write-Host "Процессор E1-2100, 4 ГБ RAM, жёсткий диск. Лишние службы будут выключены." -ForegroundColor White

    try {
        $explorer = Get-CimInstance Win32_Process -Filter "Name = 'explorer.exe'" -ErrorAction SilentlyContinue | Select-Object -First 1
        if ($explorer) {
            $ownerInfo = Invoke-CimMethod -InputObject $explorer -MethodName GetOwner
            $loggedOn = "$($ownerInfo.Domain)\$($ownerInfo.User)"
            $current = "$env:USERDOMAIN\$env:USERNAME"
            if ($loggedOn -and $current -and ($loggedOn -ne $current)) {
                Write-Warning "PowerShell работает как $current, а в систему вошёл $loggedOn."
                Write-Warning "Настройки рабочего стола попадут в профиль $current. Службы всё равно изменятся для всего ПК."
            }
        }
    }
    catch {
        Write-Warning "Не удалось сравнить текущего пользователя и вошедшего в систему."
    }

    # --- Точка восстановления и резервные копии ------------------------------
    # Сначала сохраняем состояние. Если картина после перезагрузки не устроит,
    # запустите скрипт с ключом -Restore или откатите точку в «Восстановлении системы».
    Write-Host ""
    Write-Host "Резервные копии" -ForegroundColor Cyan
    try {
        $srKey = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRestore"
        if (-not (Test-Path -LiteralPath $srKey)) {
            New-Item -Path $srKey -Force | Out-Null
        }
        New-ItemProperty -LiteralPath $srKey -Name "SystemRestorePointCreationFrequency" -Value 0 -PropertyType DWord -Force | Out-Null
        Enable-ComputerRestore -Drive "$env:SystemDrive\" -ErrorAction SilentlyContinue
        Checkpoint-Computer -Description "Optimize-MoviePC before changes" -RestorePointType MODIFY_SETTINGS -ErrorAction Stop
        Write-Host "  [ок] Точка восстановления создана." -ForegroundColor Green
    }
    catch {
        Write-Warning "  Точка восстановления не создана: $($_.Exception.Message)"
        Write-Warning "  Продолжаем. Откат служб всё равно будет в папке backup."
    }

    try {
        Get-CimInstance Win32_Service |
            Select-Object Name, StartMode, State, DisplayName |
            Export-Csv -LiteralPath (Join-Path $script:BackupDir "services-before.csv") -NoTypeInformation -Encoding UTF8
        Write-Host "  [ок] Список служб сохранён в backup\services-before.csv" -ForegroundColor Green
    }
    catch {
        Write-Warning "  Не удалось сохранить список служб: $($_.Exception.Message)"
    }

    @(
        @{ Key = "HKCU\Control Panel\Desktop"; File = "hkcu-desktop.reg" },
        @{ Key = "HKCU\Control Panel\Desktop\WindowMetrics"; File = "hkcu-windowmetrics.reg" },
        @{ Key = "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer"; File = "hkcu-explorer.reg" },
        @{ Key = "HKCU\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"; File = "hkcu-personalize.reg" },
        @{ Key = "HKCU\Software\Microsoft\Windows\CurrentVersion\GameDVR"; File = "hkcu-gamedvr.reg" },
        @{ Key = "HKCU\Software\Microsoft\Windows\CurrentVersion\PushNotifications"; File = "hkcu-toasts.reg" },
        @{ Key = "HKCU\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager"; File = "hkcu-content.reg" },
        @{ Key = "HKCU\Software\Microsoft\Windows\CurrentVersion\Search"; File = "hkcu-search.reg" },
        @{ Key = "HKCU\Software\Microsoft\Windows\CurrentVersion\BackgroundAccessApplications"; File = "hkcu-background.reg" },
        @{ Key = "HKCU\Software\Microsoft\Windows\CurrentVersion\AdvertisingInfo"; File = "hkcu-advertising.reg" },
        @{ Key = "HKCU\Software\Microsoft\Windows\CurrentVersion\Run"; File = "hkcu-run.reg" },
        @{ Key = "HKCU\Software\Microsoft\Windows\DWM"; File = "hkcu-dwm.reg" },
        @{ Key = "HKCU\Software\Microsoft\Windows\CurrentVersion\Feeds"; File = "hkcu-feeds.reg" },
        @{ Key = "HKCU\System\GameConfigStore"; File = "hkcu-gameconfig.reg" },
        @{ Key = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"; File = "hklm-run.reg" },
        @{ Key = "HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run"; File = "hklm-run32.reg" },
        @{ Key = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved"; File = "hklm-startupapproved.reg" },
        @{ Key = "HKLM\SOFTWARE\Policies\Microsoft\Windows\DataCollection"; File = "hklm-datacollection.reg" },
        @{ Key = "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate"; File = "hklm-windowsupdate.reg" },
        @{ Key = "HKLM\SOFTWARE\Policies\Microsoft\Windows\GameDVR"; File = "hklm-gamedvr.reg" },
        @{ Key = "HKLM\SOFTWARE\Policies\Microsoft\Windows\OneDrive"; File = "hklm-onedrive.reg" },
        @{ Key = "HKLM\SOFTWARE\Policies\Microsoft\Windows\Windows Search"; File = "hklm-windowssearch.reg" },
        @{ Key = "HKLM\SOFTWARE\Policies\Microsoft\Windows\CloudContent"; File = "hklm-cloudcontent.reg" },
        @{ Key = "HKLM\SOFTWARE\Policies\Microsoft\Windows\AppCompat"; File = "hklm-appcompat.reg" },
        @{ Key = "HKLM\SOFTWARE\Policies\Microsoft\Windows\System"; File = "hklm-systempolicy.reg" },
        @{ Key = "HKLM\SOFTWARE\Policies\Microsoft\Windows\DeliveryOptimization"; File = "hklm-deliveryopt.reg" },
        @{ Key = "HKLM\SOFTWARE\Policies\Microsoft\SQMClient\Windows"; File = "hklm-ceip.reg" },
        @{ Key = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Multimedia\SystemProfile"; File = "hklm-mmcss.reg" },
        @{ Key = "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management"; File = "hklm-memory.reg" },
        @{ Key = "HKLM\SYSTEM\CurrentControlSet\Control\PriorityControl"; File = "hklm-priority.reg" },
        @{ Key = "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Power"; File = "hklm-power.reg" },
        @{ Key = "HKLM\SYSTEM\CurrentControlSet\Control\GraphicsDrivers"; File = "hklm-graphics.reg" }
    ) | ForEach-Object {
        Export-RegKey -Key $_.Key -File $_.File
    }

    # --- Службы, которые должны работать -------------------------------------
    Protect-NeededServices

    # --- Телеметрия и диагностика --------------------------------------------
    # Эти службы собирают статистику и пишут на диск. К Wi-Fi и видео они не нужны,
    # а на HDD как раз они часто дают фоновую нагрузку.
    Write-Host ""
    Write-Host "Телеметрия и диагностика" -ForegroundColor Cyan
    @(
        "DiagTrack",
        "dmwappushservice",
        "diagnosticshub.standardcollector.service",
        "WerSvc",
        "wercplsupport",
        "WdiServiceHost",
        "WdiSystemHost",
        "DPS",
        "PcaSvc",
        "diagsvc",
        "pla",
        "wmiApSrv"
    ) | ForEach-Object { Disable-ExtraService -Name $_ }

    # --- Печать и факс -------------------------------------------------------
    # Для кино принтер не нужен. Если позже понадобится печать или «печать в PDF»,
    # верните службу Spooler: services.msc -> тип запуска «Автоматически».
    Write-Host ""
    Write-Host "Печать и факс" -ForegroundColor Cyan
    @(
        "Spooler",
        "PrintNotify",
        "Fax",
        "PrintWorkflowUserSvc_*",
        "StiSvc",
        "WiaRpc"
    ) | ForEach-Object { Disable-ExtraService -Name $_ }

    # --- Удалённый доступ ----------------------------------------------------
    # Удалённый рабочий стол, помощь и VPN-сервер этому ПК не нужны.
    # Обычный домашний Wi-Fi от этого не зависит (Eaphost для сетей предприятия оставлен).
    Write-Host ""
    Write-Host "Удалённый доступ" -ForegroundColor Cyan
    @(
        "RemoteAccess",
        "RemoteRegistry",
        "RasAuto",
        "RasMan",
        "SessionEnv",
        "TermService",
        "UmRdpService",
        "RpcLocator",
        "WinRM",
        "SharedAccess",
        "icssvc",
        "SstpSvc",
        "IKEEXT",
        "PolicyAgent",
        "seclogon",
        "ssh-agent"
    ) | ForEach-Object { Disable-ExtraService -Name $_ }

    # --- Xbox, игры, смешанная реальность ------------------------------------
    Write-Host ""
    Write-Host "Xbox и игровые фоновые службы" -ForegroundColor Cyan
    @(
        "XblAuthManager",
        "XblGameSave",
        "XboxGipSvc",
        "XboxNetApiSvc",
        "BcastDVRUserService_*"
    ) | ForEach-Object { Disable-ExtraService -Name $_ }

    # --- Геолокация, датчики, лишние устройства ------------------------------
    Write-Host ""
    Write-Host "Геолокация, датчики, смарт-карты" -ForegroundColor Cyan
    @(
        "lfsvc",
        "MapsBroker",
        "SensorDataService",
        "SensorService",
        "SensrSvc",
        "RetailDemo",
        "WbioSrvc",
        "SCardSvr",
        "SCPolicySvc",
        "ScDeviceEnum",
        "CertPropSvc",
        "NaturalAuthentication",
        "NgcSvc",
        "NgcCtnrSvc",
        "TabletInputService",
        "FrameServer",
        "WwanSvc"
    ) | ForEach-Object { Disable-ExtraService -Name $_ }

    # --- Обнаружение сети и раздача папок ------------------------------------
    # Браузеру нужен интернет, а не общие папки, UPnP и сетевое обнаружение.
    # Клиент SMB (LanmanWorkstation) оставлен в ручном режиме ниже: сеть Windows
    # иногда сама его вызывает, и жёсткое отключение ломает некоторые окна системы.
    Write-Host ""
    Write-Host "Сетевое обнаружение и общие ресурсы" -ForegroundColor Cyan
    @(
        "SSDPSRV",
        "upnphost",
        "fdPHost",
        "FDResPub",
        "lltdsvc",
        "LanmanServer",
        "TrkWks",
        "WebClient",
        "Netlogon",
        "WMPNetworkSvc",
        "wcncsvc",
        "Wecsvc",
        "SNMPTRAP",
        "p2pimsvc",
        "p2psvc",
        "PNRPsvc",
        "PNRPAutoReg",
        "PeerDistSvc",
        "NetTcpPortSharing",
        "NcdAutoSetup",
        "CscService"
    ) | ForEach-Object { Disable-ExtraService -Name $_ }

    Set-ManualService -Name "LanmanWorkstation"
    Set-ManualService -Name "dot3svc"
    Set-ManualService -Name "iphlpsvc"
    Set-ManualService -Name "lmhosts"

    # --- Поиск и Superfetch --------------------------------------------------
    # На HDD это главные источники ступора. Индексация и Superfetch читают диск
    # в случайных местах ровно тогда, когда браузер пишет кэш и файл подкачки.
    # Загрузка станет чуть дольше, воспроизведение — ровнее.
    # Плановая дефрагментация (defragsvc) НЕ отключается: жёсткому диску она нужна,
    # но пусть идёт по расписанию, а не во время фильма.
    Write-Host ""
    Write-Host "Индексация и Superfetch" -ForegroundColor Cyan
    @(
        "WSearch",
        "SysMain"
    ) | ForEach-Object { Disable-ExtraService -Name $_ }

    # --- Фоновые службы пользователя -----------------------------------------
    # Контакты, визитки, буфер обмена между устройствами, всплывающие советы.
    # К ролику в браузере отношения не имеют. Bluetooth-службы пользователя не трогаем.
    Write-Host ""
    Write-Host "Фоновые пользовательские службы" -ForegroundColor Cyan
    @(
        "CDPSvc",
        "CDPUserSvc_*",
        "WpnService",
        "WpnUserSvc_*",
        "MessagingService_*",
        "PimIndexMaintenanceSvc_*",
        "OneSyncSvc_*",
        "DevicesFlowUserSvc_*",
        "DevicePickerUserSvc_*",
        "CaptureService_*",
        "ConsentUxUserSvc_*",
        "cbdhsvc_*",
        "CredentialEnrollmentManagerUserSvc_*",
        "UnistoreSvc_*",
        "UserDataSvc_*",
        "UdkUserSvc_*",
        "AarSvc_*",
        "PhoneSvc",
        "WalletService",
        "WpcMonSvc",
        "wisvc",
        "DmEnrollmentSvc",
        "PushToInstall",
        "AssignedAccessManagerSvc",
        "DialogBlockingService",
        "DispBrokerDesktopSvc",
        "DisplayEnhancementService",
        "GraphicsPerfSvc",
        "MixedRealityOpenXRSvc",
        "perceptionsimulation",
        "spectrum",
        "WEPHOSTSVC",
        "WarpJITSvc",
        "fhsvc",
        "SDRSVC",
        "wbengine",
        "workfolderssvc",
        "SmsRouter",
        "EntAppSvc",
        "HvHost",
        "vmickvpexchange",
        "vmicguestinterface",
        "vmicshutdown",
        "vmicheartbeat",
        "vmicvmsession",
        "vmicrdv",
        "vmictimesync",
        "vmicvss",
        "vmcompute",
        "vmms",
        "MSiSCSI",
        "MSDTC",
        "KtmRm",
        "smphost",
        "svsvc",
        "TieringEngineService",
        "AppVClient",
        "AppMgmt",
        "AxInstSV",
        "ALG",
        "AJRouter",
        "shpamsvc",
        "NcaSvc"
    ) | ForEach-Object { Disable-ExtraService -Name $_ }

    # --- Обновления Windows --------------------------------------------------
    # Полностью гасить обновления нельзя: старый Windows 10 в интернете без заплаток
    # быстро становится опасным, а браузер как раз ходит в интернет.
    # Службы переведены в «Вручную», политика — «сообщать перед загрузкой»,
    # без автоматической перезагрузки, пока кто-то вошёл в систему.
    # Раз в месяц, когда фильм не смотрите, откройте Параметры -> Обновление и безопасность.
    # Права на службу WaaSMedicSvc не меняем: захват владельца легко ломает обслуживание системы.
    Write-Host ""
    Write-Host "Обновления Windows (не выключаем, только убираем автозапуск)" -ForegroundColor Cyan
    @(
        "wuauserv",
        "UsoSvc",
        "BITS",
        "DoSvc"
    ) | ForEach-Object { Set-ManualService -Name $_ }

    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "NoAutoUpdate" -Value 0
    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "AUOptions" -Value 2
    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "NoAutoRebootWithLoggedOnUsers" -Value 1
    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DeliveryOptimization" -Name "DODownloadMode" -Value 0

    # --- Задачи планировщика -------------------------------------------------
    # Только телеметрия, карты, оценка производительности и сбор статистики диска.
    # Проверку здоровья HDD (DiskDiagnosticResolver), дефрагментацию и Защитник не трогаем.
    # Задачи Центра обновления тоже оставляем: иначе заплатки потом не поставить штатно.
    Write-Host ""
    Write-Host "Лишние задания планировщика" -ForegroundColor Cyan
    $scheduler = Get-Service -Name "Schedule" -ErrorAction SilentlyContinue
    if ($scheduler -and $scheduler.Status -ne "Running") {
        Set-ServiceStartupSafe -Name "Schedule" -StartupType Automatic | Out-Null
        & sc.exe start Schedule | Out-Null
    }
    @(
        "\Microsoft\Windows\Application Experience\Microsoft Compatibility Appraiser",
        "\Microsoft\Windows\Application Experience\ProgramDataUpdater",
        "\Microsoft\Windows\Application Experience\StartupAppTask",
        "\Microsoft\Windows\Application Experience\PcaPatchDbTask",
        "\Microsoft\Windows\Application Experience\MareBackup",
        "\Microsoft\Windows\Autochk\Proxy",
        "\Microsoft\Windows\Customer Experience Improvement Program\Consolidator",
        "\Microsoft\Windows\Customer Experience Improvement Program\UsbCeip",
        "\Microsoft\Windows\Customer Experience Improvement Program\KernelCeipTask",
        "\Microsoft\Windows\DiskDiagnostic\Microsoft-Windows-DiskDiagnosticDataCollector",
        "\Microsoft\Windows\Feedback\Siuf\DmClient",
        "\Microsoft\Windows\Feedback\Siuf\DmClientOnScenarioDownload",
        "\Microsoft\Windows\Maps\MapsToastTask",
        "\Microsoft\Windows\Maps\MapsUpdateTask",
        "\Microsoft\Windows\Windows Error Reporting\QueueReporting",
        "\Microsoft\Windows\Windows Error Reporting\PrivacyConsentStatusTask",
        "\Microsoft\Windows\CloudExperienceHost\CreateObjectTask",
        "\Microsoft\Windows\Diagnosis\Scheduled",
        "\Microsoft\Windows\Maintenance\WinSAT",
        "\Microsoft\Windows\Shell\FamilySafetyMonitor",
        "\Microsoft\Windows\Shell\FamilySafetyRefresh",
        "\Microsoft\Windows\Shell\FamilySafetyUpload",
        "\Microsoft\Windows\DiskFootprint\Diagnostics",
        "\Microsoft\Windows\NetTrace\GatherNetworkInfo",
        "\Microsoft\Windows\PI\Sqm-Tasks",
        "\Microsoft\Windows\Power Efficiency Diagnostics\AnalyzeSystem",
        "\Microsoft\Windows\Speech\SpeechModelDownloadTask",
        "\Microsoft\Windows\HelloFace\FODCleanupTask",
        "\Microsoft\Windows\FileHistory\File History (maintenance mode)",
        "\Microsoft\Windows\Sysmain\ResPriStaticDbTask",
        "\Microsoft\Windows\Sysmain\WsSwapAssessmentTask"
    ) | ForEach-Object {
        $taskName = ($_ -split "\\")[-1]
        $taskPath = $_.Substring(0, $_.LastIndexOf("\") + 1)
        try {
            Disable-ScheduledTask -TaskName $taskName -TaskPath $taskPath -ErrorAction Stop | Out-Null
            Write-Host "  [задача выкл] $_" -ForegroundColor Green
        }
        catch {
            Write-Host "  [задача не найдена или занята] $_" -ForegroundColor DarkGray
        }
    }

    # --- Визуальные эффекты --------------------------------------------------
    # Анимации и прозрачность на этом процессоре отнимают кадры у видео.
    # ClearType (сглаживание шрифтов) оставляем: субтитры должны читаться.
    # Значки проводника не прячем — браузер ещё нужно найти и запустить.
    Write-Host ""
    Write-Host "Визуальные эффекты" -ForegroundColor Cyan
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\VisualEffects" -Name "VisualFXSetting" -Value 2
    Set-RegString -Path "HKCU:\Control Panel\Desktop" -Name "DragFullWindows" -Value "0"
    Set-RegString -Path "HKCU:\Control Panel\Desktop" -Name "FontSmoothing" -Value "2"
    Set-RegString -Path "HKCU:\Control Panel\Desktop" -Name "MenuShowDelay" -Value "100"
    # Маска «наилучшее быстродействие»: анимации выключены, шрифты остаются сглаженными.
    New-ItemProperty -LiteralPath "HKCU:\Control Panel\Desktop" -Name "UserPreferencesMask" -PropertyType Binary -Value ([byte[]](0x90, 0x12, 0x03, 0x80, 0x10, 0x00, 0x00, 0x00)) -Force | Out-Null
    Set-RegString -Path "HKCU:\Control Panel\Desktop\WindowMetrics" -Name "MinAnimate" -Value "0"
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "TaskbarAnimations" -Value 0
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "ListviewAlphaSelect" -Value 0
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "ListviewShadow" -Value 0
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize" -Name "EnableTransparency" -Value 0
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\DWM" -Name "EnableAeroPeek" -Value 0
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Serialize" -Name "StartupDelayInMSec" -Value 0
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\PushNotifications" -Name "ToastEnabled" -Value 0
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Feeds" -Name "ShellFeedsTaskbarViewMode" -Value 2
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" -Name "HideSCAMeetNow" -Value 1
    Set-RegDword -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer" -Name "HideSCAMeetNow" -Value 1
    # Старый планировщик GPU на HD 8210 только мешает. Значение 1 — выключено.
    Set-RegDword -Path "HKLM:\SYSTEM\CurrentControlSet\Control\GraphicsDrivers" -Name "HwSchMode" -Value 1

    # --- Память и жёсткий диск -----------------------------------------------
    # 4 ГБ легко уходят в ноль, если Windows ещё и сжимает память процессором.
    # E1-2100 дешевле отдать кадры видео, чем тратить их на сжатие.
    # Prefetch/Superfetch выключены по той же причине, что и служба SysMain.
    Write-Host ""
    Write-Host "Память и жёсткий диск" -ForegroundColor Cyan
    try {
        Disable-MMAgent -MemoryCompression -ErrorAction Stop
        Write-Host "  [ок] Сжатие памяти выключено." -ForegroundColor Green
    }
    catch {
        Write-Warning "  Сжатие памяти не изменилось: $($_.Exception.Message)"
    }
    try {
        Disable-MMAgent -PageCombining -ErrorAction Stop
        Write-Host "  [ок] Объединение страниц памяти выключено." -ForegroundColor Green
    }
    catch {
        Write-Warning "  Объединение страниц не изменилось: $($_.Exception.Message)"
    }

    $prefetch = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters"
    Set-RegDword -Path $prefetch -Name "EnablePrefetcher" -Value 0
    Set-RegDword -Path $prefetch -Name "EnableSuperfetch" -Value 0

    # Больше оперативки под кэш файловой системы не отдаём: её и так 4 ГБ.
    & fsutil.exe behavior set memoryusage 1 | Out-Null
    # Не обновлять время последнего доступа к каждому файлу — меньше мелких записей на HDD.
    & fsutil.exe behavior set disablelastaccess 1 | Out-Null
    Write-Host "  [ок] Лишние записи NTFS по времени доступа отключены." -ForegroundColor Green

    # Активному окну (браузеру) отдаём процессор раньше, чем фоновым службам.
    Set-RegDword -Path "HKLM:\SYSTEM\CurrentControlSet\Control\PriorityControl" -Name "Win32PrioritySeparation" -Value 38

    Set-FixedPageFile

    # Гибернация на HDD занимает примерно объём RAM и пишет большой файл.
    # Быстрый запуск при этом тоже выключится: загрузка станет чуть дольше, диск — свободнее.
    & powercfg.exe -h off | Out-Null
    Set-RegDword -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Power" -Name "HiberbootEnabled" -Value 0
    Write-Host "  [ок] Гибернация и быстрый запуск выключены." -ForegroundColor Green

    # --- Электропитание ------------------------------------------------------
    # На E1-2100 выигрыш не в «разгоне» (выше 1 ГГц он почти не бывает), а в том,
    # чтобы Wi-Fi, USB и жёсткий диск не засыпали посреди потока.
    # Пробуждение HDD из сна — это несколько секунд замершего кадра.
    Write-Host ""
    Write-Host "План электропитания" -ForegroundColor Cyan
    $highGuid = "8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c"
    $schemes = & powercfg.exe /L
    if ($schemes -notmatch $highGuid) {
        & powercfg.exe -duplicatescheme $highGuid | Out-Null
    }
    & powercfg.exe -setactive $highGuid | Out-Null
    Write-Host "  [ок] Включён план «Высокая производительность»." -ForegroundColor Green

    & powercfg.exe -change -monitor-timeout-ac 20 | Out-Null
    & powercfg.exe -change -monitor-timeout-dc 10 | Out-Null
    & powercfg.exe -change -standby-timeout-ac 0 | Out-Null
    & powercfg.exe -change -standby-timeout-dc 0 | Out-Null
    & powercfg.exe -change -hibernate-timeout-ac 0 | Out-Null
    & powercfg.exe -change -hibernate-timeout-dc 0 | Out-Null
    & powercfg.exe -change -disk-timeout-ac 0 | Out-Null
    & powercfg.exe -change -disk-timeout-dc 0 | Out-Null

    & powercfg.exe -SETACVALUEINDEX SCHEME_CURRENT SUB_DISK DISKIDLE 0 | Out-Null
    & powercfg.exe -SETDCVALUEINDEX SCHEME_CURRENT SUB_DISK DISKIDLE 0 | Out-Null
    & powercfg.exe -SETACVALUEINDEX SCHEME_CURRENT SUB_SLEEP HYBRIDSLEEP 0 | Out-Null
    & powercfg.exe -SETDCVALUEINDEX SCHEME_CURRENT SUB_SLEEP HYBRIDSLEEP 0 | Out-Null
    & powercfg.exe -SETACVALUEINDEX SCHEME_CURRENT SUB_PCIEXPRESS ASPM 0 | Out-Null
    & powercfg.exe -SETDCVALUEINDEX SCHEME_CURRENT SUB_PCIEXPRESS ASPM 0 | Out-Null
    & powercfg.exe -SETACVALUEINDEX SCHEME_CURRENT SUB_PROCESSOR PROCTHROTTLEMIN 100 | Out-Null
    & powercfg.exe -SETDCVALUEINDEX SCHEME_CURRENT SUB_PROCESSOR PROCTHROTTLEMIN 100 | Out-Null
    & powercfg.exe -SETACVALUEINDEX SCHEME_CURRENT SUB_PROCESSOR PROCTHROTTLEMAX 100 | Out-Null
    & powercfg.exe -SETDCVALUEINDEX SCHEME_CURRENT SUB_PROCESSOR PROCTHROTTLEMAX 100 | Out-Null
    & powercfg.exe -SETACVALUEINDEX SCHEME_CURRENT SUB_PROCESSOR SYSCOOLPOL 1 | Out-Null
    & powercfg.exe -SETDCVALUEINDEX SCHEME_CURRENT SUB_PROCESSOR SYSCOOLPOL 1 | Out-Null

    # 0 = максимальная производительность беспроводного адаптера (и от сети, и от батареи).
    $wifiSub = "19cbb8fa-5279-450e-9fac-8a3d5fedd0c1"
    $wifiPwr = "12bbebe6-58d6-4636-95bb-3217ef867c1a"
    & powercfg.exe -SETACVALUEINDEX SCHEME_CURRENT $wifiSub $wifiPwr 0 | Out-Null
    & powercfg.exe -SETDCVALUEINDEX SCHEME_CURRENT $wifiSub $wifiPwr 0 | Out-Null

    # Выборочная приостановка USB тоже умеет «проваливать» кадр на старых контроллерах.
    $usbSub = "2a737441-1930-4402-8d77-b2bebba308a3"
    $usbSus = "48e6b7a6-50f5-4782-a5d4-53bb8f07e226"
    & powercfg.exe -SETACVALUEINDEX SCHEME_CURRENT $usbSub $usbSus 0 | Out-Null
    & powercfg.exe -SETDCVALUEINDEX SCHEME_CURRENT $usbSub $usbSus 0 | Out-Null
    & powercfg.exe -setactive $highGuid | Out-Null
    Write-Host "  [ок] Диск, Wi-Fi и USB не уходят в энергосбережение." -ForegroundColor Green

    # --- Автозагрузка --------------------------------------------------------
    # Записи Run не удаляем: в диспетчере задач их можно включить обратно.
    # Ярлыки из папок автозагрузки переносятся в backup\startup-shortcuts, не в корзину навсегда.
    # RunOnce не трогаем — там часто лежит хвост установки программы, его нельзя срывать.
    Write-Host ""
    Write-Host "Автозагрузка" -ForegroundColor Cyan
    Disable-StartupRunKey -RunKey "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" -ApprovedKey "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run"
    Disable-StartupRunKey -RunKey "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run" -ApprovedKey "HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run"
    Disable-StartupRunKey -RunKey "HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Run" -ApprovedKey "HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run32"

    $userStartup = [Environment]::GetFolderPath("Startup")
    $commonStartup = Join-Path $env:ProgramData "Microsoft\Windows\Start Menu\Programs\Startup"
    Suspend-StartupFolder -SourceFolder $userStartup -BackupFolder (Join-Path $script:BackupDir "startup-shortcuts\user")
    Suspend-StartupFolder -SourceFolder $commonStartup -BackupFolder (Join-Path $script:BackupDir "startup-shortcuts\common")

    # OneDrive только перестаёт синхронизироваться. Файлы в папке пользователя остаются.
    Get-Process -Name "OneDrive" -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\OneDrive" -Name "DisableFileSyncNGSC" -Value 1
    Write-Host "  [ок] Синхронизация OneDrive отключена, файлы не удалялись." -ForegroundColor Green

    # --- Лишний интерфейс и телеметрия в политиках ---------------------------
    Write-Host ""
    Write-Host "Советы, фоновые приложения, телеметрия" -ForegroundColor Cyan
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "SystemPaneSuggestionsEnabled" -Value 0
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "SoftLandingEnabled" -Value 0
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "SubscribedContent-338388Enabled" -Value 0
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "SubscribedContent-338389Enabled" -Value 0
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "SubscribedContent-353694Enabled" -Value 0
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "SubscribedContent-353696Enabled" -Value 0
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" -Name "SilentInstalledAppsEnabled" -Value 0
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\BackgroundAccessApplications" -Name "GlobalUserDisabled" -Value 1
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\AdvertisingInfo" -Name "Enabled" -Value 0
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Search" -Name "BingSearchEnabled" -Value 0
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Search" -Name "CortanaConsent" -Value 0
    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Search" -Name "AllowCortana" -Value 0
    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Search" -Name "AllowSearchToUseLocation" -Value 0
    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Search" -Name "DisableWebSearch" -Value 1
    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Search" -Name "ConnectedSearchUseWeb" -Value 0
    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection" -Name "AllowTelemetry" -Value 0
    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\AppCompat" -Name "AITEnable" -Value 0
    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\AppCompat" -Name "DisableUAR" -Value 1
    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\SQMClient\Windows" -Name "CEIPEnable" -Value 0
    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Name "EnableActivityFeed" -Value 0
    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Name "PublishUserActivities" -Value 0
    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Name "UploadUserActivities" -Value 0
    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\CloudContent" -Name "DisableSoftLanding" -Value 1
    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\CloudContent" -Name "DisableWindowsConsumerFeatures" -Value 1

    # Игровая панель пишет видео на диск и на этом ПК только мешает.
    Set-RegDword -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\GameDVR" -Name "AppCaptureEnabled" -Value 0
    Set-RegDword -Path "HKCU:\System\GameConfigStore" -Name "GameDVR_Enabled" -Value 0
    Set-RegDword -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\GameDVR" -Name "AllowGameDVR" -Value 0

    # --- Мультимедиа ---------------------------------------------------------
    # SystemResponsiveness = 10 означает: 10% CPU оставить системе, остальное можно отдать
    # потокам аудио и видео. Ноль не ставим — на двух ядрах сеть тоже должна успевать.
    # NetworkThrottlingIndex = максимум отключает встроенное урезание скорости мультимедиа.
    Write-Host ""
    Write-Host "Приоритет звука и видео" -ForegroundColor Cyan
    $mmcss = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Multimedia\SystemProfile"
    Set-RegDword -Path $mmcss -Name "SystemResponsiveness" -Value 10
    if (-not (Test-Path -LiteralPath $mmcss)) {
        New-Item -Path $mmcss -Force | Out-Null
    }
    New-ItemProperty -LiteralPath $mmcss -Name "NetworkThrottlingIndex" -PropertyType DWord -Value ([uint32]::MaxValue) -Force | Out-Null

    foreach ($taskName in @("Audio", "Playback")) {
        $taskPath = Join-Path $mmcss "Tasks\$taskName"
        if (Test-Path -LiteralPath $taskPath) {
            Set-RegString -Path $taskPath -Name "Scheduling Category" -Value "High"
            Set-RegString -Path $taskPath -Name "SFIO Priority" -Value "High"
            Set-RegDword -Path $taskPath -Name "Priority" -Value 6
            Write-Host "  [ок] Повышена важность потока $taskName" -ForegroundColor Green
        }
    }

    # --- Защитник Windows: не выключаем, только снижаем цену проверки --------
    # Полное отключение защиты на компьютере, который ходит в интернет, здесь не делается.
    # Исключаем лишь кэш браузера: он всё равно перезаписывается и сильно дёргает HDD.
    # Документы и загрузки по-прежнему проверяются.
    Write-Host ""
    Write-Host "Защитник Windows (остаётся включённым)" -ForegroundColor Cyan
    try {
        Import-Module Defender -ErrorAction Stop
        Set-MpPreference -ScanAvgCPULoadFactor 5 -ErrorAction SilentlyContinue
        Set-MpPreference -EnableLowCpuPriority $true -ErrorAction SilentlyContinue

        $cachePaths = @(
            (Join-Path $env:LOCALAPPDATA "Google\Chrome\User Data\Default\Cache"),
            (Join-Path $env:LOCALAPPDATA "Google\Chrome\User Data\Default\Code Cache"),
            (Join-Path $env:LOCALAPPDATA "Google\Chrome\User Data\ShaderCache"),
            (Join-Path $env:LOCALAPPDATA "Microsoft\Edge\User Data\Default\Cache"),
            (Join-Path $env:LOCALAPPDATA "Microsoft\Edge\User Data\Default\Code Cache"),
            (Join-Path $env:LOCALAPPDATA "Microsoft\Edge\User Data\ShaderCache")
        )
        $ffProfiles = Join-Path $env:LOCALAPPDATA "Mozilla\Firefox\Profiles"
        if (Test-Path -LiteralPath $ffProfiles) {
            Get-ChildItem -LiteralPath $ffProfiles -Directory -ErrorAction SilentlyContinue | ForEach-Object {
                $cachePaths += (Join-Path $_.FullName "cache2")
            }
        }
        foreach ($cachePath in $cachePaths) {
            try {
                Add-MpPreference -ExclusionPath $cachePath -ErrorAction Stop
                Write-Host "  [исключён кэш] $cachePath" -ForegroundColor Green
            }
            catch {
                Write-Host "  [кэш уже исключён или недоступен] $cachePath" -ForegroundColor DarkGray
            }
        }
    }
    catch {
        Write-Warning "  Параметры Защитника не изменены: $($_.Exception.Message)"
    }

    # Повторная проверка на случай, если остановка какой-то службы потянула за собой звук или Wi-Fi.
    Write-Host ""
    Write-Host "Повторная проверка звука и сети" -ForegroundColor Cyan
    Protect-NeededServices

    Write-Host ""
    Write-Host "Готово. Выключено служб (вместе с вариантами имён): $($script:DisabledOk). Не удалось: $($script:DisabledFail)." -ForegroundColor Green
    Write-Host "Перезагрузите компьютер, когда будет удобно. Сам скрипт перезагрузку не запускает." -ForegroundColor Yellow
    Write-Host "Откат: .\Optimize-MoviePC.ps1 -Restore" -ForegroundColor Yellow
    Write-Host "Раз в месяц, не во время фильма, имеет смысл дефрагментировать диск: defrag $env:SystemDrive /O" -ForegroundColor Yellow

    Write-Host ""
    Write-Host "Браузер для этого железа" -ForegroundColor Cyan
    Write-Host @"
Ставьте Mozilla Firefox: https://www.mozilla.org/firefox/
На E1-2100 и 4 ГБ RAM он обычно легче Chrome и Edge.

Radeon HD 8210 аппаратно декодирует H.264 и не умеет VP9/AV1.
Поставьте расширение h264ify, иначе YouTube отдаст VP9 и ролик будет считать процессор.
Смотрите в 720p, включите аппаратное ускорение, поставьте uBlock Origin
и не держите вторую тяжёлую программу рядом с фильмом.

Подробнее: $(Join-Path $PSScriptRoot "browser-recommendation.txt")
"@
}
finally {
    try { Stop-Transcript | Out-Null } catch { }
}

# =============================================================================
# Браузер (кратко, чтобы совет остался прямо в скрипте)
#
# Лучший вариант для AMD E1-2100 / 4 ГБ / HDD — Mozilla Firefox.
# Chrome и Edge на нескольких вкладках съедают гигабайт и больше, после чего
# Windows активно листает файл подкачки на жёстком диске и кадр замирает.
#
# Обязательно расширение h264ify или enhanced-h264ify.
# Видеоядро HD 8210 тянет H.264. VP9 и AV1 идут программно и заикаются даже в 480p.
# Разрешение для этого ПК — 720p. Аппаратное ускорение в браузере должно быть включено.
# uBlock Origin убирает рекламу, которая на двух ядрах по 1 ГГц сама по себе роняет кадр.
# Одна вкладка с видео. Не запускайте Chrome и Firefox одновременно.
# =============================================================================

Jak wycofać zmiany (-Restore)

W tym samym folderze (obok musi znajdować się folder backup\) uruchom jako administrator:

.\Optimize-MoviePC.ps1 -Restore

Skrypt przywróci typy uruchamiania usług z services-before.csv (bez ich restartowania), zaimportuje zapisane kopie rejestru, przywróci skróty autostartu i poprosi o restart. Jeśli folder backup\ nie istnieje, zaproponuje skorzystanie z punktu przywracania systemu.

Czego -Restore nie przywraca: kompresji pamięci, hibernacji, planu zasilania, pliku wymiany (tylko częściowo), wyłączonych zadań harmonogramu (pozostają wyłączone), ustawień fsutil; proces OneDrive nie jest restartowany. Część można przywrócić ręcznie:

powercfg -h on
Enable-MMAgent -MemoryCompression -PageCombining

Pełne wycofanie — przez utworzony punkt przywracania systemu.

Przeglądarka dla telewizora: ustawienia, bez których wideo będzie się zacinać

  • Mozilla Firefox. Chrome i Edge z kilkoma kartami często zajmują 1–1,5 GB pamięci; razem z Windows z 4 GB nic nie zostaje, zaczyna się stronicowanie na HDD i obraz zamarza. Firefox z 1–2 kartami zwykle zużywa mniej.
  • Rozszerzenie h264ify (lub enhanced-h264ify) dla YouTube. Radeon HD 8210 sprzętowo dekoduje H.264, ale nie obsługuje VP9/AV1. Bez rozszerzenia VP9 dekoduje procesor i obraz się sypie nawet w 480p.
  • Akceleracja sprzętowa — włącz w Ustawienia → Wydajność.
  • 720p — 1080p taki sprzęt często nie uciągnie.
  • uBlock Origin — reklamy to dodatkowy JavaScript i zacięcia.
  • Jedna karta; nie uruchamiaj Chrome i Firefox jednocześnie. Jeśli potrzebujesz właśnie Chromium — jeden Chrome lub Edge + enhanced-h264ify + uBlock Origin, jedna karta 720p, ale zapas będzie gorszy niż w Firefoksie.

Realistyczny pułap takiego komputera dla telewizora: jeden film 720p w H.264, Wi-Fi bez oszczędzania energii karty, bez pobierania i aktualizacji w tle.

Podsumowanie

Optymalizacja starego komputera nie zamieni go w stację gamingową, ale słaby PC do multimediów jest całkiem realny: odchudzony Windows 10, właściwa przeglądarka i kodek H.264 pozwalają oglądać filmy i YouTube na telewizorze bez zbędnych wydatków.

Potrzebujesz pomocy z poważniejszym sprzętem? Zespół crmgo.eu konfiguruje strony i serwery, przenosi projekty, zajmuje się pozycjonowaniem SEO i automatyzacją biznesu z CRM. Zostaw zgłoszenie na crmgo.eu — doradzimy i zrobimy.

Uwaga: wpis mógł powstać z pomocą AI i redakcji. Odpowiedzialny: Dmytro Lomaka, Kaltenkirchen.