Last active
August 28, 2026 19:40
-
-
Save katai5plate/69106bf85ab4780cf1b9ef25769105f6 to your computer and use it in GitHub Desktop.
Windows 11 BSOD Checker
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # ============================================================ | |
| # 汎用 BSOD 診断情報 一括採取 v4(1ファイル版 / PowerShell ISE用) | |
| # | |
| # 目的: | |
| # Wi-Fiに限らず、GPU / Audio / Storage / USB / PCIe / Network / | |
| # WHEA / Driver / Power / Filter Driver / Windows Update 等を | |
| # まとめて採取する「初動診断」用。 | |
| # | |
| # 使い方: | |
| # 1) PowerShell ISE を「管理者として実行」 | |
| # 2) このスクリプトを丸ごと貼り付け | |
| # 3) 必要なら下の「設定」だけ変更 | |
| # 4) F5 | |
| # | |
| # 出力: | |
| # デスクトップ\BSOD_Diag_Generic_YYYYMMDD_HHMMSS.txt | |
| # | |
| # 読み取り専用: | |
| # - ドライバ変更なし | |
| # - Binding変更なし | |
| # - サービス停止なし | |
| # - レジストリ変更なし | |
| # - 再起動なし | |
| # - Driver Verifierなし | |
| # - ストレステストなし | |
| # | |
| # 注意: | |
| # - dump本体(.dmp)はコピーしません | |
| # - WFP stateは一時XMLへ出力し、関連行だけ本文へ転記後に削除 | |
| # ============================================================ | |
| # ============================================================ | |
| # ★ 設定 | |
| # ============================================================ | |
| # BSODのおおよその時刻が分かる場合だけ指定。 | |
| # 不明なら $null のままでOK。 | |
| $CrashTime = $null | |
| # 例: | |
| # $CrashTime = [datetime]"2026-08-29 00:40:35" | |
| # CrashTime指定時、その前後何分を採取するか | |
| $WindowMinutes = 90 | |
| # CrashTime不明時、過去何日を見るか | |
| $Days = 7 | |
| # 初動レポートをコンパクトにするため、重い詳細採取は既定でOFF。 | |
| # Network/WFPが怪しい時だけ $true にして同じスクリプトを再実行。 | |
| $IncludeWfpDetail = $false | |
| # Driver Storeのpnputil完全一覧はかなり長いので既定でOFF。 | |
| $IncludeFullDriverStore = $false | |
| # WERは EventName + P1 + P2 で論理的なクラッシュ種別へまとめる。 | |
| $MaxWerGroups = 30 | |
| # Application Error の生イベントは最大この件数まで | |
| $MaxApplicationErrors = 20 | |
| # Reliability Monitor は定常的な更新成功記録を除外して最大この件数 | |
| $MaxReliabilityRecords = 80 | |
| # SetupAPIログの末尾を何行入れるか | |
| $SetupApiTailLines = 300 | |
| # 出力先 | |
| $OutRoot = [Environment]::GetFolderPath("Desktop") | |
| # ============================================================ | |
| # ここから下は基本編集不要 | |
| # ============================================================ | |
| $ErrorActionPreference = "Continue" | |
| $Stamp = Get-Date -Format "yyyyMMdd_HHmmss" | |
| $ReportPath = Join-Path $OutRoot ("BSOD_Diag_Generic_v4_" + $Stamp + ".txt") | |
| # ============================================================ | |
| # 補助関数 | |
| # ============================================================ | |
| function Write-Line { | |
| param([string]$Text = "") | |
| $Text | Out-File ` | |
| -FilePath $ReportPath ` | |
| -Append ` | |
| -Encoding utf8 ` | |
| -Width 600 | |
| } | |
| function Write-Section { | |
| param( | |
| [string]$Title, | |
| [scriptblock]$Command | |
| ) | |
| Write-Line "" | |
| Write-Line "================================================================================" | |
| Write-Line $Title | |
| Write-Line "================================================================================" | |
| try { | |
| & $Command 2>&1 | | |
| Out-String -Width 600 | | |
| Out-File ` | |
| -FilePath $ReportPath ` | |
| -Append ` | |
| -Encoding utf8 ` | |
| -Width 600 | |
| } | |
| catch { | |
| Write-Line ("ERROR: " + $_.Exception.Message) | |
| } | |
| } | |
| function Get-FileMeta { | |
| param([string[]]$Paths) | |
| foreach ($Path in ($Paths | Where-Object { $_ } | Select-Object -Unique)) { | |
| if (Test-Path $Path) { | |
| try { | |
| $Item = Get-Item $Path -ErrorAction Stop | |
| $Sig = Get-AuthenticodeSignature $Path -ErrorAction SilentlyContinue | |
| [pscustomobject]@{ | |
| Path = $Path | |
| FileVersion = $Item.VersionInfo.FileVersion | |
| ProductVersion = $Item.VersionInfo.ProductVersion | |
| CompanyName = $Item.VersionInfo.CompanyName | |
| Description = $Item.VersionInfo.FileDescription | |
| LastWriteTime = $Item.LastWriteTime | |
| Length = $Item.Length | |
| SignatureStatus = $Sig.Status | |
| SignerCertificate = if ($Sig.SignerCertificate) { | |
| $Sig.SignerCertificate.Subject | |
| } else { | |
| $null | |
| } | |
| } | |
| } | |
| catch { | |
| [pscustomobject]@{ | |
| Path = $Path | |
| FileVersion = $null | |
| ProductVersion = $null | |
| CompanyName = $null | |
| Description = $null | |
| LastWriteTime = $null | |
| Length = $null | |
| SignatureStatus = "ERROR" | |
| SignerCertificate = $_.Exception.Message | |
| } | |
| } | |
| } | |
| } | |
| } | |
| function Safe-GetWinEvent { | |
| param( | |
| [string]$LogName, | |
| [datetime]$StartTime, | |
| [datetime]$EndTime | |
| ) | |
| try { | |
| Get-WinEvent ` | |
| -FilterHashtable @{ | |
| LogName = $LogName | |
| StartTime = $StartTime | |
| EndTime = $EndTime | |
| } ` | |
| -ErrorAction Stop | |
| } | |
| catch { | |
| "LOG READ ERROR [$LogName]: $($_.Exception.Message)" | |
| } | |
| } | |
| # ============================================================ | |
| # 権限 / 時間範囲 | |
| # ============================================================ | |
| $Identity = [Security.Principal.WindowsIdentity]::GetCurrent() | |
| $Principal = New-Object Security.Principal.WindowsPrincipal($Identity) | |
| $IsAdmin = $Principal.IsInRole( | |
| [Security.Principal.WindowsBuiltInRole]::Administrator | |
| ) | |
| if ($CrashTime) { | |
| $EventStart = $CrashTime.AddMinutes(-$WindowMinutes) | |
| $EventEnd = $CrashTime.AddMinutes($WindowMinutes) | |
| } | |
| else { | |
| $EventStart = (Get-Date).AddDays(-$Days) | |
| $EventEnd = Get-Date | |
| } | |
| # ============================================================ | |
| # HEADER | |
| # ============================================================ | |
| @" | |
| GENERIC BSOD DIAGNOSTIC REPORT v4 | |
| ================================================================================ | |
| Collected : $(Get-Date -Format "yyyy-MM-dd HH:mm:ss zzz") | |
| Computer : $env:COMPUTERNAME | |
| User : $($Identity.Name) | |
| Administrator : $IsAdmin | |
| PowerShell : $($PSVersionTable.PSVersion) | |
| 64-bit process : $([Environment]::Is64BitProcess) | |
| CrashTime setting: $CrashTime | |
| EventStart : $EventStart | |
| EventEnd : $EventEnd | |
| Days : $Days | |
| WindowMinutes : $WindowMinutes | |
| IncludeWfpDetail : $IncludeWfpDetail | |
| IncludeFullDriverStore : $IncludeFullDriverStore | |
| Report : $ReportPath | |
| PROFILE: | |
| - Default = compact generic first-pass | |
| - Set IncludeWfpDetail / IncludeFullDriverStore to True only for a targeted rerun | |
| READ-ONLY POLICY: | |
| - No driver install/update/remove | |
| - No adapter binding change | |
| - No service stop/start | |
| - No registry modification | |
| - No dump-setting modification | |
| - No reboot | |
| - No Driver Verifier | |
| - No stress test | |
| "@ | Set-Content -Path $ReportPath -Encoding utf8 | |
| # ============================================================ | |
| # 01 OS / BIOS / BOARD / CPU / MEMORY | |
| # ============================================================ | |
| Write-Section "01 OS / BIOS / BOARD / CPU / MEMORY" { | |
| "----- Operating System -----" | |
| Get-CimInstance Win32_OperatingSystem | | |
| Select-Object Caption,Version,BuildNumber,OSArchitecture, | |
| InstallDate,LastBootUpTime,LocalDateTime, | |
| TotalVisibleMemorySize,FreePhysicalMemory | | |
| Format-List | |
| "----- Windows CurrentVersion registry -----" | |
| Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" | | |
| Select-Object ProductName,DisplayVersion,EditionID, | |
| CurrentBuild,CurrentBuildNumber,UBR, | |
| BuildLab,BuildLabEx,InstallDate | | |
| Format-List | |
| "----- Computer System -----" | |
| Get-CimInstance Win32_ComputerSystem | | |
| Select-Object Manufacturer,Model,SystemType,TotalPhysicalMemory, | |
| HypervisorPresent | | |
| Format-List | |
| "----- BIOS / UEFI -----" | |
| Get-CimInstance Win32_BIOS | | |
| Select-Object Manufacturer,SMBIOSBIOSVersion,Version, | |
| ReleaseDate,SerialNumber | | |
| Format-List | |
| "----- Baseboard -----" | |
| Get-CimInstance Win32_BaseBoard | | |
| Select-Object Manufacturer,Product,Version | | |
| Format-List | |
| "----- CPU -----" | |
| Get-CimInstance Win32_Processor | | |
| Select-Object Name,Manufacturer,NumberOfCores, | |
| NumberOfLogicalProcessors,ProcessorId | | |
| Format-List | |
| "----- Physical Memory -----" | |
| Get-CimInstance Win32_PhysicalMemory | | |
| Select-Object BankLabel,DeviceLocator,Manufacturer, | |
| PartNumber,SerialNumber,Capacity,Speed, | |
| ConfiguredClockSpeed | | |
| Format-Table -AutoSize | |
| } | |
| # ============================================================ | |
| # 02 WINDOWS UPDATE / PACKAGES | |
| # ============================================================ | |
| Write-Section "02 WINDOWS UPDATE / INSTALLED PACKAGES" { | |
| "----- Get-HotFix -----" | |
| Get-HotFix | | |
| Sort-Object InstalledOn -Descending | | |
| Select-Object HotFixID,Description,InstalledOn,InstalledBy | | |
| Format-Table -AutoSize | |
| "----- Installed Windows Packages -----" | |
| if (Get-Command Get-WindowsPackage -ErrorAction SilentlyContinue) { | |
| Get-WindowsPackage -Online | | |
| Where-Object { $_.PackageState -eq "Installed" } | | |
| Sort-Object InstallTime -Descending | | |
| Select-Object PackageName,PackageState,ReleaseType,InstallTime | | |
| Format-Table -AutoSize | |
| } | |
| else { | |
| "Get-WindowsPackage unavailable." | |
| } | |
| } | |
| # ============================================================ | |
| # 03 CRASH DUMP SETTINGS / DUMP FILES / LIVEKERNELREPORTS | |
| # ============================================================ | |
| Write-Section "03 CRASH DUMP SETTINGS / DUMP FILES / LIVEKERNELREPORTS" { | |
| "----- CrashControl -----" | |
| Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\CrashControl" | | |
| Select-Object CrashDumpEnabled,DumpFile,MinidumpDir, | |
| LogEvent,AutoReboot,Overwrite, | |
| AlwaysKeepMemoryDump,FilterPages, | |
| AutomaticManagedPagefile | | |
| Format-List | |
| "----- Pagefile -----" | |
| Get-CimInstance Win32_PageFileSetting | Format-List | |
| Get-CimInstance Win32_PageFileUsage | Format-List | |
| "----- Minidumps / MEMORY.DMP -----" | |
| $DumpList = @() | |
| if (Test-Path "$env:windir\MEMORY.DMP") { | |
| $DumpList += Get-Item "$env:windir\MEMORY.DMP" | |
| } | |
| $CrashControlForPaths = Get-ItemProperty ` | |
| "HKLM:\SYSTEM\CurrentControlSet\Control\CrashControl" ` | |
| -ErrorAction SilentlyContinue | |
| $MiniDumpDirs = @( | |
| "$env:windir\Minidump", | |
| "$env:windir\Minidumps" | |
| ) | |
| if ($CrashControlForPaths.MinidumpDir) { | |
| $MiniDumpDirs += [Environment]::ExpandEnvironmentVariables( | |
| [string]$CrashControlForPaths.MinidumpDir | |
| ) | |
| } | |
| foreach ($MiniDumpDir in ($MiniDumpDirs | Where-Object { $_ } | Select-Object -Unique)) { | |
| if (Test-Path $MiniDumpDir) { | |
| "Scanning minidump directory: $MiniDumpDir" | |
| $DumpList += Get-ChildItem ` | |
| (Join-Path $MiniDumpDir "*.dmp") ` | |
| -ErrorAction SilentlyContinue | |
| } | |
| } | |
| $DumpList | | |
| Sort-Object FullName -Unique | | |
| Sort-Object LastWriteTime -Descending | | |
| Select-Object FullName,Length,CreationTime,LastWriteTime | | |
| Format-Table -AutoSize | |
| "----- Dump type interpretation -----" | |
| $CrashControl = Get-ItemProperty ` | |
| "HKLM:\SYSTEM\CurrentControlSet\Control\CrashControl" ` | |
| -ErrorAction SilentlyContinue | |
| $DumpTypeName = switch ($CrashControl.CrashDumpEnabled) { | |
| 0 { "None" } | |
| 1 { "Complete memory dump" } | |
| 2 { "Kernel memory dump" } | |
| 3 { "Small memory dump" } | |
| 7 { "Automatic memory dump" } | |
| default { "Unknown / other ($($CrashControl.CrashDumpEnabled))" } | |
| } | |
| "CrashDumpEnabled = $($CrashControl.CrashDumpEnabled) : $DumpTypeName" | |
| if ($CrashControl.CrashDumpEnabled -eq 3) { | |
| "NOTE: Small/Triage dumps may omit third-party code/data pages and much of the kernel stack." | |
| } | |
| "----- BugCheck event dump references vs current files -----" | |
| $RecentBugChecks = Get-WinEvent ` | |
| -FilterHashtable @{ | |
| LogName = "System" | |
| ProviderName = "Microsoft-Windows-WER-SystemErrorReporting" | |
| Id = 1001 | |
| StartTime = $EventStart | |
| EndTime = $EventEnd | |
| } ` | |
| -ErrorAction SilentlyContinue | | |
| Sort-Object TimeCreated -Descending | | |
| Select-Object -First 20 | |
| $BugCheckRefs = foreach ($B in $RecentBugChecks) { | |
| $Msg = [string]$B.Message | |
| $BugCodeMatch = [regex]::Match( | |
| $Msg, | |
| '(?i)0x[0-9a-f]{8}' | |
| ) | |
| $DumpPathMatch = [regex]::Match( | |
| $Msg, | |
| '(?i)([A-Z]:\\[^。;\r\n]+?\.dmp)' | |
| ) | |
| $DumpPath = if ($DumpPathMatch.Success) { | |
| $DumpPathMatch.Groups[1].Value | |
| } else { | |
| "" | |
| } | |
| [pscustomobject]@{ | |
| TimeCreated = $B.TimeCreated | |
| BugCheck = if ($BugCodeMatch.Success) { | |
| $BugCodeMatch.Value | |
| } else { | |
| "" | |
| } | |
| DumpPath = $DumpPath | |
| ExistsNow = if ($DumpPath) { | |
| Test-Path $DumpPath | |
| } else { | |
| $null | |
| } | |
| } | |
| } | |
| $BugCheckRefs | | |
| Format-Table -AutoSize | |
| "----- LiveKernelReports -----" | |
| if (Test-Path "$env:windir\LiveKernelReports") { | |
| Get-ChildItem "$env:windir\LiveKernelReports" ` | |
| -Recurse ` | |
| -File ` | |
| -ErrorAction SilentlyContinue | | |
| Sort-Object LastWriteTime -Descending | | |
| Select-Object -First 100 FullName,Length,LastWriteTime | | |
| Format-Table -AutoSize | |
| } | |
| else { | |
| "LiveKernelReports directory not found." | |
| } | |
| } | |
| # ============================================================ | |
| # 04 CRASH / POWER / WER EVENTS | |
| # ============================================================ | |
| Write-Section "04 CRASH / POWER / WER EVENTS" { | |
| # CrashTimeを明示していない場合は、直近のBugCheck Event 1001を | |
| # 「フォーカス時刻」として前後WindowMinutes分を見る。 | |
| # 見つからなければ通常のEventStart/EventEndを使う。 | |
| $FocusStart = $EventStart | |
| $FocusEnd = $EventEnd | |
| $FocusReason = "Configured event range" | |
| if (-not $CrashTime) { | |
| $LatestBugCheck = Get-WinEvent ` | |
| -FilterHashtable @{ | |
| LogName = "System" | |
| ProviderName = "Microsoft-Windows-WER-SystemErrorReporting" | |
| Id = 1001 | |
| StartTime = $EventStart | |
| EndTime = $EventEnd | |
| } ` | |
| -ErrorAction SilentlyContinue | | |
| Sort-Object TimeCreated -Descending | | |
| Select-Object -First 1 | |
| if ($LatestBugCheck) { | |
| $FocusStart = $LatestBugCheck.TimeCreated.AddMinutes(-$WindowMinutes) | |
| $FocusEnd = $LatestBugCheck.TimeCreated.AddMinutes($WindowMinutes) | |
| $FocusReason = "Auto-focused around latest BugCheck Event 1001" | |
| } | |
| } | |
| "FocusReason : $FocusReason" | |
| "FocusStart : $FocusStart" | |
| "FocusEnd : $FocusEnd" | |
| "" | |
| "----- System: BugCheck / Kernel-Power / volmgr / EventLog -----" | |
| Get-WinEvent ` | |
| -FilterHashtable @{ | |
| LogName = "System" | |
| StartTime = $FocusStart | |
| EndTime = $FocusEnd | |
| } ` | |
| -ErrorAction SilentlyContinue | | |
| Where-Object { | |
| $_.Id -in 12,13,41,1001,6005,6006,6008,161,162 ` | |
| -or $_.ProviderName -match ` | |
| 'BugCheck|WER-SystemErrorReporting|Kernel-Power|volmgr|EventLog' | |
| } | | |
| Sort-Object TimeCreated | | |
| Select-Object TimeCreated,Id,LevelDisplayName,ProviderName,Message | | |
| Format-List | |
| "----- Application WER: compact logical report groups -----" | |
| "NOTE: WerRecords is the number of WER log records, NOT confirmed crash occurrences." | |
| "Windows may re-log/re-submit old reports many times." | |
| $WerRaw = Get-WinEvent ` | |
| -FilterHashtable @{ | |
| LogName = "Application" | |
| ProviderName = "Windows Error Reporting" | |
| Id = 1001 | |
| StartTime = $EventStart | |
| EndTime = $EventEnd | |
| } ` | |
| -ErrorAction SilentlyContinue | |
| $WerCompact = foreach ($E in $WerRaw) { | |
| $Message = [string]$E.Message | |
| $EventNameMatch = [regex]::Match( | |
| $Message, | |
| '(?mi)^\s*(?:イベント名|Event Name)\s*:\s*(.+?)\s*$' | |
| ) | |
| $EventName = if ($EventNameMatch.Success) { | |
| $EventNameMatch.Groups[1].Value.Trim() | |
| } else { | |
| "" | |
| } | |
| if ($EventName -notmatch 'BlueScreen|LiveKernelEvent|Hardware|Kernel') { | |
| continue | |
| } | |
| $P = @{} | |
| foreach ($N in 1..5) { | |
| $M = [regex]::Match( | |
| $Message, | |
| "(?mi)^\s*P$N\s*:\s*(.*?)\s*$" | |
| ) | |
| $P[$N] = if ($M.Success) { | |
| $M.Groups[1].Value.Trim() | |
| } else { | |
| "" | |
| } | |
| } | |
| [pscustomobject]@{ | |
| TimeCreated = $E.TimeCreated | |
| EventName = $EventName | |
| P1 = $P[1] | |
| P2 = $P[2] | |
| P3 = $P[3] | |
| P4 = $P[4] | |
| P5 = $P[5] | |
| GroupKey = "$EventName|$($P[1])|$($P[2])" | |
| } | |
| } | |
| if ($WerCompact) { | |
| $WerCompact | | |
| Group-Object GroupKey | | |
| ForEach-Object { | |
| $Newest = $_.Group | | |
| Sort-Object TimeCreated -Descending | | |
| Select-Object -First 1 | |
| $Oldest = $_.Group | | |
| Sort-Object TimeCreated | | |
| Select-Object -First 1 | |
| [pscustomobject]@{ | |
| LastSeen = $Newest.TimeCreated | |
| FirstSeen = $Oldest.TimeCreated | |
| WerRecords = $_.Count | |
| EventName = $Newest.EventName | |
| P1 = $Newest.P1 | |
| P2 = $Newest.P2 | |
| SampleP3 = $Newest.P3 | |
| SampleP4 = $Newest.P4 | |
| SampleP5 = $Newest.P5 | |
| } | |
| } | | |
| Sort-Object LastSeen -Descending | | |
| Select-Object -First $MaxWerGroups | | |
| Format-Table -AutoSize | |
| } | |
| else { | |
| "No BlueScreen / LiveKernelEvent style WER records found in range." | |
| } | |
| "----- Application Error: newest only -----" | |
| Get-WinEvent ` | |
| -FilterHashtable @{ | |
| LogName = "Application" | |
| ProviderName = "Application Error" | |
| StartTime = $EventStart | |
| EndTime = $EventEnd | |
| } ` | |
| -ErrorAction SilentlyContinue | | |
| Sort-Object TimeCreated -Descending | | |
| Select-Object -First $MaxApplicationErrors ` | |
| TimeCreated,Id,LevelDisplayName,ProviderName,Message | | |
| Format-List | |
| } | |
| # ============================================================ | |
| # 05 SYSTEM CRITICAL / ERROR EVENTS - GENERIC | |
| # ============================================================ | |
| Write-Section "05 SYSTEM CRITICAL / ERROR EVENTS - GENERIC" { | |
| Get-WinEvent ` | |
| -FilterHashtable @{ | |
| LogName = "System" | |
| StartTime = $EventStart | |
| EndTime = $EventEnd | |
| Level = 1,2 | |
| } ` | |
| -ErrorAction SilentlyContinue | | |
| Sort-Object TimeCreated | | |
| Select-Object TimeCreated,Id,LevelDisplayName,ProviderName,Message | | |
| Format-List | |
| } | |
| # ============================================================ | |
| # 06 WHEA / CPU / MEMORY HARDWARE SIGNALS | |
| # ============================================================ | |
| Write-Section "06 WHEA / CPU / MEMORY HARDWARE SIGNALS" { | |
| "----- WHEA-Logger -----" | |
| Get-WinEvent ` | |
| -FilterHashtable @{ | |
| LogName = "System" | |
| ProviderName = "Microsoft-Windows-WHEA-Logger" | |
| StartTime = $EventStart | |
| EndTime = $EventEnd | |
| } ` | |
| -ErrorAction SilentlyContinue | | |
| Sort-Object TimeCreated | | |
| Select-Object TimeCreated,Id,LevelDisplayName,Message | | |
| Format-List | |
| "----- MemoryDiagnostics-Results -----" | |
| Get-WinEvent ` | |
| -FilterHashtable @{ | |
| LogName = "System" | |
| ProviderName = "Microsoft-Windows-MemoryDiagnostics-Results" | |
| StartTime = (Get-Date).AddDays(-90) | |
| EndTime = Get-Date | |
| } ` | |
| -ErrorAction SilentlyContinue | | |
| Sort-Object TimeCreated -Descending | | |
| Select-Object -First 20 TimeCreated,Id,LevelDisplayName,Message | | |
| Format-List | |
| } | |
| # ============================================================ | |
| # 07 ALL PRESENT PROBLEM DEVICES | |
| # ============================================================ | |
| Write-Section "07 ALL PRESENT PNP DEVICES WITH NON-OK STATUS" { | |
| if (Get-Command Get-PnpDevice -ErrorAction SilentlyContinue) { | |
| Get-PnpDevice -PresentOnly | | |
| Where-Object { $_.Status -ne "OK" } | | |
| Sort-Object Class,FriendlyName | | |
| Select-Object Status,Class,FriendlyName,InstanceId,Problem | | |
| Format-Table -AutoSize | |
| } | |
| else { | |
| "Get-PnpDevice unavailable." | |
| } | |
| } | |
| # ============================================================ | |
| # 08 IMPORTANT PNP DEVICE / DRIVER INVENTORY | |
| # ============================================================ | |
| Write-Section "08 IMPORTANT PNP DEVICE / DRIVER INVENTORY" { | |
| $Drivers = Get-CimInstance Win32_PnPSignedDriver | |
| "----- DISPLAY -----" | |
| $Drivers | | |
| Where-Object { $_.DeviceClass -match '^DISPLAY$' } | | |
| Select-Object DeviceName,Manufacturer,DriverProviderName, | |
| DriverVersion,DriverDate,InfName,IsSigned,DeviceID | | |
| Format-Table -AutoSize | |
| "----- MEDIA / AUDIO -----" | |
| $Drivers | | |
| Where-Object { $_.DeviceClass -match '^MEDIA$' } | | |
| Select-Object DeviceName,Manufacturer,DriverProviderName, | |
| DriverVersion,DriverDate,InfName,IsSigned,DeviceID | | |
| Format-Table -AutoSize | |
| "----- NETWORK -----" | |
| $Drivers | | |
| Where-Object { $_.DeviceClass -match '^NET$' } | | |
| Select-Object DeviceName,Manufacturer,DriverProviderName, | |
| DriverVersion,DriverDate,InfName,IsSigned,DeviceID | | |
| Format-Table -AutoSize | |
| "----- STORAGE / CONTROLLERS -----" | |
| $Drivers | | |
| Where-Object { | |
| $_.DeviceClass -match ` | |
| 'HDC|SCSIADAPTER|STORAGE|DISKDRIVE|CDROM' | |
| } | | |
| Select-Object DeviceName,DeviceClass,Manufacturer, | |
| DriverProviderName,DriverVersion,DriverDate, | |
| InfName,IsSigned,DeviceID | | |
| Format-Table -AutoSize | |
| "----- USB / BLUETOOTH -----" | |
| $Drivers | | |
| Where-Object { | |
| $_.DeviceClass -match 'USB|BLUETOOTH' | |
| } | | |
| Select-Object DeviceName,DeviceClass,Manufacturer, | |
| DriverProviderName,DriverVersion,DriverDate, | |
| InfName,IsSigned,DeviceID | | |
| Format-Table -AutoSize | |
| "----- SYSTEM / PCI / CHIPSET-LIKE -----" | |
| $Drivers | | |
| Where-Object { | |
| $_.DeviceClass -match '^SYSTEM$' | |
| } | | |
| Select-Object DeviceName,Manufacturer,DriverProviderName, | |
| DriverVersion,DriverDate,InfName,IsSigned,DeviceID | | |
| Format-Table -AutoSize | |
| } | |
| # ============================================================ | |
| # 09 THIRD-PARTY DRIVER PACKAGES | |
| # ============================================================ | |
| Write-Section "09 THIRD-PARTY DRIVER PACKAGES" { | |
| "----- Present third-party PnP drivers (compact) -----" | |
| Get-CimInstance Win32_PnPSignedDriver | | |
| Where-Object { | |
| $_.InfName -like "oem*.inf" ` | |
| -and $_.DriverProviderName ` | |
| -and $_.DriverProviderName -notmatch '^Microsoft($| Corporation$| Windows$)' | |
| } | | |
| Sort-Object DriverProviderName,DeviceClass,DeviceName | | |
| Select-Object DeviceClass,DeviceName,DriverProviderName, | |
| DriverVersion,DriverDate,InfName,IsSigned | | |
| Format-Table -AutoSize | |
| "----- Full Driver Store (pnputil) -----" | |
| if ($IncludeFullDriverStore) { | |
| pnputil /enum-drivers 2>&1 | Out-String -Width 600 | |
| } | |
| else { | |
| "Skipped by default. Set `$IncludeFullDriverStore = `$true for a targeted rerun." | |
| } | |
| } | |
| # ============================================================ | |
| # 10 RUNNING KERNEL / FILESYSTEM DRIVERS | |
| # ============================================================ | |
| Write-Section "10 RUNNING KERNEL / FILESYSTEM DRIVERS" { | |
| Get-CimInstance Win32_SystemDriver | | |
| Where-Object { $_.State -eq "Running" } | | |
| Sort-Object Name | | |
| Select-Object Name,DisplayName,State,StartMode, | |
| PathName,ServiceType | | |
| Format-Table -AutoSize | |
| } | |
| # ============================================================ | |
| # 11 FILTER DRIVERS | |
| # ============================================================ | |
| Write-Section "11 FILTER DRIVERS - FLTMC" { | |
| "----- fltmc filters -----" | |
| fltmc filters 2>&1 | Out-String -Width 600 | |
| "----- fltmc instances -----" | |
| fltmc instances 2>&1 | Out-String -Width 600 | |
| } | |
| # ============================================================ | |
| # 12 STORAGE SNAPSHOT | |
| # ============================================================ | |
| Write-Section "12 STORAGE SNAPSHOT" { | |
| "----- Get-Disk -----" | |
| if (Get-Command Get-Disk -ErrorAction SilentlyContinue) { | |
| Get-Disk | | |
| Select-Object Number,FriendlyName,SerialNumber, | |
| BusType,PartitionStyle,OperationalStatus, | |
| HealthStatus,Size,IsBoot,IsSystem | | |
| Format-Table -AutoSize | |
| } | |
| "----- Get-PhysicalDisk -----" | |
| if (Get-Command Get-PhysicalDisk -ErrorAction SilentlyContinue) { | |
| $PhysicalDisks = Get-PhysicalDisk | |
| $PhysicalDisks | | |
| Select-Object FriendlyName,SerialNumber,MediaType, | |
| BusType,HealthStatus,OperationalStatus, | |
| Size,FirmwareVersion | | |
| Format-Table -AutoSize | |
| "----- Storage reliability counters (if supported) -----" | |
| foreach ($pd in $PhysicalDisks) { | |
| try { | |
| $pd | Get-StorageReliabilityCounter | | |
| Select-Object DeviceId,Temperature,TemperatureMax, | |
| ReadErrorsTotal,ReadErrorsUncorrected, | |
| WriteErrorsTotal,WriteErrorsUncorrected, | |
| Wear,PowerOnHours,StartStopCycleCount | | |
| Format-List | |
| } | |
| catch { | |
| "Reliability counters unavailable for $($pd.FriendlyName)" | |
| } | |
| } | |
| } | |
| "----- Storage-related System events -----" | |
| Get-WinEvent ` | |
| -FilterHashtable @{ | |
| LogName = "System" | |
| StartTime = $EventStart | |
| EndTime = $EventEnd | |
| } ` | |
| -ErrorAction SilentlyContinue | | |
| Where-Object { | |
| $_.ProviderName -match ` | |
| 'disk|storahci|stornvme|storport|Ntfs|volmgr|partmgr|spaceport|iaStor|nvme' | |
| } | | |
| Sort-Object TimeCreated | | |
| Select-Object TimeCreated,Id,LevelDisplayName,ProviderName,Message | | |
| Format-List | |
| } | |
| # ============================================================ | |
| # 13 GPU / DISPLAY SNAPSHOT | |
| # ============================================================ | |
| Write-Section "13 GPU / DISPLAY SNAPSHOT" { | |
| "----- Video Controllers -----" | |
| Get-CimInstance Win32_VideoController | | |
| Select-Object Name,AdapterCompatibility,DriverVersion, | |
| DriverDate,PNPDeviceID,AdapterRAM, | |
| VideoProcessor,Status | | |
| Format-List | |
| "----- Display/GPU-related System events -----" | |
| Get-WinEvent ` | |
| -FilterHashtable @{ | |
| LogName = "System" | |
| StartTime = $EventStart | |
| EndTime = $EventEnd | |
| } ` | |
| -ErrorAction SilentlyContinue | | |
| Where-Object { | |
| $_.ProviderName -match ` | |
| 'Display|nvlddmkm|amdkmdag|amdwddmg|igfx|Intel.*Graphics' | |
| } | | |
| Sort-Object TimeCreated | | |
| Select-Object TimeCreated,Id,LevelDisplayName,ProviderName,Message | | |
| Format-List | |
| } | |
| # ============================================================ | |
| # 14 AUDIO SNAPSHOT | |
| # ============================================================ | |
| Write-Section "14 AUDIO SNAPSHOT" { | |
| "----- Sound Devices -----" | |
| Get-CimInstance Win32_SoundDevice | | |
| Select-Object Name,Manufacturer,PNPDeviceID,Status | | |
| Format-List | |
| "----- MEDIA-class signed drivers -----" | |
| Get-CimInstance Win32_PnPSignedDriver | | |
| Where-Object { $_.DeviceClass -eq "MEDIA" } | | |
| Select-Object DeviceName,Manufacturer,DriverProviderName, | |
| DriverVersion,DriverDate,InfName,IsSigned,DeviceID | | |
| Format-List | |
| } | |
| # ============================================================ | |
| # 15 USB / CONTROLLER SNAPSHOT | |
| # ============================================================ | |
| Write-Section "15 USB / CONTROLLER SNAPSHOT" { | |
| "----- USB Controllers -----" | |
| Get-CimInstance Win32_USBController | | |
| Select-Object Name,Manufacturer,PNPDeviceID,Status | | |
| Format-List | |
| "----- Present USB devices -----" | |
| if (Get-Command Get-PnpDevice -ErrorAction SilentlyContinue) { | |
| Get-PnpDevice -PresentOnly | | |
| Where-Object { $_.Class -match 'USB' } | | |
| Select-Object Status,Class,FriendlyName,InstanceId,Problem | | |
| Format-Table -AutoSize | |
| } | |
| } | |
| # ============================================================ | |
| # 16 NETWORK SNAPSHOT - GENERIC | |
| # ============================================================ | |
| Write-Section "16 NETWORK SNAPSHOT - GENERIC" { | |
| "----- Adapters -----" | |
| Get-NetAdapter -IncludeHidden | | |
| Sort-Object Name | | |
| Select-Object Name,InterfaceDescription,Status,LinkSpeed, | |
| MacAddress,DriverInformation,DriverFileName, | |
| NdisVersion,ifIndex | | |
| Format-Table -AutoSize | |
| "----- All Bindings -----" | |
| Get-NetAdapterBinding -AllBindings | | |
| Sort-Object Name,DisplayName | | |
| Select-Object Name,InterfaceDescription,DisplayName, | |
| ComponentID,Enabled | | |
| Format-Table -AutoSize | |
| "----- IP Configuration -----" | |
| Get-NetIPConfiguration | | |
| Select-Object InterfaceAlias,InterfaceDescription, | |
| NetProfile,IPv4Address,IPv6Address, | |
| IPv4DefaultGateway,DNSServer | | |
| Format-List | |
| "----- Network-related System events -----" | |
| Get-WinEvent ` | |
| -FilterHashtable @{ | |
| LogName = "System" | |
| StartTime = $EventStart | |
| EndTime = $EventEnd | |
| } ` | |
| -ErrorAction SilentlyContinue | | |
| Where-Object { | |
| $_.ProviderName -match ` | |
| 'NDIS|Tcpip|Netwtw|WLAN|e2f|e2fn|rtwl|Realtek|NetAdapter' | |
| } | | |
| Sort-Object TimeCreated | | |
| Select-Object TimeCreated,Id,LevelDisplayName,ProviderName,Message | | |
| Format-List | |
| } | |
| # ============================================================ | |
| # 17 OPTIONAL NETWORK FILTER / VPN DETAIL | |
| # ============================================================ | |
| Write-Section "17 OPTIONAL NETWORK FILTER / VPN DETAIL" { | |
| "----- Relevant services/drivers if present -----" | |
| Get-CimInstance Win32_SystemDriver | | |
| Where-Object { | |
| $_.Name -match ` | |
| 'Netwtw|SeLow|Neo|pxwfp|vpn|wireguard|^tap|wintun' ` | |
| -or $_.DisplayName -match ` | |
| 'Wi-Fi|SoftEther|WireGuard|TAP|VPN' | |
| } | | |
| Sort-Object Name | | |
| Select-Object Name,DisplayName,State,StartMode, | |
| PathName,ServiceType | | |
| Format-List | |
| "----- SoftEther LocalBridge config, if installed -----" | |
| $SoftEtherConfig = "C:\Program Files\SoftEther VPN Server\vpn_server.config" | |
| if (Test-Path $SoftEtherConfig) { | |
| Get-Item $SoftEtherConfig | | |
| Select-Object FullName,Length,LastWriteTime | | |
| Format-List | |
| Select-String ` | |
| -Path $SoftEtherConfig ` | |
| -Pattern ` | |
| 'LocalBridge|EnableSoftEtherKernelModeDriver|ShowAllInterfaces|DeviceName|HubName|LimitBroadcast|MonitorMode|NoPromiscuousMode' ` | |
| -Context 2,3 | | |
| ForEach-Object { $_.ToString() } | |
| } | |
| else { | |
| "SoftEther vpn_server.config not found." | |
| } | |
| "----- WFP relevant matches -----" | |
| if (-not $IncludeWfpDetail) { | |
| 'Skipped by default. Set `$IncludeWfpDetail = `$true for a targeted network/WFP rerun.' | |
| } | |
| else { | |
| $TempWfp = Join-Path $env:TEMP ("BSOD_WFP_" + $Stamp + ".xml") | |
| try { | |
| netsh wfp show state file="$TempWfp" 2>&1 | | |
| Out-String -Width 600 | |
| if (Test-Path $TempWfp) { | |
| $Patterns = @( | |
| 'PacketiX VPN IPsec WFP Callout', | |
| 'pxwfp', | |
| 'SeLow', | |
| 'Neo6', | |
| 'Netwtw', | |
| 'WireGuard', | |
| 'Wintun' | |
| ) | |
| Select-String ` | |
| -Path $TempWfp ` | |
| -Pattern $Patterns ` | |
| -Context 4,8 | | |
| ForEach-Object { $_.ToString() } | |
| Remove-Item $TempWfp -Force -ErrorAction SilentlyContinue | |
| } | |
| else { | |
| "WFP state file was not created." | |
| } | |
| } | |
| catch { | |
| "WFP collection error: $($_.Exception.Message)" | |
| if (Test-Path $TempWfp) { | |
| Remove-Item $TempWfp -Force -ErrorAction SilentlyContinue | |
| } | |
| } | |
| } | |
| } | |
| # ============================================================ | |
| # 18 HYPER-V / VBS / SECURITY VIRTUALIZATION | |
| # ============================================================ | |
| Write-Section "18 HYPER-V / VBS / SECURITY VIRTUALIZATION" { | |
| "----- Hypervisor -----" | |
| Get-CimInstance Win32_ComputerSystem | | |
| Select-Object Manufacturer,Model,HypervisorPresent | | |
| Format-List | |
| "----- Device Guard / VBS -----" | |
| try { | |
| Get-CimInstance ` | |
| -Namespace "root\Microsoft\Windows\DeviceGuard" ` | |
| -ClassName Win32_DeviceGuard | | |
| Format-List * | |
| } | |
| catch { | |
| "Win32_DeviceGuard unavailable: $($_.Exception.Message)" | |
| } | |
| "----- Hyper-V feature -----" | |
| if (Get-Command Get-WindowsOptionalFeature -ErrorAction SilentlyContinue) { | |
| Get-WindowsOptionalFeature ` | |
| -Online ` | |
| -FeatureName Microsoft-Hyper-V-All ` | |
| -ErrorAction SilentlyContinue | | |
| Select-Object FeatureName,State | | |
| Format-List | |
| } | |
| "----- powercfg /a -----" | |
| powercfg /a 2>&1 | Out-String -Width 600 | |
| } | |
| # ============================================================ | |
| # 19 RELIABILITY MONITOR DATA | |
| # ============================================================ | |
| Write-Section "19 RELIABILITY MONITOR DATA" { | |
| try { | |
| Get-CimInstance Win32_ReliabilityRecords | | |
| Where-Object { | |
| $_.TimeGenerated -ge $EventStart ` | |
| -and $_.TimeGenerated -le $EventEnd ` | |
| -and $_.SourceName -notmatch 'WindowsUpdateClient' ` | |
| -and $_.ProductName -notmatch 'Microsoft Defender Antivirus.*セキュリティ インテリジェンス|Microsoft Defender Antivirus.*Security Intelligence' | |
| } | | |
| Sort-Object TimeGenerated -Descending | | |
| Select-Object -First $MaxReliabilityRecords ` | |
| TimeGenerated,SourceName,ProductName, | |
| EventIdentifier,Message | | |
| Format-List | |
| } | |
| catch { | |
| "Win32_ReliabilityRecords unavailable: $($_.Exception.Message)" | |
| } | |
| } | |
| # ============================================================ | |
| # 20 SETUPAPI DEVICE INSTALL LOG - TAIL | |
| # ============================================================ | |
| Write-Section "20 SETUPAPI DEVICE INSTALL LOG - TAIL" { | |
| $SetupApi = "$env:windir\INF\setupapi.dev.log" | |
| if (Test-Path $SetupApi) { | |
| "File: $SetupApi" | |
| "LastWriteTime: $((Get-Item $SetupApi).LastWriteTime)" | |
| "Showing last $SetupApiTailLines lines:" | |
| "" | |
| Get-Content $SetupApi -Tail $SetupApiTailLines -ErrorAction SilentlyContinue | |
| } | |
| else { | |
| "setupapi.dev.log not found." | |
| } | |
| } | |
| # ============================================================ | |
| # 21 QUICK SUMMARY | |
| # ============================================================ | |
| Write-Section "21 QUICK SUMMARY" { | |
| "----- OS / last boot -----" | |
| Get-CimInstance Win32_OperatingSystem | | |
| Select-Object Caption,Version,BuildNumber,LastBootUpTime | | |
| Format-List | |
| "----- Exact Windows build (registry) -----" | |
| Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" | | |
| Select-Object ProductName,DisplayVersion,CurrentBuildNumber,UBR,BuildLabEx | | |
| Format-List | |
| "----- BIOS -----" | |
| Get-CimInstance Win32_BIOS | | |
| Select-Object Manufacturer,SMBIOSBIOSVersion,ReleaseDate | | |
| Format-List | |
| "----- Problem devices -----" | |
| if (Get-Command Get-PnpDevice -ErrorAction SilentlyContinue) { | |
| Get-PnpDevice -PresentOnly | | |
| Where-Object { $_.Status -ne "OK" } | | |
| Select-Object Status,Class,FriendlyName,Problem | | |
| Format-Table -AutoSize | |
| } | |
| "----- Newest dumps -----" | |
| $QuickDumpList = @() | |
| $QuickCrashControl = Get-ItemProperty ` | |
| "HKLM:\SYSTEM\CurrentControlSet\Control\CrashControl" ` | |
| -ErrorAction SilentlyContinue | |
| $QuickMiniDumpDirs = @( | |
| "$env:windir\Minidump", | |
| "$env:windir\Minidumps" | |
| ) | |
| if ($QuickCrashControl.MinidumpDir) { | |
| $QuickMiniDumpDirs += [Environment]::ExpandEnvironmentVariables( | |
| [string]$QuickCrashControl.MinidumpDir | |
| ) | |
| } | |
| foreach ($QuickMiniDumpDir in ($QuickMiniDumpDirs | Select-Object -Unique)) { | |
| if (Test-Path $QuickMiniDumpDir) { | |
| $QuickDumpList += Get-ChildItem ` | |
| (Join-Path $QuickMiniDumpDir "*.dmp") ` | |
| -ErrorAction SilentlyContinue | |
| } | |
| } | |
| if (Test-Path "$env:windir\MEMORY.DMP") { | |
| $QuickDumpList += Get-Item "$env:windir\MEMORY.DMP" | |
| } | |
| $QuickDumpList | | |
| Sort-Object FullName -Unique | | |
| Sort-Object LastWriteTime -Descending | | |
| Select-Object -First 15 FullName,Length,LastWriteTime | | |
| Format-Table -AutoSize | |
| "----- Recent WHEA -----" | |
| Get-WinEvent ` | |
| -FilterHashtable @{ | |
| LogName = "System" | |
| ProviderName = "Microsoft-Windows-WHEA-Logger" | |
| StartTime = $EventStart | |
| EndTime = $EventEnd | |
| } ` | |
| -ErrorAction SilentlyContinue | | |
| Select-Object TimeCreated,Id,LevelDisplayName,Message | | |
| Format-List | |
| } | |
| # ============================================================ | |
| # 22 GENERIC WINDBG CHECKLIST | |
| # ============================================================ | |
| Write-Section "22 GENERIC WINDBG CHECKLIST - COPY INTO WINDBG" { | |
| @' | |
| [まず全BSOD共通] | |
| !analyze -v | |
| .bugcheck | |
| .time | |
| !uptime | |
| vertarget | |
| r | |
| !thread | |
| kv | |
| lm t n | |
| !blackboxbsd | |
| !blackboxntfs | |
| !blackboxpnp | |
| !blackboxwinlogon | |
| [0x7F / Arg1=8 / STACK_OVERFLOW] | |
| !thread | |
| !stackusage | |
| Stack Base / Stack Limit / Current と fault RSP を比較。 | |
| raw stack: | |
| dps <RSP付近> L100 | |
| 同一driver-rangeのpointerが大量にあれば候補。 | |
| ただし code pointer = return address確定ではない。 | |
| code pageがdumpにある場合だけ: | |
| ub <candidate-address> L10 | |
| [0x124 / WHEA_UNCORRECTABLE_ERROR] | |
| !analyze -v | |
| Arg2がWHEA_ERROR_RECORDなら: | |
| !errrec <Arg2> | |
| Windows側レポートのWHEA-Loggerも確認。 | |
| [0x9F / DRIVER_POWER_STATE_FAILURE] | |
| !analyze -v | |
| !poaction | |
| 解析結果にIRP addressが出た場合: | |
| !irp <IRP-address> | |
| device objectが分かれば: | |
| !devstack <device-object> | |
| [0xD1 / 0xA / 0x50 / 0x3B / 0x1E 等] | |
| !analyze -v | |
| kv | |
| faulting RIP: | |
| ln <RIP> | |
| u <RIP-20> <RIP+40> | |
| 該当module: | |
| lmvm <module> | |
| [Network / NDIS疑い] | |
| !ndiskd.netadapter | |
| !ndiskd.filter | |
| !ndiskd.protocol | |
| 特定adapter: | |
| !ndiskd.netadapter <handle> | |
| 特定protocol open: | |
| !ndiskd.mopen <handle> | |
| [Storage疑い] | |
| !blackboxntfs | |
| stack/module名: | |
| storport | |
| stornvme | |
| storahci | |
| disk | |
| ntfs | |
| volmgr | |
| iaStor* | |
| 等を確認。 | |
| [GPU疑い] | |
| lm t n | |
| 以下のようなmoduleを確認: | |
| nvlddmkm | |
| amdkmdag | |
| igdkmd* | |
| dxgkrnl | |
| watchdog | |
| 該当module: | |
| lmvm <module> | |
| [Audio / USB / その他driver疑い] | |
| !blackboxpnp | |
| lm t n | |
| kv | |
| faulting moduleが分かれば: | |
| lmvm <module> | |
| [重要] | |
| Small/Triage Dumpでは、 | |
| third-party code/data pageや完全なstackが入っていないことがある。 | |
| 読めないページを延々追うより、 | |
| 次回用に Automatic / Kernel Memory Dump を検討する。 | |
| '@ | |
| } | |
| # ============================================================ | |
| # 完了 | |
| # ============================================================ | |
| Write-Line "" | |
| Write-Line "================================================================================" | |
| Write-Line "COLLECTION COMPLETE" | |
| Write-Line "================================================================================" | |
| Write-Line ("Finished: " + (Get-Date -Format "yyyy-MM-dd HH:mm:ss zzz")) | |
| Write-Line "No system configuration was changed." | |
| Write-Host "" | |
| Write-Host "============================================================" -ForegroundColor Green | |
| Write-Host " 汎用 BSOD 診断情報の採取完了" -ForegroundColor Green | |
| Write-Host "============================================================" -ForegroundColor Green | |
| Write-Host "" | |
| Write-Host "出力ファイル:" -ForegroundColor Yellow | |
| Write-Host $ReportPath -ForegroundColor Cyan | |
| Write-Host "" | |
| Write-Host "このTXT 1枚をそのままAIへ渡せます。" -ForegroundColor Yellow | |
| Write-Host "dump本体(.dmp)は必要に応じて別途渡してください。" -ForegroundColor Yellow | |
| Write-Host "" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment