If (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) { Start-Process PowerShell.exe -ArgumentList ("-NoProfile -ExecutionPolicy Bypass -File `"{0}`"" -f $PSCommandPath) -Verb RunAs Exit } #get all devices function Get-Devices { $pnpdevices = Get-PnpDevice -PresentOnly | Select-Object FriendlyName, InstanceId, Description, Status | Where-Object { $_.Status -eq 'OK' } $drivers = Get-WindowsDriver -Online -All | Select-Object Driver, OriginalFileName $devs = @() foreach ($dev in $pnpdevices) { try { $driverName = ((pnputil.exe /enum-devices /InstanceId $dev.InstanceId | Select-String 'Driver Name: ') -split ':')[1].trim() foreach ($driver in $drivers) { if ($driver.Driver -eq $driverName) { $driverPath = Split-Path $driver.OriginalFileName -Parent } } } catch { $driverPath = $null } $customObj = [PSCustomObject]@{ DeviceName = $dev.FriendlyName DeviceID = $dev.InstanceId Status = $dev.Status Description = $dev.Description DriverPath = $driverPath } $devs += $customObj } return $devs } Add-Type -AssemblyName PresentationFramework Add-Type -AssemblyName System.Windows.Forms $window = New-Object System.Windows.Window $window.Title = 'Device Manager' $window.Width = 900 $window.Height = 700 $window.Background = [System.Windows.Media.Brushes]::DarkGray $window.Foreground = [System.Windows.Media.Brushes]::White $grid = New-Object System.Windows.Controls.Grid $grid.Background = [System.Windows.Media.Brushes]::Gainsboro $row1 = New-Object System.Windows.Controls.RowDefinition $row1.Height = New-Object System.Windows.GridLength(1, [System.Windows.GridUnitType]::Star) $row2 = New-Object System.Windows.Controls.RowDefinition $row2.Height = New-Object System.Windows.GridLength(0, [System.Windows.GridUnitType]::Auto) $grid.RowDefinitions.Add($row1) | Out-Null $grid.RowDefinitions.Add($row2) | Out-Null $window.Content = $grid $deviceList = New-Object System.Windows.Controls.ListView $deviceList.Background = [System.Windows.Media.Brushes]::DarkGray $deviceList.Foreground = [System.Windows.Media.Brushes]::Black $deviceList.SelectionMode = [System.Windows.Controls.SelectionMode]::Multiple $deviceList.Margin = New-Object System.Windows.Thickness(10, 10, 10, 5) [System.Windows.Controls.Grid]::SetRow($deviceList, 0) $gridView = New-Object System.Windows.Controls.GridView $deviceList.View = $gridView $checkColumn = New-Object System.Windows.Controls.GridViewColumn $checkColumn.Header = 'Select' $checkColumn.Width = 45 $checkTemplate = New-Object System.Windows.DataTemplate $checkFactory = New-Object System.Windows.FrameworkElementFactory([System.Windows.Controls.CheckBox]) $checkBinding = New-Object System.Windows.Data.Binding('IsSelected') $checkFactory.SetBinding([System.Windows.Controls.CheckBox]::IsCheckedProperty, $checkBinding) $checkTemplate.VisualTree = $checkFactory $checkColumn.CellTemplate = $checkTemplate $gridView.Columns.Add($checkColumn) | Out-Null $columns = @( @{Header = 'Device Name'; Width = 200; Property = 'DeviceName' }, @{Header = 'Description'; Width = 250; Property = 'Description' }, @{Header = 'Device ID'; Width = 250; Property = 'DeviceID' }, @{Header = 'Driver Path'; Width = 200; Property = 'DriverPath' } ) foreach ($col in $columns) { $column = New-Object System.Windows.Controls.GridViewColumn $column.Header = $col.Header $column.Width = $col.Width $binding = New-Object System.Windows.Data.Binding($col.Property) $column.DisplayMemberBinding = $binding $gridView.Columns.Add($column) | out-null } $grid.AddChild($deviceList) | out-null $buttonPanel = New-Object System.Windows.Controls.StackPanel $buttonPanel.Orientation = [System.Windows.Controls.Orientation]::Horizontal $buttonPanel.HorizontalAlignment = [System.Windows.HorizontalAlignment]::Right $buttonPanel.Margin = New-Object System.Windows.Thickness(0, 5, 0, 10) [System.Windows.Controls.Grid]::SetRow($buttonPanel, 1) $applyButton = New-Object System.Windows.Controls.Button $applyButton.Content = 'Apply' $applyButton.Width = 75 $applyButton.Height = 30 $applyButton.Margin = New-Object System.Windows.Thickness(5) $applyButton.Background = [System.Windows.Media.Brushes]::DarkSlateGray $applyButton.Foreground = [System.Windows.Media.Brushes]::White $buttonPanel.Children.Add($applyButton) | Out-Null $cancelButton = New-Object System.Windows.Controls.Button $cancelButton.Content = 'Cancel' $cancelButton.Width = 75 $cancelButton.Height = 30 $cancelButton.Margin = New-Object System.Windows.Thickness(5) $cancelButton.Background = [System.Windows.Media.Brushes]::DarkSlateGray $cancelButton.Foreground = [System.Windows.Media.Brushes]::White $buttonPanel.Children.Add($cancelButton) | Out-Null $grid.AddChild($buttonPanel) | Out-Null $deviceCollection = New-Object System.Collections.ObjectModel.ObservableCollection[PSObject] Write-Host '[*] Getting Device Info...' -f Green $devices = Get-Devices foreach ($device in $devices) { $device | Add-Member -MemberType NoteProperty -Name IsSelected -Value $false $deviceCollection.Add($device) | Out-Null } $deviceList.ItemsSource = $deviceCollection $applyButton.Add_Click({ $selectedDevices = $deviceCollection | Where-Object { $_.IsSelected } if ($selectedDevices) { foreach ($device in $selectedDevices) { Write-Host "[*] Removing $($device.DeviceName)..." -ForegroundColor Green pnputil.exe /remove-device $device.DeviceID #pnputil may remove the path im not 100% sure so test and remove if needed if (Test-Path $device.DriverPath) { Write-Host '[*] Removing Driver Store Path at ' -NoNewline -ForegroundColor Green Write-Host "[$($device.DriverPath)]" -ForegroundColor Yellow takeown /f $device.DriverPath /r /d Y *>$null icacls $device.DriverPath /grant administrators:F /t *>$null Remove-Item $device.DriverPath -Force -Recurse } Write-Host '[*] Preventing Windows from Reinstalling...' -ForegroundColor Green $policyPath = 'HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\DeviceInstall\Restrictions' $denyPath = "$policyPath\DenyInstanceIDs" #policies to enable Reg.exe add $policyPath /v 'DenyInstanceIDs' /t REG_DWORD /d '1' /f Reg.exe add $policyPath /v 'DenyInstanceIDsRetroactive' /t REG_DWORD /d '0' /f #block device by ID #key name "1" should increase for each new device added try { #get the largest key num and add 1 $regKeyNum = [string](((Get-Item "registry::$denyPath" -ErrorAction Stop).Property | Measure-Object -Maximum).Maximum + 1) } catch { $regKeyNum = '1' } Reg.exe add $denyPath /v $regKeyNum /t REG_SZ /d $device.DeviceID /f } Write-Host '[!] Done...' -ForegroundColor Cyan } else { [Windows.MessageBox]::Show('No Devices Selected!', 'Warning', 'OK', 'Warning') } }) $cancelButton.Add_Click({ $window.Close() }) $window.ShowDialog() | Out-Null