diff --git a/diag1.ps1 b/diag1.ps1 index f5d4956..4a15550 100644 --- a/diag1.ps1 +++ b/diag1.ps1 @@ -1,30 +1,45 @@ -# diag1.ps1 - быстрая диагностика: SMART + журнал + тест чтения файлов CS2 -# Запуск от администратора: powershell -NoProfile -ExecutionPolicy Bypass -File C:\diag1.ps1 +# 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 -function H($t) { "`n" + ('=' * 70); "== $t"; ('=' * 70) } +# ВАЖНО: имя функции не 'H' - алиасы в PowerShell разрешаются раньше функций, h = Get-History +function Sec($t) { "`n" + ('=' * 72); "== $t"; ('=' * 72) } -H "СИСТЕМА" -Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version, BuildNumber, LastBootUpTime | Format-List +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 -H "ПАМЯТЬ (Speed = профиль, ConfiguredClockSpeed = фактическая; расхождение = XMP/EXPO)" +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 -H "ВИДЕОКАРТА И ДРАЙВЕР" -Get-CimInstance Win32_VideoController | Select-Object Name, DriverVersion, DriverDate, AdapterRAM | Format-List +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 -H "ДИСКИ" +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 -H "СЧЁТЧИКИ НАДЁЖНОСТИ (Windows)" +Sec "СЧЁТЧИКИ НАДЁЖНОСТИ (Windows)" foreach ($pd in Get-PhysicalDisk) { "--- Диск $($pd.DeviceId): $($pd.FriendlyName)" $pd | Get-StorageReliabilityCounter | @@ -33,82 +48,119 @@ foreach ($pd in Get-PhysicalDisk) { Format-List } -H "SMART (smartctl)" +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"; & $sm -a $d 2>&1 } + foreach ($d in $devs) { + "`n--- $d" + $r = & $sm -a $d 2>&1 + $smartRaw += $r + $r + } } else { - "!!! smartctl поставить не удалось. Ставим вручную: https://sourceforge.net/projects/smartmontools/" + "!!! smartctl поставить не удалось. Вручную: https://sourceforge.net/projects/smartmontools/" } -H "СОБЫТИЯ ЖУРНАЛА ЗА 30 ДНЕЙ (диск, ФС, GPU, креши)" +Sec "СОБЫТИЯ ЗА 30 ДНЕЙ (диск, ФС, GPU, креши)" $since = (Get-Date).AddDays(-30) -$providers = @( - @{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='BugCheck'; f=@{ProviderName='Microsoft-Windows-Kernel-Power'; ID=41; StartTime=$since}} +$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 $providers) { +foreach ($p in $provs) { "`n--- $($p.n)" try { - $ev = Get-WinEvent -FilterHashtable $p.f -MaxEvents 40 -ErrorAction Stop - $ev | Select-Object TimeCreated, Id, LevelDisplayName, @{n='Msg';e={($_.Message -replace '\s+',' ').Substring(0, [Math]::Min(180, $_.Message.Length))}} | + 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 { "нет событий" } } -H "ПОИСК БИБЛИОТЕК STEAM" +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; "найдено: $cand" } - } -} -if (-not $libs) { "!!! Библиотеки Steam не найдены по стандартным путям" } - -H "ТЕСТ ЧТЕНИЯ: vanity-файлы CS2 (падают только в премьере) + мелкие vpk" -function Test-Read($path) { - try { - $fs = [IO.File]::Open($path, 'Open', 'Read', 'Read') - $buf = New-Object byte[] 4194304 - $sw = [Diagnostics.Stopwatch]::StartNew() - $total = 0 - while (($n = $fs.Read($buf, 0, $buf.Length)) -gt 0) { $total += $n } - $sw.Stop(); $fs.Close() - $mb = $total / 1MB - $spd = if ($sw.Elapsed.TotalSeconds -gt 0) { $mb / $sw.Elapsed.TotalSeconds } else { 0 } - "OK {0,8:N1} MB {1,7:N1} MB/s {2}" -f $mb, $spd, $path - } catch { - "FAIL $path`n -> $($_.Exception.Message)" + 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" - $maps = Get-ChildItem -Path $cs2 -Recurse -Filter '*.vpk' -File -ErrorAction SilentlyContinue | - Where-Object { $_.Name -like '*vanity*' -or $_.Length -lt 200MB } - "Файлов к проверке: $($maps.Count)" - foreach ($m in $maps) { Test-Read $m.FullName } + $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 не найдена" } -H "CHKDSK E: /scan (только чтение, без правки)" +Sec "CHKDSK E: /scan (только чтение, без правки)" if (Test-Path 'E:\') { chkdsk E: /scan } else { "диска E нет" } -H "ГОТОВО. Отчёт: $out" +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 +Write-Host "`nОтчёт сохранён: $out -- пришли файл целиком" -ForegroundColor Green