167 lines
9.5 KiB
PowerShell
167 lines
9.5 KiB
PowerShell
# diag1.ps1 v2 - быстрая диагностика: SMART + журнал + тест чтения файлов CS2
|
||
# ТОЛЬКО ОТ АДМИНИСТРАТОРА. Вывод компактный, полный отчёт в Desktop\diag1.txt
|
||
# Запуск: [Net.ServicePointManager]::SecurityProtocol='Tls12'; irm https://git.dttb.ru/oleg/scripts/raw/branch/main/diag1.ps1 | iex
|
||
|
||
$ErrorActionPreference = 'Continue'
|
||
|
||
# --- проверка прав: без админа SMART и chkdsk не работают
|
||
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||
if (-not $isAdmin) {
|
||
Write-Host "`n!!! ЗАПУЩЕНО БЕЗ ПРАВ АДМИНИСТРАТОРА !!!" -ForegroundColor Red
|
||
Write-Host "SMART, счётчики надёжности и chkdsk не сработают. Смысла в прогоне нет." -ForegroundColor Red
|
||
Write-Host "Win+X -> 'Терминал (администратор)' -> вставить команду заново.`n" -ForegroundColor Yellow
|
||
return
|
||
}
|
||
|
||
$out = "$env:USERPROFILE\Desktop\diag1.txt"
|
||
Start-Transcript -Path $out -Force | Out-Null
|
||
|
||
# ВАЖНО: имя функции не 'H' - алиасы в PowerShell разрешаются раньше функций, h = Get-History
|
||
function Sec($t) { "`n" + ('=' * 72); "== $t"; ('=' * 72) }
|
||
|
||
Sec "СИСТЕМА"
|
||
Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version, BuildNumber, LastBootUpTime, InstallDate | Format-List
|
||
Get-CimInstance Win32_Processor | Select-Object Name, CurrentClockSpeed, MaxClockSpeed | Format-List
|
||
|
||
Sec "ПАМЯТЬ (Speed = профиль, ConfiguredClockSpeed = факт; расхождение или >2666 = XMP/EXPO)"
|
||
Get-CimInstance Win32_PhysicalMemory |
|
||
Select-Object DeviceLocator, Manufacturer, PartNumber, @{n='GB';e={$_.Capacity/1GB}}, Speed, ConfiguredClockSpeed, ConfiguredVoltage |
|
||
Format-Table -AutoSize
|
||
|
||
Sec "ВИДЕОКАРТА, ДРАЙВЕР, TDR"
|
||
Get-CimInstance Win32_VideoController | Select-Object Name, DriverVersion, DriverDate | Format-List
|
||
"--- Параметры TDR в реестре (пусто = значения по умолчанию):"
|
||
Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\GraphicsDrivers' -ErrorAction SilentlyContinue |
|
||
Select-Object TdrDelay, TdrDdiDelay, TdrLevel | Format-List
|
||
|
||
Sec "ДИСКИ"
|
||
Get-PhysicalDisk | Select-Object DeviceId, FriendlyName, MediaType, BusType, HealthStatus, OperationalStatus, @{n='GB';e={[int]($_.Size/1GB)}} | Format-Table -AutoSize
|
||
Get-Disk | Select-Object Number, FriendlyName, SerialNumber, FirmwareVersion, HealthStatus | Format-Table -AutoSize
|
||
Get-Volume | Where-Object DriveLetter | Select-Object DriveLetter, FileSystem, HealthStatus, @{n='FreeGB';e={[int]($_.SizeRemaining/1GB)}}, @{n='SizeGB';e={[int]($_.Size/1GB)}} | Format-Table -AutoSize
|
||
|
||
Sec "СЧЁТЧИКИ НАДЁЖНОСТИ (Windows)"
|
||
foreach ($pd in Get-PhysicalDisk) {
|
||
"--- Диск $($pd.DeviceId): $($pd.FriendlyName)"
|
||
$pd | Get-StorageReliabilityCounter |
|
||
Select-Object Temperature, TemperatureMax, ReadErrorsTotal, ReadErrorsCorrected, ReadErrorsUncorrected,
|
||
WriteErrorsTotal, WriteErrorsCorrected, WriteErrorsUncorrected, Wear, PowerOnHours, StartStopCycleCount |
|
||
Format-List
|
||
}
|
||
|
||
Sec "SMART (smartctl) - ГЛАВНАЯ УЛИКА"
|
||
$sm = "C:\Program Files\smartmontools\bin\smartctl.exe"
|
||
if (-not (Test-Path $sm)) {
|
||
"smartctl не найден, ставлю через winget..."
|
||
winget install --id smartmontools.smartmontools -e --silent --accept-source-agreements --accept-package-agreements 2>&1 | Out-String
|
||
}
|
||
$smartRaw = @()
|
||
if (Test-Path $sm) {
|
||
$devs = & $sm --scan 2>&1 | ForEach-Object { if ($_ -match '^(\S+)\s') { $Matches[1] } }
|
||
foreach ($d in $devs) {
|
||
"`n--- $d"
|
||
$r = & $sm -a $d 2>&1
|
||
$smartRaw += $r
|
||
$r
|
||
}
|
||
} else {
|
||
"!!! smartctl поставить не удалось. Вручную: https://sourceforge.net/projects/smartmontools/"
|
||
}
|
||
|
||
Sec "СОБЫТИЯ ЗА 30 ДНЕЙ (диск, ФС, GPU, креши)"
|
||
$since = (Get-Date).AddDays(-30)
|
||
$provs = @(
|
||
@{n='disk'; f=@{ProviderName='disk'; StartTime=$since}},
|
||
@{n='Ntfs'; f=@{ProviderName='Microsoft-Windows-Ntfs'; StartTime=$since}},
|
||
@{n='storahci'; f=@{ProviderName='storahci'; StartTime=$since}},
|
||
@{n='stornvme'; f=@{ProviderName='stornvme'; StartTime=$since}},
|
||
@{n='volmgr'; f=@{ProviderName='volmgr'; StartTime=$since}},
|
||
@{n='WHEA-Logger'; f=@{ProviderName='Microsoft-Windows-WHEA-Logger'; StartTime=$since}},
|
||
@{n='Display (TDR)'; f=@{ProviderName='Display'; StartTime=$since}},
|
||
@{n='amdkmdag'; f=@{ProviderName='amdkmdag'; StartTime=$since}},
|
||
@{n='Application Error'; f=@{ProviderName='Application Error'; StartTime=$since}},
|
||
@{n='Kernel-Power 41'; f=@{ProviderName='Microsoft-Windows-Kernel-Power'; ID=41; StartTime=$since}}
|
||
)
|
||
foreach ($p in $provs) {
|
||
"`n--- $($p.n)"
|
||
try {
|
||
Get-WinEvent -FilterHashtable $p.f -MaxEvents 40 -ErrorAction Stop |
|
||
Select-Object TimeCreated, Id, LevelDisplayName,
|
||
@{n='Msg';e={($_.Message -replace '\s+',' ').Substring(0, [Math]::Min(160, $_.Message.Length))}} |
|
||
Format-Table -AutoSize -Wrap
|
||
} catch { "нет событий" }
|
||
}
|
||
|
||
Sec "ТЕСТ ЧТЕНИЯ CS2 (печатаю только проблемные; норма SATA SSD 450-550 МБ/с)"
|
||
$libs = @()
|
||
foreach ($drv in (Get-Volume | Where-Object { $_.DriveLetter -and $_.FileSystem -eq 'NTFS' }).DriveLetter) {
|
||
foreach ($cand in @("${drv}:\steam\steamapps\common", "${drv}:\SteamLibrary\steamapps\common", "${drv}:\Program Files (x86)\Steam\steamapps\common")) {
|
||
if (Test-Path $cand) { $libs += $cand }
|
||
}
|
||
}
|
||
"Библиотеки: $($libs -join ', ')"
|
||
|
||
$cs2 = $libs | ForEach-Object { Join-Path $_ 'Counter-Strike Global Offensive' } | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||
if ($cs2) {
|
||
"CS2: $cs2"
|
||
$mapsDir = Join-Path $cs2 'game\csgo\maps'
|
||
if (Test-Path $mapsDir) {
|
||
"`n--- Каталог карт найден. Файлы *vanity* (читаются ТОЛЬКО в премьере):"
|
||
$v = Get-ChildItem $mapsDir -Filter '*vanity*' -File -ErrorAction SilentlyContinue
|
||
if ($v) { $v | Select-Object Name, @{n='MB';e={[math]::Round($_.Length/1MB,1)}}, LastWriteTime | Format-Table -AutoSize }
|
||
else { "!!! vanity-файлов НЕТ - игра их не докачала либо структура изменилась" }
|
||
} else { "!!! Каталога $mapsDir нет" }
|
||
|
||
$files = Get-ChildItem -Path $cs2 -Recurse -Filter '*.vpk' -File -ErrorAction SilentlyContinue
|
||
$buf = New-Object byte[] 4194304
|
||
$bad = @(); $slow = @(); $spds = @(); $n_ok = 0
|
||
foreach ($f in $files) {
|
||
try {
|
||
$fs = [IO.File]::Open($f.FullName, 'Open', 'Read', 'Read')
|
||
$sw = [Diagnostics.Stopwatch]::StartNew(); $tot = 0
|
||
while (($k = $fs.Read($buf, 0, $buf.Length)) -gt 0) { $tot += $k }
|
||
$sw.Stop(); $fs.Close()
|
||
$n_ok++
|
||
$mb = $tot / 1MB
|
||
# файлы мельче 8 МБ по скорости не оцениваем - оверхед открытия искажает
|
||
if ($mb -ge 8 -and $sw.Elapsed.TotalSeconds -gt 0) {
|
||
$s = $mb / $sw.Elapsed.TotalSeconds
|
||
$spds += $s
|
||
if ($s -lt 200) {
|
||
$slow += "SLOW {0,7:N1} MB/s {1,8:N1} MB {2}" -f $s, $mb, $f.FullName
|
||
}
|
||
}
|
||
} catch {
|
||
$bad += "FAIL $($f.FullName) -> $($_.Exception.Message)"
|
||
}
|
||
}
|
||
"`nПрочитано файлов: $n_ok, ошибок: $($bad.Count), медленных: $($slow.Count)"
|
||
if ($spds.Count) {
|
||
$st = $spds | Measure-Object -Minimum -Maximum -Average
|
||
"Скорость по файлам >8 МБ: min {0:N1} / avg {1:N1} / max {2:N1} МБ/с (проверено {3})" -f $st.Minimum, $st.Average, $st.Maximum, $spds.Count
|
||
}
|
||
if ($bad) { "`n--- ОШИБКИ ЧТЕНИЯ:"; $bad }
|
||
if ($slow) { "`n--- МЕДЛЕННЫЕ:"; $slow }
|
||
if (-not $bad -and -not $slow) { "Проблемных файлов нет - чтение на полной скорости." }
|
||
} else {
|
||
"!!! Папка CS2 не найдена"
|
||
}
|
||
|
||
Sec "CHKDSK E: /scan (только чтение, без правки)"
|
||
if (Test-Path 'E:\') { chkdsk E: /scan } else { "диска E нет" }
|
||
|
||
Sec "СВОДКА ПО SMART (то, что решает)"
|
||
if ($smartRaw) {
|
||
$keys = 'Reallocated_Sector_Ct|Current_Pending_Sector|Offline_Uncorrectable|Reported_Uncorrect|UDMA_CRC_Error|Raw_Read_Error_Rate|Wear_Leveling|Total_LBAs_Written|Media_Wearout|Power_On_Hours|Temperature_Celsius|Available_Spare|Percentage_Used|Media and Data Integrity'
|
||
$hit = $smartRaw | Select-String -Pattern $keys
|
||
if ($hit) { $hit | ForEach-Object { $_.Line } } else { "атрибуты не распознаны - смотреть полный вывод выше" }
|
||
"`n--- Итог самотестирования:"
|
||
($smartRaw | Select-String -Pattern 'SMART overall-health|test result').Line
|
||
} else {
|
||
"SMART не собран"
|
||
}
|
||
|
||
Sec "ГОТОВО"
|
||
"Отчёт: $out"
|
||
Stop-Transcript | Out-Null
|
||
Write-Host "`nОтчёт сохранён: $out -- пришли файл целиком" -ForegroundColor Green
|