I'm trying to get the number of physical USB ports on a Windows machine using Go and WMI. I wrote the following code using ole and oleutil:
func GetUSBCount() (int, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if err := ole.CoInitialize(0); err != nil {
return 0, fmt.Errorf("CoInitialize failed: %v", err)
}
defer ole.CoUninitialize()
unknown, err := oleutil.CreateObject("WbemScripting.SWbemLocator")
if err != nil {
return 0, fmt.Errorf("CreateObject failed: %v", err)
}
defer unknown.Release()
ws, err := unknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
return 0, fmt.Errorf("QueryInterface failed: %v", err)
}
defer ws.Release()
serviceRaw, err := oleutil.CallMethod(ws, "ConnectServer")
if err != nil {
return 0, fmt.Errorf("ConnectServer failed: %v", err)
}
service := serviceRaw.ToIDispatch()
defer service.Release()
resultRaw, err := oleutil.CallMethod(service, "ExecQuery", "SELECT * FROM Win32_USBPort")
if err != nil {
return 0, fmt.Errorf("ExecQuery failed: %v", err)
}
result := resultRaw.ToIDispatch()
defer result.Release()
countRaw, err := oleutil.GetProperty(result, "Count")
if err != nil {
return 0, fmt.Errorf("GetProperty Count failed: %v", err)
}
count := int(countRaw.Val)
return count, nil
}
The problem:
The count returned by this code is not consistent.
Sometimes it returns 3, sometimes 4, even when I haven’t physically added or removed ports.
Connecting a USB device doesn’t reliably increase the count.
I’ve tried querying Win32_USBHub and Win32_USBPort but both approaches give unreliable results.
What I want:
A way to reliably get the number of fixed physical USB ports on a Windows machine (not counting virtual devices or hubs created by plugged-in devices).
Is there a better way to achieve this in Go (or via Windows APIs/WMI) that will give me consistent physical USB port counts?