在Windows 7下从.NET应用程序中查找USB串行端口

时间:2010-02-17 09:55:48

标签: .net windows-7 wmi serial-port

我有一个应用程序,它会查找具有自定义USB描述符的特定FTDI串行端口。我当前的代码使用the example from Code Project,它会搜索MSSerial_PortName下的root\WMI WMI表,并从root\CIMV2\WIN32_PnPEntity中提取额外的USB信息。

这在XP下运行良好,但应用程序也必须在Windows 7上的标准用户下运行。在此环境中,root\WMI的访问会导致“拒绝访问”ManagementException

有人建议在以标准用户身份运行时,将串口的DOS设备名称交叉引用到USB信息吗?到目前为止,我已经查看了root\CIMV2\WIN32_SerialPort*表,但它们只包含主板端口。我也考虑使用SetupAPI,但我还没有找到一个完整且有效的PInvoke模板。

2 个答案:

答案 0 :(得分:6)

我发现了一个适合我们案例的答案,虽然不是一般的答案。我们的USB转换器都是FTDI,FTDI提供DLL that handles this。我使用DLL的代码如下:

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();
        }
    }
}

答案 1 :(得分:3)

这看起来很有希望。

从FDTI网站上可以下载应用程序“重新分配COMNo实用程序”。此应用程序在所有Windows平台上显示FTDI设备可用。检查哪些FDTI设备可用有很大帮助。

当我尝试在自己的应用程序中使用您的代码时,我发现我在运行时遇到了一些问题。如果可能的话,扩展你的代码,这样任何人都可以将它作为一个示例项目使用,而无需先编译它。

但仍然是一个伟大的贡献。 感谢。

下面是适用于我的示例代码。

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; }
    }

}