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

发布于 2024-08-22 13:53:27 字数 590 浏览 4 评论 0原文

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

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

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

韬韬不绝 2024-08-29 13:53:27

我发现了一个适合我们案例的答案,尽管不是通用的。我们的USB转换器都是FTDI,FTDI提供了一个DLL来处理这个问题 。我使用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();
        }
    }
}

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();
        }
    }
}
2024-08-29 13:53:27

这看起来很有希望。

从 FDTI 站点上可以下载应用程序“重新分配 COMNo Utility”。该应用程序在所有 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; }
    }

}

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

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文