$ErrorActionPreference = "SilentlyContinue" $ProgressPreference = "SilentlyContinue" $since = (Get-Date).AddDays(-90) function GB($bytes) { if ($null -eq $bytes) { return $null } return [math]::Round(([double]$bytes / 1GB), 1) } function Clean($value) { if ($null -eq $value) { return $null } return ([string]$value).Trim() } # 관리자 권한 여부 $isAdmin = $false try { $identity = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = New-Object Security.Principal.WindowsPrincipal($identity) $isAdmin = $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) } catch {} # 시스템 / OS $computerSystem = Get-CimInstance Win32_ComputerSystem | ForEach-Object { [PSCustomObject]@{ Manufacturer = Clean $_.Manufacturer Model = Clean $_.Model SystemType = Clean $_.SystemType TotalPhysicalMemory_GB = GB $_.TotalPhysicalMemory } } $os = Get-CimInstance Win32_OperatingSystem | ForEach-Object { [PSCustomObject]@{ Caption = Clean $_.Caption Version = Clean $_.Version BuildNumber = Clean $_.BuildNumber OSArchitecture = Clean $_.OSArchitecture InstallDate = if ($_.InstallDate) { $_.InstallDate.ToString("yyyy-MM-dd HH:mm:ss") } else { $null } LastBootUpTime = if ($_.LastBootUpTime) { $_.LastBootUpTime.ToString("yyyy-MM-dd HH:mm:ss") } else { $null } } } # CPU $cpu = Get-CimInstance Win32_Processor | ForEach-Object { [PSCustomObject]@{ Name = Clean $_.Name Manufacturer = Clean $_.Manufacturer ProcessorId = Clean $_.ProcessorId SocketDesignation = Clean $_.SocketDesignation NumberOfCores = $_.NumberOfCores NumberOfLogicalProcessors = $_.NumberOfLogicalProcessors MaxClockSpeed_MHz = $_.MaxClockSpeed CurrentClockSpeed_MHz = $_.CurrentClockSpeed } } # 메인보드 $board = Get-CimInstance Win32_BaseBoard | ForEach-Object { [PSCustomObject]@{ Manufacturer = Clean $_.Manufacturer Product = Clean $_.Product Version = Clean $_.Version SerialNumber = Clean $_.SerialNumber } } # BIOS $bios = Get-CimInstance Win32_BIOS | ForEach-Object { [PSCustomObject]@{ Manufacturer = Clean $_.Manufacturer SMBIOSBIOSVersion = Clean $_.SMBIOSBIOSVersion Version = Clean $_.Version SerialNumber = Clean $_.SerialNumber BIOS_Date = if ($_.ReleaseDate) { $_.ReleaseDate.ToString("yyyy-MM-dd") } else { $null } } } # RAM - 모듈 단위 $ramRaw = Get-CimInstance Win32_PhysicalMemory $ram = $ramRaw | ForEach-Object { [PSCustomObject]@{ DeviceLocator = Clean $_.DeviceLocator BankLabel = Clean $_.BankLabel Manufacturer = Clean $_.Manufacturer PartNumber = Clean $_.PartNumber SerialNumber = Clean $_.SerialNumber Capacity_GB = GB $_.Capacity Speed_MHz = $_.Speed ConfiguredClockSpeed_MHz = $_.ConfiguredClockSpeed ConfiguredVoltage_mV = $_.ConfiguredVoltage SMBIOSMemoryType = $_.SMBIOSMemoryType } } $totalRamGB = [math]::Round((($ramRaw | Measure-Object Capacity -Sum).Sum / 1GB), 1) # GPU - Windows 정보 $gpu = Get-CimInstance Win32_VideoController | ForEach-Object { [PSCustomObject]@{ Name = Clean $_.Name VideoProcessor = Clean $_.VideoProcessor PNPDeviceID = Clean $_.PNPDeviceID AdapterRAM_GB_WMI = if ($_.AdapterRAM) { GB $_.AdapterRAM } else { $null } DriverVersion = Clean $_.DriverVersion DriverDate = if ($_.DriverDate) { $_.DriverDate.ToString("yyyy-MM-dd") } else { $null } VideoModeDescription = Clean $_.VideoModeDescription CurrentHorizontalResolution = $_.CurrentHorizontalResolution CurrentVerticalResolution = $_.CurrentVerticalResolution CurrentRefreshRate_Hz = $_.CurrentRefreshRate } } # NVIDIA는 nvidia-smi가 가장 정확한 VRAM/온도/전력 정보를 제공 $nvidia = @() try { $query = & nvidia-smi --query-gpu=index,name,pci.bus_id,memory.total,memory.used,temperature.gpu,utilization.gpu,power.draw,power.limit,driver_version,vbios_version --format=csv,noheader,nounits 2>$null if ($LASTEXITCODE -eq 0 -and $query) { foreach ($line in $query) { $p = $line -split ',\s*' if ($p.Count -ge 11) { $nvidia += [PSCustomObject]@{ Index = [int]$p[0] Name = Clean $p[1] PCI_BusId = Clean $p[2] VRAM_Total_MB = [double]$p[3] VRAM_Total_GB = [math]::Round(([double]$p[3] / 1024), 1) VRAM_Used_MB = [double]$p[4] Temperature_C = [double]$p[5] Utilization_GPU_Percent = [double]$p[6] Power_Draw_W = [double]$p[7] Power_Limit_W = [double]$p[8] DriverVersion = Clean $p[9] VBIOSVersion = Clean $p[10] } } } } } catch {} # 저장장치 - Get-Disk $disks = Get-Disk | ForEach-Object { [PSCustomObject]@{ Number = $_.Number FriendlyName = Clean $_.FriendlyName SerialNumber = Clean $_.SerialNumber BusType = [string]$_.BusType PartitionStyle = [string]$_.PartitionStyle Size_GB = [math]::Round(($_.Size / 1GB), 0) HealthStatus = [string]$_.HealthStatus OperationalStatus = ($_.OperationalStatus -join ', ') IsBoot = $_.IsBoot IsSystem = $_.IsSystem } } # 저장장치 - 실제 물리 디스크 모델 / 펌웨어 / 상태 $physical = Get-PhysicalDisk | ForEach-Object { [PSCustomObject]@{ DeviceId = $_.DeviceId FriendlyName = Clean $_.FriendlyName Manufacturer = Clean $_.Manufacturer Model = Clean $_.Model SerialNumber = Clean $_.SerialNumber FirmwareVersion = Clean $_.FirmwareVersion MediaType = [string]$_.MediaType BusType = [string]$_.BusType SpindleSpeed = $_.SpindleSpeed Size_GB = [math]::Round(($_.Size / 1GB), 0) HealthStatus = [string]$_.HealthStatus OperationalStatus = ($_.OperationalStatus -join ', ') } } # SSD/HDD SMART / 신뢰도 카운터 (지원되는 장치만) $reliability = @() Get-PhysicalDisk | ForEach-Object { $pd = $_ $rc = $pd | Get-StorageReliabilityCounter if ($rc) { $reliability += [PSCustomObject]@{ FriendlyName = Clean $pd.FriendlyName SerialNumber = Clean $pd.SerialNumber Temperature_C = $rc.Temperature Wear_Percent = $rc.Wear PowerOnHours = $rc.PowerOnHours ReadErrorsTotal = $rc.ReadErrorsTotal ReadErrorsUncorrected = $rc.ReadErrorsUncorrected WriteErrorsTotal = $rc.WriteErrorsTotal WriteErrorsUncorrected = $rc.WriteErrorsUncorrected } } } # 볼륨 정보 $volumes = Get-Volume | Where-Object { $_.DriveLetter } | ForEach-Object { [PSCustomObject]@{ DriveLetter = [string]$_.DriveLetter FileSystemLabel = Clean $_.FileSystemLabel FileSystem = Clean $_.FileSystem HealthStatus = [string]$_.HealthStatus Size_GB = if ($_.Size) { [math]::Round(($_.Size / 1GB), 1) } else { $null } Free_GB = if ($_.SizeRemaining) { [math]::Round(($_.SizeRemaining / 1GB), 1) } else { 0 } } } # 현재 장치 오류 $deviceErrors = Get-PnpDevice -PresentOnly | Where-Object { $_.Status -ne "OK" } | ForEach-Object { [PSCustomObject]@{ Class = $_.Class FriendlyName = $_.FriendlyName InstanceId = $_.InstanceId Status = $_.Status Problem = $_.Problem } } function EventItems($items) { @($items | Select-Object -First 40 | ForEach-Object { [PSCustomObject]@{ TimeCreated = if ($_.TimeCreated) { $_.TimeCreated.ToString("s") } else { $null } ProviderName = $_.ProviderName Id = $_.Id LevelDisplayName = $_.LevelDisplayName Message = $_.Message } }) } # 최근 90일 이벤트 로그 $whea = Get-WinEvent -FilterHashtable @{LogName='System';ProviderName='Microsoft-Windows-WHEA-Logger';StartTime=$since} $allSystem = Get-WinEvent -FilterHashtable @{LogName='System';StartTime=$since} $storageEvents = $allSystem | Where-Object { ($_.ProviderName -match '^(disk|stornvme|storahci|iaStor)') -and ($_.LevelDisplayName -match 'Error|Critical') } $gpuEvents = $allSystem | Where-Object { ($_.ProviderName -match 'nvlddmkm|^Display$') -and ($_.LevelDisplayName -match 'Error|Critical|Warning') } $power41 = Get-WinEvent -FilterHashtable @{LogName='System';Id=41;StartTime=$since} # Windows 라이선스 / 정품 인증 상태 $windowsLicense = Get-CimInstance SoftwareLicensingProduct | Where-Object { $_.Name -like 'Windows*' -and $_.PartialProductKey } | Select-Object -First 1 Name,Description,LicenseStatus,PartialProductKey # 최종 JSON 객체 $report = [ordered]@{ ReportVersion = "4.0" GeneratedAt = (Get-Date).ToString("s") ComputerName = $env:COMPUTERNAME UserName = $env:USERNAME IsAdministrator = $isAdmin System = @($computerSystem) OS = @($os) CPU = @($cpu) Mainboard = @($board) BIOS = @($bios) RAM = @($ram) TotalRAM_GB = $totalRamGB GPU = @($gpu) NvidiaSMI = @($nvidia) Disks = @($disks) PhysicalDisks = @($physical) Reliability = @($reliability) Volumes = @($volumes) DeviceErrors = @($deviceErrors) Events = [ordered]@{ WHEA = EventItems $whea Storage = EventItems $storageEvents GPU = EventItems $gpuEvents KernelPower41 = EventItems $power41 } WindowsLicense = $windowsLicense } # 바탕화면에 JSON 자동 생성 $desktop = [Environment]::GetFolderPath('Desktop') if ([string]::IsNullOrWhiteSpace($desktop)) { $desktop = Join-Path $env:USERPROFILE 'Desktop' } $out = Join-Path $desktop 'PC-CHECK-REPORT.json' $json = $report | ConvertTo-Json -Depth 10 # UTF-8 BOM 없이 저장하여 웹에서 바로 JSON.parse 가능하게 함 $utf8NoBom = New-Object System.Text.UTF8Encoding($false) [System.IO.File]::WriteAllText($out, $json, $utf8NoBom) Write-Host "" Write-Host "============================================================" -ForegroundColor DarkGray Write-Host " PC CHECK 정밀검사 완료" -ForegroundColor Green Write-Host "============================================================" -ForegroundColor DarkGray Write-Host "결과 JSON : $out" -ForegroundColor Yellow Write-Host "CPU : $($cpu[0].Name)" -ForegroundColor White Write-Host "BOARD : $($board[0].Manufacturer) $($board[0].Product)" -ForegroundColor White Write-Host "RAM : $totalRamGB GB" -ForegroundColor White if ($nvidia.Count -gt 0) { Write-Host "GPU : $($nvidia[0].Name) / VRAM $($nvidia[0].VRAM_Total_GB) GB / $($nvidia[0].Temperature_C) C" -ForegroundColor White } elseif ($gpu.Count -gt 0) { Write-Host "GPU : $($gpu[0].Name)" -ForegroundColor White } Write-Host "WHEA : $(@($whea).Count) 건" -ForegroundColor $(if (@($whea).Count -eq 0) {'Green'} else {'Red'}) Write-Host "DISK ERR : $(@($storageEvents).Count) 건" -ForegroundColor $(if (@($storageEvents).Count -eq 0) {'Green'} else {'Red'}) Write-Host "GPU ERR : $(@($gpuEvents).Count) 건" -ForegroundColor $(if (@($gpuEvents).Count -eq 0) {'Green'} else {'Yellow'}) Write-Host "" Write-Host "바탕화면의 PC-CHECK-REPORT.json 파일을 PC CHECK 웹페이지에 드래그하세요." -ForegroundColor Cyan