mirror of
https://github.com/croit/load-virtio-scsi-on-boot.git
synced 2026-09-24 07:50:08 +01:00
added support for viostor.inf (VirtIO Block)
script now supports using vioscsi.inf and viostor.inf removed a few manual registry changes on Windows versions 2016 and older
This commit is contained in:
@@ -1,34 +1,40 @@
|
||||
Purpose of this script
|
||||
* make Windows load the VirtIO SCSI pass-through driver on boot without reboot or external programs
|
||||
* make Windows load the VirtIO SCSI and/or Block driver on boot without reboot or external programs
|
||||
|
||||
Prerequisites
|
||||
* VirtIO SCSI driver (vioscsi) must be installed **OR** path to the INF-File must be given as argument to the script
|
||||
* Windows 7/8 or Windows Server 2008 or newer versions
|
||||
* VirtIO SCSI driver (vioscsi) must be installed OR path to the INF file must be given as argument
|
||||
* VirtIO Block driver (viostor) must be installed OR path to the INF file must be given as argument
|
||||
* Windows 7/8 or Windows Server 2008
|
||||
|
||||
Remarks
|
||||
* On Windows before Windows Server 2022 and Windows 10 2004 the software device created by the script will not be removed automatically, but this can be done via device manager. It can also be left there, no harm in that.
|
||||
* You should have a backup of your system.
|
||||
* This script was tested
|
||||
* on Windows Server 2025 Standard Edition (24H2)
|
||||
* on Windows Server 2022 Datacenter Edition (21H2)
|
||||
* with virtio drivers version .266, .271, .285
|
||||
* This script was tested only
|
||||
** on Windows Server 2025 Standard Edition (24H2)
|
||||
** on Windows Server 2022 Datacenter Edition (21H2)
|
||||
** with virtio drivers version .266 .271 .285
|
||||
** on Windows Server 2016 Standard Edition
|
||||
** with virtio drivers version .271
|
||||
* nearly all code in here was written by AI
|
||||
|
||||
How to use
|
||||
either
|
||||
* install the ``vioscsi.inf`` before **OR**
|
||||
* tell the script to do it by ``-InfPath`` parameter **OR**
|
||||
* use ``virtio-win-guest-tools.exe /S`` to install it
|
||||
|
||||
* install the vioscsi.inf/viostor.inf before OR
|
||||
* tell the script to do it by -ScsiInfPath and/or -BlockInfPath parameter OR
|
||||
* use virtio-win-guest-tools.exe /S to install it
|
||||
depending on the set security policy it might be required to run the script via
|
||||
``PowerShell /ExecutionPolicy Bypass /File <path-to-this-script-file> [-InfPath <path-to-vioscsi.inf>]``
|
||||
PowerShell /ExecutionPolicy Bypass /File <path-to-this-script-file> [-Driver <scsi|block|both>] [-ScsiInfPath <path>] [-BlockInfPath <path>]
|
||||
|
||||
Driver options:
|
||||
- scsi (default) - Install VirtIO SCSI driver only
|
||||
- block - Install VirtIO Block driver only
|
||||
- both - Install both drivers
|
||||
|
||||
How does the script work?
|
||||
* install the vioscsi driver, if requested
|
||||
* install the driver(s), if requested
|
||||
* create a software based device via Win32-API
|
||||
* add some registry settings
|
||||
* use ``pnputil`` to install the driver for this device
|
||||
* use ``pnputil`` to remove the device
|
||||
|
||||
* use pnputil to install the driver for this device
|
||||
* use pnputil to remove the device
|
||||
The driver-to-device assignment marks the driver for being loaded on boot.
|
||||
Now the Windows is ready for migration to a VirtIO based SCSI disk.
|
||||
Now the Windows is ready for migration to a VirtIO based SCSI or Block disk.
|
||||
|
||||
Executable → Regular
+133
-56
@@ -1,9 +1,10 @@
|
||||
# Purpose of this script
|
||||
# * make Windows load the VirtIO SCSI pass-through driver on boot without reboot or external programs
|
||||
# * make Windows load the VirtIO SCSI and/or Block driver on boot without reboot or external programs
|
||||
#
|
||||
# Prerequisites
|
||||
# * VirtIO SCSI driver (vioscsi) must be installed OR path to the INF-File must be given as argument to the script
|
||||
# * Windows 7/8 or Windows Server 2008 or newer
|
||||
# * VirtIO SCSI driver (vioscsi) must be installed OR path to the INF file must be given as argument
|
||||
# * VirtIO Block driver (viostor) must be installed OR path to the INF file must be given as argument
|
||||
# * Windows 7/8 or Windows Server 2008
|
||||
#
|
||||
# Remarks
|
||||
# * On Windows before Windows Server 2022 and Windows 10 2004 the software device created by the script will not be removed automatically, but this can be done via device manager. It can also be left there, no harm in that.
|
||||
@@ -11,29 +12,38 @@
|
||||
# * This script was tested only
|
||||
# ** on Windows Server 2025 Standard Edition (24H2)
|
||||
# ** on Windows Server 2022 Datacenter Edition (21H2)
|
||||
# ** with virtio drivers version .266, .271, .285
|
||||
# ** with virtio drivers version .266
|
||||
# * nearly all code in here was written by AI
|
||||
#
|
||||
# How to use
|
||||
# either
|
||||
# * install the vioscsi.inf before OR
|
||||
# * tell the script to do it by -InfPath parameter OR
|
||||
# * install the vioscsi.inf/viostor.inf before OR
|
||||
# * tell the script to do it by -ScsiInfPath and/or -BlockInfPath parameter OR
|
||||
# * use virtio-win-guest-tools.exe /S to install it
|
||||
# depending on the set security policy it might be required to run the script via
|
||||
# PowerShell /ExecutionPolicy Bypass /File <path-to-this-script-file> [-InfPath <path-to-vioscsi.inf>]
|
||||
# PowerShell /ExecutionPolicy Bypass /File <path-to-this-script-file> [-Driver <scsi|block|both>] [-ScsiInfPath <path>] [-BlockInfPath <path>]
|
||||
#
|
||||
# Driver options:
|
||||
# - scsi (default) - Install VirtIO SCSI driver only
|
||||
# - block - Install VirtIO Block driver only (requires -BlockInfPath)
|
||||
# - both - Install both drivers (requires -ScsiInfPath and -BlockInfPath)
|
||||
#
|
||||
# How does the script work?
|
||||
# * install the vioscsi driver, if requested
|
||||
# * install the driver(s), if requested
|
||||
# * create a software based device via Win32-API
|
||||
# * add some registry settings
|
||||
# * use pnputil to install the driver for this device
|
||||
# * use pnputil to remove the device
|
||||
# The driver-to-device assignment marks the driver for being loaded on boot.
|
||||
# Now the Windows is ready for migration to a VirtIO based SCSI disk.
|
||||
# Now the Windows is ready for migration to a VirtIO based SCSI or Block disk.
|
||||
|
||||
# ==== PARAMETER ====
|
||||
param(
|
||||
[string]$InfPath = "" # Optional: Path to vioscsi.inf file
|
||||
[string]$InfPath = "",
|
||||
[ValidateSet("scsi", "block", "both")]
|
||||
[string]$Driver = "scsi",
|
||||
[string]$ScsiInfPath = "",
|
||||
[string]$BlockInfPath = ""
|
||||
)
|
||||
|
||||
$source = @"
|
||||
@@ -107,7 +117,7 @@ public class DeviceInstaller
|
||||
IntPtr DeviceInfoSet,
|
||||
ref SP_DEVINFO_DATA DeviceInfoData);
|
||||
|
||||
public static void CreateSoftwareDeviceWithHardwareId(string deviceId, string classGuidStr, string hardwareId)
|
||||
public static void CreateSoftwareDeviceWithHardwareId(string deviceId, string classGuidStr, string hardwareId, string deviceDescription)
|
||||
{
|
||||
Guid classGuid = new Guid(classGuidStr);
|
||||
IntPtr devInfoSet = SetupDiCreateDeviceInfoList(ref classGuid, IntPtr.Zero);
|
||||
@@ -124,7 +134,7 @@ public class DeviceInstaller
|
||||
devInfoData.cbSize = (uint)Marshal.SizeOf(typeof(SP_DEVINFO_DATA));
|
||||
devInfoData.ClassGuid = classGuid;
|
||||
|
||||
if (!SetupDiCreateDeviceInfo(devInfoSet, deviceId, ref classGuid, "VirtIO SCSI Controller", IntPtr.Zero, DICD_GENERATE_ID, ref devInfoData))
|
||||
if (!SetupDiCreateDeviceInfo(devInfoSet, deviceId, ref classGuid, deviceDescription, IntPtr.Zero, DICD_GENERATE_ID, ref devInfoData))
|
||||
{
|
||||
int error = Marshal.GetLastWin32Error();
|
||||
throw new Exception("SetupDiCreateDeviceInfo failed with error " + error);
|
||||
@@ -211,18 +221,62 @@ if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdent
|
||||
# Add compiled class
|
||||
Add-Type -TypeDefinition $source
|
||||
|
||||
$deviceId = "vioscsi"
|
||||
$classGuid = "{4d36e97b-e325-11ce-bfc1-08002be10318}"
|
||||
$hardwareId = "PCI\VEN_1AF4&DEV_1004&SUBSYS_00081AF4&REV_00"
|
||||
$driverConfigs = @{
|
||||
"vioscsi" = @{
|
||||
Name = "vioscsi"
|
||||
HardwareId = "PCI\VEN_1AF4&DEV_1004&SUBSYS_00081AF4&REV_00"
|
||||
HardwareIdShort = "PCI\VEN_1AF4&DEV_1004"
|
||||
RegistryPath = "HKLM:\SOFTWARE\RedHat\Virtio-Win\Components\vioscsi"
|
||||
InfFile = "vioscsi.inf"
|
||||
DeviceDesc = "VirtIO SCSI Controller"
|
||||
DriverDesc = "Red Hat VirtIO SCSI pass-through controller"
|
||||
# InfSection is recorded only in the redundant Control\Class entry below; pnputil
|
||||
# writes the authoritative one, so this value is cosmetic. Confirm against the
|
||||
# actual INF (DDInstall section) if you ever rely on it.
|
||||
InfSection = "scsi_inst"
|
||||
ClassGuid = "{4d36e97b-e325-11ce-bfc1-08002be10318}"
|
||||
InfPathParam = $ScsiInfPath
|
||||
}
|
||||
"viostor" = @{
|
||||
Name = "viostor"
|
||||
HardwareId = "PCI\VEN_1AF4&DEV_1001"
|
||||
HardwareIdShort = "PCI\VEN_1AF4&DEV_1001"
|
||||
RegistryPath = "HKLM:\SOFTWARE\RedHat\Virtio-Win\Components\viostor"
|
||||
InfFile = "viostor.inf"
|
||||
DeviceDesc = "VirtIO Block Controller"
|
||||
DriverDesc = "Red Hat VirtIO SCSI controller"
|
||||
InfSection = "rhelscsi_inst"
|
||||
ClassGuid = "{4d36e97b-e325-11ce-bfc1-08002be10318}"
|
||||
InfPathParam = $BlockInfPath
|
||||
}
|
||||
}
|
||||
|
||||
# Registry path for VirtIO installation
|
||||
$virtioBasePath = "HKLM:\SOFTWARE\RedHat\Virtio-Win\Components\vioscsi"
|
||||
$driversToProcess = @()
|
||||
switch ($Driver) {
|
||||
"scsi" { $driversToProcess += $driverConfigs["vioscsi"] }
|
||||
"block" { $driversToProcess += $driverConfigs["viostor"] }
|
||||
"both" {
|
||||
$driversToProcess += $driverConfigs["vioscsi"]
|
||||
$driversToProcess += $driverConfigs["viostor"]
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($drv in $driversToProcess) {
|
||||
$deviceId = $drv.Name
|
||||
$classGuid = $drv.ClassGuid
|
||||
$hardwareId = $drv.HardwareId
|
||||
$virtioBasePath = $drv.RegistryPath
|
||||
$currentInfPath = if ($drv.InfPathParam) { $drv.InfPathParam } else { $InfPath }
|
||||
|
||||
Write-Host "`n========================================" -ForegroundColor Cyan
|
||||
Write-Host "Processing driver: $($drv.Name)" -ForegroundColor Cyan
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
|
||||
try {
|
||||
# OPTIONAL: Install INF driver first if path provided
|
||||
if ($InfPath -and (Test-Path $InfPath)) {
|
||||
if ($currentInfPath -and (Test-Path $currentInfPath)) {
|
||||
Write-Host "Installing INF driver from provided path..." -ForegroundColor Yellow
|
||||
Write-Host "INF Path: $InfPath" -ForegroundColor Cyan
|
||||
Write-Host "INF Path: $currentInfPath" -ForegroundColor Cyan
|
||||
|
||||
# Check Windows version for correct pnputil syntax
|
||||
$osVersion = [System.Environment]::OSVersion.Version
|
||||
@@ -233,11 +287,11 @@ try {
|
||||
|
||||
try {
|
||||
if ($useNewSyntax) {
|
||||
Write-Host "Executing: pnputil /add-driver `"$InfPath`" /install" -ForegroundColor Gray
|
||||
& pnputil /add-driver "$InfPath" /install
|
||||
Write-Host "Executing: pnputil /add-driver `"$currentInfPath`" /install" -ForegroundColor Gray
|
||||
& pnputil /add-driver "$currentInfPath" /install
|
||||
} else {
|
||||
Write-Host "Executing: pnputil -a -i `"$InfPath`"" -ForegroundColor Gray
|
||||
& pnputil -a -i "$InfPath"
|
||||
Write-Host "Executing: pnputil -a -i `"$currentInfPath`"" -ForegroundColor Gray
|
||||
& pnputil -a -i "$currentInfPath"
|
||||
}
|
||||
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
@@ -252,24 +306,24 @@ try {
|
||||
|
||||
Write-Host "Waiting for driver registration..." -ForegroundColor Cyan
|
||||
Start-Sleep -Seconds 2
|
||||
} elseif ($InfPath) {
|
||||
throw "Provided INF path does not exist: $InfPath"
|
||||
} elseif ($currentInfPath) {
|
||||
throw "Provided INF path does not exist: $currentInfPath"
|
||||
}
|
||||
# Check if VirtIO registry entries exist
|
||||
if (-not (Test-Path $virtioBasePath)) {
|
||||
Write-Host "VirtIO guest tools registry not found, searching DriverDatabase..." -ForegroundColor Yellow
|
||||
|
||||
# Fallback: Search in DriverDatabase for vioscsi.inf
|
||||
# Fallback: Search in DriverDatabase for driver-specific INF
|
||||
$driverDbPath = "HKLM:\SYSTEM\DriverDatabase\DriverPackages"
|
||||
$vioscsiDrivers = Get-ChildItem $driverDbPath | Where-Object { $_.Name -like "*vioscsi.inf*" }
|
||||
$virtioDrivers = Get-ChildItem $driverDbPath | Where-Object { $_.Name -like "*$($drv.InfFile)*" }
|
||||
|
||||
if ($vioscsiDrivers) {
|
||||
if ($virtioDrivers) {
|
||||
# Take the first matching entry
|
||||
$driverEntry = $vioscsiDrivers[0]
|
||||
$driverEntry = $virtioDrivers[0]
|
||||
$oemInfName = (Get-ItemProperty -Path $driverEntry.PSPath).'(default)'
|
||||
|
||||
if ($oemInfName) {
|
||||
Write-Host "Found vioscsi driver in DriverDatabase: $($driverEntry.Name.Split('\')[-1])" -ForegroundColor Cyan
|
||||
Write-Host "Found $($drv.Name) driver in DriverDatabase: $($driverEntry.Name.Split('\')[-1])" -ForegroundColor Cyan
|
||||
Write-Host "OEM INF name: $oemInfName" -ForegroundColor Cyan
|
||||
$oemInf = "$env:windir\INF\$oemInfName"
|
||||
$infFullPath = $oemInf # Set for consistency
|
||||
@@ -277,7 +331,7 @@ try {
|
||||
throw "Could not read OEM INF name from DriverDatabase entry"
|
||||
}
|
||||
} else {
|
||||
throw "VirtIO SCSI driver not found in DriverDatabase. Please install vioscsi.inf or virtio-win-guest-tools.exe first."
|
||||
throw "$($drv.DeviceDesc) driver not found in DriverDatabase. Please install $($drv.InfFile) or virtio-win-guest-tools.exe first."
|
||||
}
|
||||
} else {
|
||||
# Original method: Read from VirtIO guest tools registry
|
||||
@@ -298,7 +352,7 @@ try {
|
||||
# Step 1: Create device
|
||||
Write-Host "`nStep 1: Creating device using Setup API..." -ForegroundColor Yellow
|
||||
|
||||
[DeviceInstaller]::CreateSoftwareDeviceWithHardwareId($deviceId, $classGuid, $hardwareId)
|
||||
[DeviceInstaller]::CreateSoftwareDeviceWithHardwareId($deviceId, $classGuid, $hardwareId, $drv.DeviceDesc)
|
||||
Write-Host "Device created successfully using Setup API!" -ForegroundColor Green
|
||||
|
||||
# Step 2: Assign driver
|
||||
@@ -309,12 +363,20 @@ try {
|
||||
# Find the created device path
|
||||
$devicePath = "HKLM:\SYSTEM\CurrentControlSet\Enum\ROOT\$deviceId\0000"
|
||||
|
||||
# The Enum device-node property writes further down are blocked for Administrators
|
||||
# on Windows Server 2016 (build 14393) - only SYSTEM may write under ...\Enum.
|
||||
# There they error harmlessly because pnputil performs the real driver binding.
|
||||
# On 2019+ (build > 14393) the freshly-created device subkey is writable, so the
|
||||
# writes succeed. Gate them on the build to keep the 2016 run free of SecurityExceptions.
|
||||
$osBuild = [int](Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").CurrentBuildNumber
|
||||
$writeEnumDeviceProps = $osBuild -gt 14393
|
||||
|
||||
if (-not (Test-Path $devicePath)) {
|
||||
Write-Host "Warning: Created device not found at expected path $devicePath" -ForegroundColor Yellow
|
||||
$enumPath = "HKLM:\SYSTEM\CurrentControlSet\Enum\ROOT"
|
||||
$vioscsiDevices = Get-ChildItem $enumPath | Where-Object { $_.Name -like "*vioscsi*" -or $_.Name -like "*$deviceId*" }
|
||||
if ($vioscsiDevices) {
|
||||
$devicePath = $vioscsiDevices[0].PSPath + "\0000"
|
||||
$foundDevices = Get-ChildItem $enumPath | Where-Object { $_.Name -like "*$deviceId*" }
|
||||
if ($foundDevices) {
|
||||
$devicePath = $foundDevices[0].PSPath + "\0000"
|
||||
Write-Host "Found device at: $devicePath" -ForegroundColor Cyan
|
||||
}
|
||||
}
|
||||
@@ -329,10 +391,12 @@ try {
|
||||
|
||||
Write-Host "Checking device registry configuration..." -ForegroundColor Cyan
|
||||
|
||||
# Add only missing values, no overwriting
|
||||
# Add only missing values, no overwriting.
|
||||
# These target the protected Enum device node; only attempt where permitted (2019+).
|
||||
if ($writeEnumDeviceProps) {
|
||||
if (-not $originalProps.Service) {
|
||||
Set-ItemProperty -Path $devicePath -Name "Service" -Value "vioscsi" -Type String
|
||||
Write-Host "Added Service: vioscsi" -ForegroundColor Green
|
||||
Set-ItemProperty -Path $devicePath -Name "Service" -Value $drv.Name -Type String
|
||||
Write-Host "Added Service: $($drv.Name)" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "Service already set: $($originalProps.Service)" -ForegroundColor Cyan
|
||||
}
|
||||
@@ -345,7 +409,7 @@ try {
|
||||
}
|
||||
|
||||
if (-not $originalProps.DeviceDesc) {
|
||||
Set-ItemProperty -Path $devicePath -Name "DeviceDesc" -Value "@$oemInfName,%virtioscsi.devicedesc%;VirtIO SCSI Controller" -Type String
|
||||
Set-ItemProperty -Path $devicePath -Name "DeviceDesc" -Value $drv.DeviceDesc -Type String
|
||||
Write-Host "Added DeviceDesc" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "DeviceDesc already set" -ForegroundColor Cyan
|
||||
@@ -359,12 +423,15 @@ try {
|
||||
}
|
||||
|
||||
if (-not $originalProps.CompatibleIDs) {
|
||||
$compatibleIds = @("PCI\VEN_1AF4&DEV_1004", "PCI\VEN_1AF4", "PCI\CC_010000", "PCI\CC_0100")
|
||||
$compatibleIds = @($drv.HardwareIdShort, "PCI\VEN_1AF4", "PCI\CC_010000", "PCI\CC_0100")
|
||||
Set-ItemProperty -Path $devicePath -Name "CompatibleIDs" -Value $compatibleIds -Type MultiString
|
||||
Write-Host "Added CompatibleIDs" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "CompatibleIDs already set" -ForegroundColor Cyan
|
||||
}
|
||||
} else {
|
||||
Write-Host "Skipping manual Enum device-node writes on build $osBuild (pnputil performs the binding)" -ForegroundColor DarkGray
|
||||
}
|
||||
|
||||
Write-Host "Device registry configuration checked" -ForegroundColor Green
|
||||
}
|
||||
@@ -395,17 +462,17 @@ try {
|
||||
|
||||
# Set driver class properties
|
||||
Set-ItemProperty -Path $newClassPath -Name "InfPath" -Value $oemInfName -Type String
|
||||
Set-ItemProperty -Path $newClassPath -Name "InfSection" -Value "scsi_inst" -Type String
|
||||
Set-ItemProperty -Path $newClassPath -Name "InfSection" -Value $drv.InfSection -Type String
|
||||
Set-ItemProperty -Path $newClassPath -Name "ProviderName" -Value "Red Hat, Inc." -Type String
|
||||
Set-ItemProperty -Path $newClassPath -Name "DriverDate" -Value "10-21-2024" -Type String
|
||||
Set-ItemProperty -Path $newClassPath -Name "DriverVersion" -Value "100.100.104.26600" -Type String
|
||||
Set-ItemProperty -Path $newClassPath -Name "MatchingDeviceId" -Value $targetHardwareId -Type String
|
||||
Set-ItemProperty -Path $newClassPath -Name "DriverDesc" -Value "Red Hat VirtIO SCSI pass-through controller" -Type String
|
||||
Set-ItemProperty -Path $newClassPath -Name "DriverDesc" -Value $drv.DriverDesc -Type String
|
||||
|
||||
Write-Host "Driver class binding created: $nextNumberStr" -ForegroundColor Green
|
||||
|
||||
# Pre-configure the device to reference this driver
|
||||
if (Test-Path $devicePath) {
|
||||
# Pre-configure the device to reference this driver (Enum writes: build > 14393 only)
|
||||
if ($writeEnumDeviceProps -and (Test-Path $devicePath)) {
|
||||
Set-ItemProperty -Path $devicePath -Name "Driver" -Value "{4d36e97b-e325-11ce-bfc1-08002be10318}\$nextNumberStr" -Type String
|
||||
Set-ItemProperty -Path $devicePath -Name "Problem" -Value 0 -Type DWord
|
||||
Set-ItemProperty -Path $devicePath -Name "StatusFlags" -Value 0x18 -Type DWord
|
||||
@@ -415,10 +482,13 @@ try {
|
||||
# Step 3: Create Critical Device Database entries
|
||||
Write-Host "`nStep 3: Creating Critical Device Database entries..." -ForegroundColor Yellow
|
||||
|
||||
# Critical Device Database paths
|
||||
# Critical Device Database paths - generate based on driver hardware ID
|
||||
$hardwareIdShortNormalized = $drv.HardwareIdShort -replace '\\', '#'
|
||||
$hardwareIdNormalized = $hardwareId -replace '\\', '#'
|
||||
|
||||
$criticalDbPaths = @(
|
||||
"HKLM:\SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\pci#ven_1af4&dev_1004",
|
||||
"HKLM:\SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\pci#ven_1af4&dev_1004&subsys_00081af4&rev_00"
|
||||
"HKLM:\SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\$hardwareIdShortNormalized",
|
||||
"HKLM:\SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\$hardwareIdNormalized"
|
||||
)
|
||||
|
||||
$criticalDbCount = 0
|
||||
@@ -430,8 +500,8 @@ try {
|
||||
|
||||
# Verify path was created
|
||||
if (Test-Path $criticalPath) {
|
||||
Set-ItemProperty -Path $criticalPath -Name "Service" -Value "vioscsi" -Type String -ErrorAction SilentlyContinue
|
||||
Set-ItemProperty -Path $criticalPath -Name "ClassGUID" -Value "{4d36e97b-e325-11ce-bfc1-08002be10318}" -Type String -ErrorAction SilentlyContinue
|
||||
Set-ItemProperty -Path $criticalPath -Name "Service" -Value $drv.Name -Type String -ErrorAction SilentlyContinue
|
||||
Set-ItemProperty -Path $criticalPath -Name "ClassGUID" -Value $drv.ClassGuid -Type String -ErrorAction SilentlyContinue
|
||||
$criticalDbCount++
|
||||
|
||||
$shortPath = $criticalPath.Split('\')[-1]
|
||||
@@ -549,7 +619,7 @@ public class ConfigManager {
|
||||
Write-Host "Both pnputil syntaxes failed" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
# Check Windows version for pnputil /remove-device support
|
||||
# Check Windows version for pnputil /remove-device support
|
||||
$buildNumber = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").CurrentBuildNumber
|
||||
$supportsRemoveDevice = ([int]$buildNumber -ge 19041)
|
||||
|
||||
@@ -557,8 +627,8 @@ public class ConfigManager {
|
||||
Write-Host "`npnputil /remove-device not supported on this Windows version (Build $buildNumber)" -ForegroundColor Yellow
|
||||
Write-Host "Required: Windows 10 2004+ (Build 19041+) or Windows Server 2022+" -ForegroundColor Yellow
|
||||
Write-Host "`nManual removal required:" -ForegroundColor Cyan
|
||||
Write-Host "- Device Manager: devmgmt.msc -> Uninstall VirtIO SCSI Controller" -ForegroundColor Gray
|
||||
Write-Host "- devcon.exe: devcon remove ROOT\\VIOSCSI\\0000" -ForegroundColor Gray
|
||||
Write-Host "- Device Manager: devmgmt.msc -> Uninstall $($drv.DeviceDesc)" -ForegroundColor Gray
|
||||
Write-Host "- devcon.exe: devcon remove ROOT\\$($drv.Name.ToUpper())\0000" -ForegroundColor Gray
|
||||
return
|
||||
}
|
||||
|
||||
@@ -579,7 +649,7 @@ public class ConfigManager {
|
||||
}
|
||||
elseif ($line -match "Device Description:\s+(.+)") {
|
||||
$deviceDesc = $Matches[1].Trim()
|
||||
# Only target ROOT enumerated devices (phantom devices) with vioscsi
|
||||
# Only target ROOT-enumerated phantom devices for the current driver
|
||||
if ($currentInstanceId -like "ROOT\*$deviceId*") {
|
||||
$virtioDevices += [PSCustomObject]@{
|
||||
InstanceId = $currentInstanceId
|
||||
@@ -622,7 +692,7 @@ public class ConfigManager {
|
||||
Write-Host "`nStep 3: Verification..." -ForegroundColor Yellow
|
||||
|
||||
# Check if devices still exist
|
||||
$remainingDevices = Get-WmiObject -Class Win32_PnPEntity -Filter "DeviceID LIKE 'ROOT\\%vioscsi%'" -ErrorAction SilentlyContinue
|
||||
$remainingDevices = Get-WmiObject -Class Win32_PnPEntity -Filter "DeviceID LIKE 'ROOT\\%$deviceId%'" -ErrorAction SilentlyContinue
|
||||
if ($remainingDevices) {
|
||||
Write-Host "Some VirtIO phantom devices still visible:" -ForegroundColor Yellow
|
||||
foreach ($device in $remainingDevices) {
|
||||
@@ -641,9 +711,16 @@ public class ConfigManager {
|
||||
if ($removedCount -eq 0 -and $virtioDevices.Count -eq 0) {
|
||||
Write-Host "`nNo phantom devices found - system is already clean" -ForegroundColor Cyan
|
||||
}
|
||||
} catch {
|
||||
|
||||
Write-Host "`n========================================" -ForegroundColor Green
|
||||
Write-Host "Completed processing driver: $($drv.Name)" -ForegroundColor Green
|
||||
Write-Host "========================================" -ForegroundColor Green
|
||||
} # End try (per-driver processing)
|
||||
|
||||
catch {
|
||||
Write-Host "`n=== ERROR ===" -ForegroundColor Red
|
||||
$errorMessage = $_.Exception.Message
|
||||
Write-Host "Error during device creation and configuration or removal: $errorMessage" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
} # End catch
|
||||
} # End foreach $drv in $driversToProcess
|
||||
|
||||
Reference in New Issue
Block a user