CYBERDUDEBIVASH Native NVMe Validation Script to help you verify if your servers have successfully transitioned to the new StorMQ path? CYBERDUDEBIVASH ENTERPRISE BLUEPRINT

CYBERDUDEBIVASH

 Daily Threat Intel by CyberDudeBivash
Zero-days, exploit breakdowns, IOCs, detection rules & mitigation playbooks.

Follow on LinkedInApps & Security ToolsCYBERDUDEBIVASH PVT LTD WWW.CYBERDUDEBIVASH.COM

<# 

CYBERDUDEBIVASH ENTERPRISE BLUEPRINT

Native NVMe / StorMQ Validation Script (Windows Server 2025)

Goal:

  – Detect NVMe storage controllers & driver stack

  – Capture storage stack related ETW providers availability

  – Validate key NVMe / Storport / stornvme / StorMQ related telemetry

  – Pull relevant Windows event logs for storage path transitions and errors

  – Produce a single JSON + TXT report for audit/change-management

IMPORTANT:

  – “StorMQ path” exposure varies by build, driver, and features.

  – This script collects signals that strongly correlate with the new path, but Microsoft may change naming/telemetry between builds.

  – Use it as a validation pack + evidence artifact for rollout.

Usage:

  1) Run elevated PowerShell

  2) Optional: -OutDir “C:\Temp\NVMeAudit”

  3) Optionally run after enabling native NVMe and reboot.

Example:

  .\CDB-StorMQ-NativeNVMe-Validate.ps1 -OutDir “C:\Temp\CDB_NVMe_Validation”

#>

[CmdletBinding()]

param(

  [string]$OutDir = “$env:SystemDrive\CDB_NVMe_StorMQ_Validation”,

  [switch]$IncludePerfSample,

  [int]$PerfSampleSeconds = 20

)

Set-StrictMode -Version Latest

$ErrorActionPreference = “Stop”

function New-CdbDir {

  param([string]$Path)

  if (-not (Test-Path $Path)) { New-Item -Path $Path -ItemType Directory | Out-Null }

}

function Write-CdbFile {

  param([string]$Path, [string]$Content)

  $Content | Out-File -FilePath $Path -Encoding UTF8

}

function Try-Run {

  param([scriptblock]$Block)

  try { & $Block } catch { return @{ error = $_.Exception.Message } }

}

New-CdbDir -Path $OutDir

$timestamp = Get-Date -Format “yyyyMMdd_HHmmss”

$txtPath = Join-Path $OutDir “CDB_StorMQ_NativeNVMe_Validation_$timestamp.txt”

$jsonPath = Join-Path $OutDir “CDB_StorMQ_NativeNVMe_Validation_$timestamp.json”

$report = [ordered]@{

  meta = [ordered]@{

    generated_at = (Get-Date).ToString(“o”)

    host = $env:COMPUTERNAME

    user = $env:USERNAME

    out_dir = $OutDir

    script = “CDB-StorMQ-NativeNVMe-Validate.ps1”

    version = “1.0”

  }

}

# — OS & build —

$os = Get-CimInstance Win32_OperatingSystem

$cs = Get-CimInstance Win32_ComputerSystem

$report.os = [ordered]@{

  caption = $os.Caption

  version = $os.Version

  build_number = $os.BuildNumber

  install_date = $os.InstallDate

  last_boot = $os.LastBootUpTime

  manufacturer = $cs.Manufacturer

  model = $cs.Model

}

# — Enumerate storage controllers —

$report.storage_controllers = Try-Run {

  $controllers = Get-PnpDevice -Class “SCSIAdapter” -ErrorAction SilentlyContinue

  $nvmeControllers = Get-PnpDevice -Class “System” -ErrorAction SilentlyContinue | Where-Object {

    $_.FriendlyName -match “NVMe|NVM Express|Non-Volatile Memory”

  }

  $stornvme = Get-PnpDevice -ErrorAction SilentlyContinue | Where-Object {

    $_.FriendlyName -match “stornvme|NVM Express Controller|Standard NVM Express”

  }

  [ordered]@{

    scsi_adapter = $controllers | Select-Object FriendlyName, InstanceId, Status, Class, ProblemCode

    nvme_like_system = $nvmeControllers | Select-Object FriendlyName, InstanceId, Status, Class, ProblemCode

    stornvme_hits = $stornvme | Select-Object FriendlyName, InstanceId, Status, Class, ProblemCode

  }

}

# — NVMe disks & mapping to controllers/drivers —

$report.disks = Try-Run {

  $physical = Get-PhysicalDisk | Select-Object FriendlyName, MediaType, BusType, Size, HealthStatus, OperationalStatus

  $disk = Get-Disk | Select-Object Number, FriendlyName, SerialNumber, BusType, PartitionStyle, IsBoot, IsSystem, Size

  [ordered]@{

    physical_disk = $physical

    disk = $disk

  }

}

# — Driver stack evidence —

$report.driver_stack = Try-Run {

  $nvmeDevs = Get-PnpDevice -ErrorAction SilentlyContinue | Where-Object {

    $_.FriendlyName -match “NVMe|NVM Express|Standard NVM Express”

  }

  $drivers = foreach ($d in $nvmeDevs) {

    $drv = Get-PnpDeviceProperty -InstanceId $d.InstanceId -KeyName “DEVPKEY_Device_DriverVersion” -ErrorAction SilentlyContinue

    $inf = Get-PnpDeviceProperty -InstanceId $d.InstanceId -KeyName “DEVPKEY_Device_DriverInfPath” -ErrorAction SilentlyContinue

    [pscustomobject]@{

      Device = $d.FriendlyName

      InstanceId = $d.InstanceId

      DriverVersion = $drv.Data

      DriverInf = $inf.Data

      Status = $d.Status

    }

  }

  $storport = Get-ItemProperty “HKLM:\SYSTEM\CurrentControlSet\Services\storport” -ErrorAction SilentlyContinue

  $stornvmeSvc = Get-ItemProperty “HKLM:\SYSTEM\CurrentControlSet\Services\stornvme” -ErrorAction SilentlyContinue

  [ordered]@{

    nvme_device_drivers = $drivers

    storport_service = $storport

    stornvme_service = $stornvmeSvc

  }

}

# — Feature / registry knobs (best-effort, build dependent) —

# These keys/values may differ across builds. We do best-effort discovery for StorMQ-like indicators.

$report.stormq_indicators = Try-Run {

  $keysToCheck = @(

    “HKLM:\SYSTEM\CurrentControlSet\Services\stornvme”,

    “HKLM:\SYSTEM\CurrentControlSet\Services\storport”,

    “HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4d36e97b-e325-11ce-bfc1-08002be10318}”

  )

  $found = @()

  foreach ($k in $keysToCheck) {

    if (Test-Path $k) {

      $props = Get-ItemProperty $k -ErrorAction SilentlyContinue

      $found += [pscustomobject]@{

        Key = $k

        Properties = ($props.PSObject.Properties | Where-Object { $_.Name -notmatch “^PS” } | ForEach-Object { “$($_.Name)=$($_.Value)” })

      }

    }

  }

  # Search registry for “StorMQ” mentions (limited scope to avoid being slow)

  $stormqMatches = @()

  foreach ($k in $keysToCheck) {

    if (Test-Path $k) {

      $props = Get-ItemProperty $k -ErrorAction SilentlyContinue

      foreach ($p in $props.PSObject.Properties) {

        if ($p.Name -match “StorMQ|MQ|MultiQueue|NativeNVMe|NVMeIo” -or ($p.Value -as [string]) -match “StorMQ|MultiQueue|NativeNVMe”) {

          $stormqMatches += [pscustomobject]@{ Key=$k; Name=$p.Name; Value=$p.Value }

        }

      }

    }

  }

  [ordered]@{

    scanned_keys = $keysToCheck

    key_dumps = $found

    stormq_like_matches = $stormqMatches

    note = “Registry indicators are build/driver dependent; absence does not guarantee feature is off.”

  }

}

# — ETW provider presence (useful to capture evidence) —

$report.etw_providers = Try-Run {

  $providers = logman query providers 2>$null

  $hits = $providers | Select-String -Pattern “storport|stornvme|nvme|storage|disk|classpnp|storsvc” -CaseSensitive:$false

  [ordered]@{

    total_lines = ($providers | Measure-Object).Count

    matched_lines = $hits.Line

  }

}

# — Windows Event Logs: storage-related errors / controller resets —

$report.event_logs = Try-Run {

  $since = (Get-Date).AddDays(-14)

  $filters = @(

    @{ LogName=”System”; ProviderName=”stornvme”; StartTime=$since },

    @{ LogName=”System”; ProviderName=”storport”; StartTime=$since },

    @{ LogName=”System”; ProviderName=”disk”; StartTime=$since },

    @{ LogName=”System”; ProviderName=”Ntfs”; StartTime=$since },

    @{ LogName=”System”; ProviderName=”Microsoft-Windows-Storage-ClassPnP”; StartTime=$since }

  )

  $events = @()

  foreach ($f in $filters) {

    $events += Get-WinEvent -FilterHashtable $f -ErrorAction SilentlyContinue | Select-Object TimeCreated, Id, LevelDisplayName, ProviderName, Message

  }

  # Keep last 200 to avoid huge report

  $events = $events | Sort-Object TimeCreated -Descending | Select-Object -First 200

  [ordered]@{

    window_days = 14

    top_events = $events

  }

}

# — Optional Perf sample: storage CPU + disk latency counters —

if ($IncludePerfSample) {

  $report.perf_sample = Try-Run {

    $counters = @(

      “\Processor(_Total)\% Processor Time”,

      “\Processor Information(_Total)\% DPC Time”,

      “\System\Processor Queue Length”,

      “\PhysicalDisk(_Total)\Avg. Disk sec/Read”,

      “\PhysicalDisk(_Total)\Avg. Disk sec/Write”,

      “\PhysicalDisk(_Total)\Disk Reads/sec”,

      “\PhysicalDisk(_Total)\Disk Writes/sec”,

      “\PhysicalDisk(_Total)\Current Disk Queue Length”

    )

    $sample = Get-Counter -Counter $counters -SampleInterval 1 -MaxSamples $PerfSampleSeconds

    [ordered]@{

      seconds = $PerfSampleSeconds

      counters = $counters

      readings = $sample.CounterSamples | Select-Object Path, CookedValue, TimeStamp

    }

  }

}

# — Generate a simple determination block (best-effort) —

$report.determination = Try-Run {

  $busTypes = @()

  try { $busTypes = (Get-Disk | Select-Object -ExpandProperty BusType -ErrorAction SilentlyContinue | Sort-Object -Unique) } catch {}

  $hasNvmeDisk = $false

  if ($busTypes -contains “NVMe”) { $hasNvmeDisk = $true }

  $driverInfHits = @()

  try {

    $driverInfHits = @($report.driver_stack.nvme_device_drivers | Where-Object { $_.DriverInf -match “stornvme|nvme” })

  } catch {}

  $stormqHint = $false

  try {

    if (($report.stormq_indicators.stormq_like_matches | Measure-Object).Count -gt 0) { $stormqHint = $true }

  } catch {}

  $confidence = “Low”

  if ($hasNvmeDisk -and ($driverInfHits.Count -gt 0)) { $confidence = “Medium” }

  if ($hasNvmeDisk -and ($driverInfHits.Count -gt 0) -and $stormqHint) { $confidence = “High” }

  [ordered]@{

    has_nvme_disk = $hasNvmeDisk

    unique_bus_types = $busTypes

    nvme_driver_inf_hits = $driverInfHits

    stormq_registry_hint = $stormqHint

    confidence = $confidence

    guidance = @(

      “If confidence is Low: verify disks are truly NVMe (BusType=NVMe) and the OS is Windows Server 2025 build supporting Native NVMe.”,

      “If confidence is Medium: you have NVMe and likely stornvme path; next validate performance counters and ETW traces during DiskSpd load.”,

      “If confidence is High: you have NVMe + driver evidence + MQ-like registry hints; archive this JSON as rollout proof and still run a load test.”

    )

  }

}

# — Write TXT report —

$lines = @()

$lines += “CYBERDUDEBIVASH ENTERPRISE BLUEPRINT – Native NVMe / StorMQ Validation”

$lines += “Generated: $($report.meta.generated_at)”

$lines += “Host: $($report.meta.host)”

$lines += “OS: $($report.os.caption)  Version: $($report.os.version)  Build: $($report.os.build_number)”

$lines += “”

$lines += “== Determination (best-effort) ==”

$lines += “Has NVMe Disk: $($report.determination.has_nvme_disk)”

$lines += “Bus Types: $([string]::Join(‘,’, $report.determination.unique_bus_types))”

$lines += “Confidence: $($report.determination.confidence)”

$lines += “StorMQ registry hint: $($report.determination.stormq_registry_hint)”

$lines += “”

$lines += “== NVMe Drivers (summary) ==”

try {

  foreach ($d in $report.driver_stack.nvme_device_drivers) {

    $lines += (“{0} | {1} | {2}” -f $d.Device, $d.DriverVersion, $d.DriverInf)

  }

} catch {

  $lines += “Driver enumeration failed or returned no results.”

}

$lines += “”

$lines += “== Recent Storage Events (last 14 days, top 50) ==”

try {

  $ev = $report.event_logs.top_events | Select-Object -First 50

  foreach ($e in $ev) {

    $lines += (“{0} | {1} | {2} | {3}” -f $e.TimeCreated, $e.ProviderName, $e.Id, $e.LevelDisplayName)

  }

} catch {

  $lines += “No events captured.”

}

Write-CdbFile -Path $txtPath -Content ($lines -join “`r`n”)

# — Write JSON report —

$report | ConvertTo-Json -Depth 8 | Out-File -FilePath $jsonPath -Encoding UTF8

Write-Host “Report saved:”

Write-Host ” – $txtPath”

Write-Host ” – $jsonPath”

Write-Host “”

Write-Host “Next step (recommended): run with -IncludePerfSample and compare before/after enabling Native NVMe.”

CYBERDUDEBIVASH ENTERPRISE BLUEPRINT — How to Use This Script (Correctly)

1) Run it in two phases (before vs after)

  • Phase A (Baseline): Run on Windows Server 2022 / current state
  • Phase B (Native NVMe Enabled): Run after enabling the feature and rebooting
  • Keep both JSON files — they’re your change management proof

2) Add a controlled load test for validation (recommended)

Run a repeatable DiskSpd test on the same volume:

  • Compare CPUIOPS, and tail latency

3) What “Success” should look like

  • The report shows BusType = NVMe
  • NVMe driver stack present (often stornvme in INF)
  • No new storport/stornvme controller resets
  • Under the same DiskSpd load: lower CPU and stable latency

CYBERDUDEBIVASH Services CTA (Enterprise)

Apps & Products hub: https://www.cyberdudebivash.com/apps-products/
Enterprise Contact: https://www.cyberdudebivash.com/contact


#CyberDudeBivash #WindowsServer2025 #NVMe #StorMQ #StoragePerformance #ServerOptimization #HyperV #SRE #PlatformEngineering #EnterpriseIT #DevSecOps #Observability

Leave a comment

Design a site like this with WordPress.com
Get started