Finding USB serial ports from a .NET application under Windows 7

家住魔仙堡 提交于 2019-12-30 05:01:08

问题


I have an application that looks for a specific FTDI serial port with customised USB descriptors. My current code uses the example from Code Project, which searches the MSSerial_PortName WMI table under root\WMI, and pulls out extra USB information from root\CIMV2\WIN32_PnPEntity.

This worked well under XP, but the application must also run under a standard user onWindows 7. In this environment access of root\WMI results in an "Access Denied" ManagementException.

Can anybody suggest a way to cross reference the DOS device name of a serial port to the USB information, while running as a standard user? So far I've looked at the root\CIMV2\WIN32_SerialPort* tables, but they only contain motherboard ports. I've also considered using SetupAPI, but I haven't found a complete and working PInvoke template for this.


回答1:


I've discovered an answer suitable for our case, though not a generic one. Our USB converters are all FTDI, and FTDI provide a DLL that handles this. My code using the DLL is below:

UInt32 count = 0;
FTDI.FT_STATUS status = ftdi.GetNumberOfDevices(ref count);
if (status != FTDI.FT_STATUS.FT_OK)
{
    log.Warn("Unable to access FTDI");
    return ports;
}
FTDI.FT_DEVICE_INFO_NODE[] list = new FTDI.FT_DEVICE_INFO_NODE[count];
status = ftdi.GetDeviceList(list);
if (status != FTDI.FT_STATUS.FT_OK)
{
    log.Warn("Unable to access FTDI");
    return ports;
}
foreach (FTDI.FT_DEVICE_INFO_NODE node in list)
{
    if ((status = ftdi.OpenByLocation(node.LocId)) == FTDI.FT_STATUS.FT_OK)
    {
        try
        {
            string comport;
            ftdi.GetCOMPort(out comport);
            ports.Add(new Port(comport, node.Description, node.SerialNumber));
        }
        finally
        {
            ftdi.Close();
        }
    }
}



回答2:


This looks promising.

From the FDTI site on can download the application "Reassign COMNo Utility". This application shows on all Windows platforms which FTDI device is available. It helps a lot to check which FDTI devices are available.

When I tried to use your code within my own applications I discovered that I had some issues with getting it up an running. If possible extend your code so anybody can use it as an sample project without any struggle to get it compiled first.

But still a great contribution. Thanks.

Below the sample code that worked for me.

using FTD2XX_NET;
private List<FDTIPort> FindFdtiUsbDevices()
    {
    ///////////////////////
    // Requires 
    // FTD2XX_NET.dll
    ///////////////////////

    List<FDTIPort> ports = new List<FDTIPort>();

    FTDI _ftdi = new FTDI();

    UInt32 count = 0;
    FTDI.FT_STATUS status = _ftdi.GetNumberOfDevices(ref count);
    if (status != FTDI.FT_STATUS.FT_OK)
    {
        Console.WriteLine("log.Warn: Unable to access FTDI");
        return ports;
    }

    FTDI.FT_DEVICE_INFO_NODE[] list = new FTDI.FT_DEVICE_INFO_NODE[count];
    status = _ftdi.GetDeviceList(list);
    if (status != FTDI.FT_STATUS.FT_OK)
    {
        Console.WriteLine("log.Warn: Unable to access FTDI");
        return ports;
    }


    foreach (FTDI.FT_DEVICE_INFO_NODE node in list)
    {
        if ((status = _ftdi.OpenByLocation(node.LocId)) == FTDI.FT_STATUS.FT_OK)
        {
            try
            {
                string comport;
                _ftdi.GetCOMPort(out comport);

                if (comport != null && comport.Length > 0)
                {
                    ports.Add(new FDTIPort(comport, node.Description.ToString(), node.SerialNumber.ToString()));
                }
             }
             finally
             {
                 _ftdi.Close();
             }
        }
    }

    _ftdi.Dispose();
    return ports;
}

public class FDTIPort
{
     private string _nodeComportName = "";
     private string _nodeDescription = "";
     private string _nodeSerialNumber = "";

    // Constructor
    public FDTIPort()
    {
        _nodeComportName = "";
        _nodeDescription = "";
        _nodeSerialNumber = "";
    }
    // Constructor

    public FDTIPort ( string nodeComportName, string nodeDescription, string nodeSerialNumber )
    {
        _nodeComportName = nodeComportName;
        _nodeDescription = nodeDescription;
        _nodeSerialNumber = nodeSerialNumber;
    }

    public string nodeComportName {
        get { return this._nodeComportName; }
    }

    public string nodeDescription
    {
        get { return this._nodeDescription; }
    }

    public string nodeSerialNumber
    {
        get { return this._nodeSerialNumber; }
    }

}


来源:https://stackoverflow.com/questions/2279646/finding-usb-serial-ports-from-a-net-application-under-windows-7

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!