1

I'm trying to get number of physical USB ports of PC for different Windows operating systems. To start with it seemed like an easy task but now I'm getting desperate.

Maybe this question is not even valid since I don't know how USB ports are treated on hardware level.

I thought using WMI(C) and ManagementObjectSearcher would be the right path to take and it returned right values... on certain operating systems. Or that's what I thought.

For example, I tried the following:

// >wmic path win32_usbhub get name

private const string UsbProperty = "Name";
private const string UsbPath = "Win32_USBHub";
private const string UsbPortName = "USB ROOT HUB";

...

// Get USB Ports
public IEnumerable<string> GetUsbPorts()
{
    // All from Win32_USBHub where name contains USB ROOT HUB
    return GetManagementObjectValues(UsbProperty, UsbPath).Where(name => 
        CultureInfo.CurrentCulture.CompareInfo.IndexOf(
            name, UsbPortName, CompareOptions.IgnoreCase) >= 0);
}

.

// Query
private static IEnumerable<string> GetManagementObjectValues(
    string properties, string path, Func<object, string> formatter = null)
{
    var values = new List<string>();
    string query = string.Format("SELECT {0} FROM {1}", properties, path);
    var search = new ManagementObjectSearcher(query);

    try
    {
        foreach (ManagementObject item in search.Get())
        {
            string value = string.Empty;
            foreach (string property in properties.Split(',')
                .Select(prop => prop.Trim()))
            {
                if (item[property] == null)
                    continue;

                if (value.Length > 0)
                    value += " ";

                if (formatter != null)
                    value += formatter(item[properties]);
                value += item[property].ToString();
            }
            values.Add(value.TrimEnd());
        }
    }
    catch (Exception e)
    {
        if (e is ManagementException)
            Logger.Warn(string.Format(
                "Can't extract {0} properties of {1}", properties, path), e);
        else
            Logger.Error(e);
    }

    return values.Count >= 1 ? values : new List<string> { DefaultValue };
}

This seemed to get me the right amount on Windows8 but on WindowsXP it was totally off.

Next, I tried (for example) the following. I noticed that on Win8 I have USB<number> as ExternalReferenceDesignator but on WinXP, there's plain USB as InternalReferenceDesignator and external is empty.

For XP this seemed to work just fine but then again on Win8 amount of ports was six (6). Actual port count is 3 and with docking station station seven (7).

// >wmic path Win32_PortConnector get ExternalReferenceDesignator,InternalReferenceDesignator

private const string UsbPortName = "USB";     
private const string PortProperties = 
    "ExternalReferenceDesignator, InternalReferenceDesignator";
private const string PortPath = @"Win32_PortConnector";

...

public IEnumerable<string> GetEthernetPorts()
{
    // All where external includes USB or internal equals USB
    return GetManagementObjectValues(PortProperties, PortPath).Where(name => 
        CultureInfo.CurrentCulture.CompareInfo.IndexOf(
            name, UsbPortName, CompareOptions.IgnoreCase) >= 0 ||
        string.Compare(name, UsbPortName, StringComparison.OrdinalIgnoreCase) == 0);
}    

So is it even possible or am I just looking from the wrong place?

Mikko Viitala
  • 8,344
  • 4
  • 37
  • 62

2 Answers2

3

And to answer my own question: No, it's not possible.

WMIC query results for Win32_USBController (or some related path) might seem right but you can't draw any conclusions from them. Information about connectors aren't stored on the baseboard or any other location either.

For example an old Dell Latitude D830 with Windows XP SP3 has three (3) physical connectors but WMIC and USBView.exe shows results below:

C:\>wmic path win32_usbcontroller get caption
Caption
Intel(R) ICH8 Family USB Universal Host Controller - 2834
Intel(R) ICH8 Family USB Universal Host Controller - 2835
Intel(R) ICH8 Family USB2 Enhanced Host Controller - 283A
Intel(R) ICH8 Family USB Universal Host Controller - 2830
Intel(R) ICH8 Family USB Universal Host Controller - 2831
Intel(R) ICH8 Family USB Universal Host Controller - 2832
Intel(R) ICH8 Family USB2 Enhanced Host Controller - 2836

imgur

Mikko Viitala
  • 8,344
  • 4
  • 37
  • 62
0

I know it has been a while since the question was asked, but I just happened to be working on a USB port tree for a support app of some sort. Initially, I tried to use Win32..., as much as it is not intended to be used as a source of information for the rebuilding of the device tree, the answer of this post explains some possibilities (Get List of connected USB Devices). I played with it but I did not like it. UsbView by itself was also not an option (lack of skill in C ). Luckily I found NativeUsbLib. It provides you with a USB device tree, you just need to understand how to read it. Not a physical USB port This image shows a port that clearly states it is not possible to use it. In addition to that parameter, there is "Companion Hub Symbolic Link Name", in my experience, it has to be present on a valid USB port. As for multiple controllers, and even multiple ports in one controller that satisfy my previous statement, there is an explanation. Multiple ports for same physical port, in my case, ports 1 and 13 are the same. If a device is 1.1 or 2.0 it will show under port 1, and if it supports 3.0 it will show up under port 13. And same goes for two controllers, they don't have 100% the same structure, but once you strip unnecessary data, and merge data (not necessarily all of it) that is left, the result will be a USB port tree. I can't guarantee all of the statements are true, but that is my current experience, and I might update this post. If not, feel free to message me if you have some questions. Btw. NativeUsbLib by default does not provide data for ports that don't have a device present (plugged in). To fix that, comment out lines in DeviceFactory that check if the device is present (line 35). Hope this helps someone and sorry for my spelling, I am sure I messed up somewhere...