Initial commit: Driver Booster Pro - Go + WebView2 desktop app
Windows system utility with driver scanning, Windows Update integration, and system info collection. Beautiful dark-themed UI via embedded WebView2. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
153
internal/drivers/drivers.go
Normal file
153
internal/drivers/drivers.go
Normal file
@@ -0,0 +1,153 @@
|
||||
package drivers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Driver struct {
|
||||
DeviceName string `json:"deviceName"`
|
||||
DeviceClass string `json:"deviceClass"`
|
||||
Manufacturer string `json:"manufacturer"`
|
||||
DriverVersion string `json:"driverVersion"`
|
||||
DriverDate string `json:"driverDate"`
|
||||
Status string `json:"status"`
|
||||
InfName string `json:"infName"`
|
||||
IsSigned bool `json:"isSigned"`
|
||||
NeedsUpdate bool `json:"needsUpdate"`
|
||||
}
|
||||
|
||||
type ScanResult struct {
|
||||
Drivers []Driver `json:"drivers"`
|
||||
TotalCount int `json:"totalCount"`
|
||||
OutdatedCount int `json:"outdatedCount"`
|
||||
ErrorCount int `json:"errorCount"`
|
||||
ScanTime string `json:"scanTime"`
|
||||
ScannedAt time.Time `json:"scannedAt"`
|
||||
}
|
||||
|
||||
type Scanner struct{}
|
||||
|
||||
func NewScanner() *Scanner {
|
||||
return &Scanner{}
|
||||
}
|
||||
|
||||
func (s *Scanner) Scan() ScanResult {
|
||||
start := time.Now()
|
||||
result := ScanResult{
|
||||
Drivers: []Driver{},
|
||||
}
|
||||
|
||||
drivers := s.enumDriversPnP()
|
||||
result.Drivers = drivers
|
||||
result.TotalCount = len(drivers)
|
||||
|
||||
for _, d := range drivers {
|
||||
if d.NeedsUpdate {
|
||||
result.OutdatedCount++
|
||||
}
|
||||
if d.Status == "Error" || d.Status == "Degraded" {
|
||||
result.ErrorCount++
|
||||
}
|
||||
}
|
||||
|
||||
result.ScanTime = time.Since(start).Round(time.Millisecond).String()
|
||||
result.ScannedAt = time.Now()
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *Scanner) enumDriversPnP() []Driver {
|
||||
// Use PowerShell to enumerate PnP signed drivers via WMI
|
||||
psScript := `
|
||||
Get-CimInstance Win32_PnPSignedDriver | Where-Object { $_.DeviceName -ne $null } | Select-Object -First 100 DeviceName, DeviceClass, Manufacturer, DriverVersion, DriverDate, InfName, IsSigned, Status | ConvertTo-Json -Compress
|
||||
`
|
||||
out, err := exec.Command("powershell", "-NoProfile", "-Command", psScript).Output()
|
||||
if err != nil {
|
||||
return []Driver{}
|
||||
}
|
||||
|
||||
var raw []struct {
|
||||
DeviceName string `json:"DeviceName"`
|
||||
DeviceClass string `json:"DeviceClass"`
|
||||
Manufacturer string `json:"Manufacturer"`
|
||||
DriverVersion string `json:"DriverVersion"`
|
||||
DriverDate string `json:"DriverDate"`
|
||||
InfName string `json:"InfName"`
|
||||
IsSigned bool `json:"IsSigned"`
|
||||
Status string `json:"Status"`
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(out, &raw); err != nil {
|
||||
// Try as single object (when only 1 result)
|
||||
var single struct {
|
||||
DeviceName string `json:"DeviceName"`
|
||||
DeviceClass string `json:"DeviceClass"`
|
||||
Manufacturer string `json:"Manufacturer"`
|
||||
DriverVersion string `json:"DriverVersion"`
|
||||
DriverDate string `json:"DriverDate"`
|
||||
InfName string `json:"InfName"`
|
||||
IsSigned bool `json:"IsSigned"`
|
||||
Status string `json:"Status"`
|
||||
}
|
||||
if err := json.Unmarshal(out, &single); err != nil {
|
||||
return []Driver{}
|
||||
}
|
||||
raw = append(raw, single)
|
||||
}
|
||||
|
||||
drivers := make([]Driver, 0, len(raw))
|
||||
for _, r := range raw {
|
||||
d := Driver{
|
||||
DeviceName: r.DeviceName,
|
||||
DeviceClass: normalizeClass(r.DeviceClass),
|
||||
Manufacturer: r.Manufacturer,
|
||||
DriverVersion: r.DriverVersion,
|
||||
DriverDate: formatDriverDate(r.DriverDate),
|
||||
InfName: r.InfName,
|
||||
IsSigned: r.IsSigned,
|
||||
Status: r.Status,
|
||||
}
|
||||
d.NeedsUpdate = checkIfOutdated(r.DriverDate)
|
||||
drivers = append(drivers, d)
|
||||
}
|
||||
|
||||
return drivers
|
||||
}
|
||||
|
||||
func normalizeClass(class string) string {
|
||||
if class == "" {
|
||||
return "Other"
|
||||
}
|
||||
return class
|
||||
}
|
||||
|
||||
func formatDriverDate(date string) string {
|
||||
if date == "" {
|
||||
return "Unknown"
|
||||
}
|
||||
// WMI returns dates like "20230115000000.000000-000" or "/Date(1234567890000)/"
|
||||
if strings.Contains(date, "/Date(") {
|
||||
return date // Will be parsed on frontend
|
||||
}
|
||||
if len(date) >= 8 {
|
||||
return date[:4] + "-" + date[4:6] + "-" + date[6:8]
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
func checkIfOutdated(dateStr string) bool {
|
||||
if dateStr == "" {
|
||||
return false
|
||||
}
|
||||
// Consider drivers older than 2 years as potentially outdated
|
||||
if len(dateStr) >= 8 {
|
||||
t, err := time.Parse("20060102", dateStr[:8])
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return time.Since(t) > 2*365*24*time.Hour
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user