كيف يمكنني الحصول على اسم مألوف منفذ COM في ويندوز ؟

StackOverflow https://stackoverflow.com/questions/304986

سؤال

لدي مودم GSM متصل عبر USB.المودم يخلق 2 المنافذ التسلسلية.الأول هو تلقائيا تعلق على مودم ثاني يظهر في "إدارة الأجهزة" كما "HUAWEI Mobile Connect - 3G PC UI Interface (COM6)"

المنفذ الثاني يستخدم للحصول على المعلومات الحيوية من المودم مثل إشارة الجودة ؛ إرسال واستقبال الرسائل النصية;ومجموعة كاملة من الوظائف الأخرى.

أنا أكتب التطبيق الذي سوف يختتم بعض الميزات التي يقدمها المنفذ الثاني.ما أحتاجه هو متأكد النار طريقة تحديد منفذ COM هي واحدة الغيار.بالتكرار الموانئ التحقق من استجابة "ATE0" ليست كافية.المودم منفذ هو عادة أقل مرقمة من واحد ، وعندما الاتصال الهاتفي غير نشطة ، فإنه سيتم الرد على "ATE0" نفس المنفذ الثاني.

ما كنت أفكر به هو بالتكرار المنافذ وفحص ودية الاسم كما يظهر في "إدارة الأجهزة".بهذه الطريقة يمكن ربط ميناء في طلبي إلى ميناء المسمى "HUAWEI Mobile Connect - 3G PC UI Interface (COM6)" في "إدارة الأجهزة".أنا فقط لم يتم العثور على أي معلومات حتى الآن من شأنها أن تسمح لي أن الحصول على هذا الاسم برمجيا.

هل كانت مفيدة؟

المحلول

ومنذ زمن طويل كتبت أداة لعميل لفعل هذا، ولكن لGPS بدلا من المودم.

ولقد بدا للتو في ذلك، والبتات التي-القفز بأنها ربما مفيدة هي:

    GUID guid = GUID_DEVCLASS_PORTS;

SP_DEVICE_INTERFACE_DATA interfaceData;
ZeroMemory(&interfaceData, sizeof(interfaceData));
interfaceData.cbSize = sizeof(interfaceData);

SP_DEVINFO_DATA devInfoData;
ZeroMemory(&devInfoData, sizeof(devInfoData));
devInfoData.cbSize = sizeof(devInfoData);

if(SetupDiEnumDeviceInfo(
    hDeviceInfo,            // Our device tree
    nDevice,            // The member to look for
    &devInfoData
    ))
{
    DWORD regDataType;

    BYTE hardwareId[300];
    if(SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, &regDataType, hardwareId, sizeof(hardwareId), NULL))
    {
...

و(استدعاء هذا الشيء في حلقة مع تزايد n الجهاز)

ثم

BYTE friendlyName[300];
        if(SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, NULL, friendlyName, sizeof(friendlyName), NULL))
        {
            strFriendlyNames += (LPCTSTR)friendlyName;
            strFriendlyNames += '\n';
        }

والذي يجد اسم الجهاز.

ونأمل أن تساعدك في الاتجاه الصحيح.

نصائح أخرى

بعد تحديد المنفذ التسلسلي الجهاز هو واحد كنت تريد (من خلال النظر في ودية الاسم عن طريق فحص الجهاز الأصل الخ) ، الطريقة الصحيحة للحصول على اسم الميناء سيكون على الأرجح:

  • الاحتجاج SetupDiOpenDevRegKey(hDevInfo, devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ) للحصول على HKEY يسمى الجهاز الرئيسية
  • الاستعلام مفتاح التسجيل هذا على REG_SZ قيمة "PortName"
  • لا تنسى أن تغلق HKEY :)

ومع ذلك ، فإن هذا قد يتطلب الكثير من إمكانية التشغيل المتداخل في C# هذا ليس مضحكا, لذلك أنا لا ألومك إذا كنت الحفاظ على سلسلة تحليل الحل.

والمعلومات المرسلة بواسطة ويل عميد كانت مفيدة للغاية. هذا هو رمز التي عملت في نهاية المطاف بالنسبة لي. وقد اتخذ كل شيء في فئة PInvoke حرفيا من http://www.pinvoke.net . لم تضطر إلى تغيير نوع البيانات هنا أو هناك والعمل على انجاحه (مثل عند استخدام التعداد بدلا من UINT) ولكن يجب أن يكون من السهل معرفة.

internal static string GetComPortByDescription(string Description)
{
    string Result = string.Empty;
    Guid guid = PInvoke.GUID_DEVCLASS_PORTS;
    uint nDevice = 0;
    uint nBytes = 300;
    byte[] retval = new byte[nBytes];
    uint RequiredSize = 0;
    uint PropertyRegDataType = 0;

    PInvoke.SP_DEVINFO_DATA devInfoData = new PInvoke.SP_DEVINFO_DATA();
    devInfoData.cbSize = Marshal.SizeOf(typeof(PInvoke.SP_DEVINFO_DATA));

    IntPtr hDeviceInfo = PInvoke.SetupDiGetClassDevs(
        ref guid, 
        null, 
        IntPtr.Zero, 
        PInvoke.DIGCF.DIGCF_PRESENT);

    while (PInvoke.SetupDiEnumDeviceInfo(hDeviceInfo, nDevice++, ref devInfoData))
    {
        if (PInvoke.SetupDiGetDeviceRegistryProperty(
                hDeviceInfo, 
                ref devInfoData, 
                PInvoke.SPDRP.SPDRP_FRIENDLYNAME,
                out PropertyRegDataType, 
                retval, 
                nBytes, 
                out RequiredSize))
        {
            if (System.Text.Encoding.Unicode.GetString(retval).Substring(0, Description.Length).ToLower() ==
                Description.ToLower())
            {
                string tmpstring = System.Text.Encoding.Unicode.GetString(retval);
                Result = tmpstring.Substring(tmpstring.IndexOf("COM"),tmpstring.IndexOf(')') - tmpstring.IndexOf("COM"));
            } // if retval == description
        } // if (PInvoke.SetupDiGetDeviceRegistryProperty( ... SPDRP_FRIENDLYNAME ...
    } // while (PInvoke.SetupDiEnumDeviceInfo(hDeviceInfo, nDevice++, ref devInfoData))

    PInvoke.SetupDiDestroyDeviceInfoList(hDeviceInfo);
    return Result;
}

وأعتقد أن Result = tmpstring.Substring(tmpstring.IndexOf("COM"),tmpstring.IndexOf(')') - tmpstring.IndexOf("COM")); الخط هو أخرق قليلا، وسيكون موضع تقدير اقتراحات حول كيفية تنظيفه.

وشكرا لمساعدتكم مع هذه المسألة ويل، بدونك، كنت لا تزال يكون البحث جوجل.

ووC ++ الإصدار على أساسWill عميد الإجابة.

#include <windows.h>
#include <initguid.h>
#include <devguid.h>
#include <setupapi.h>

void enumerateSerialPortsFriendlyNames()
{
    SP_DEVINFO_DATA devInfoData = {};
    devInfoData.cbSize = sizeof(devInfoData);

    // get the tree containing the info for the ports
    HDEVINFO hDeviceInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS,
                                               0,
                                               nullptr,
                                               DIGCF_PRESENT
                                               );
    if (hDeviceInfo == INVALID_HANDLE_VALUE)
    {
        return;
    }

    // iterate over all the devices in the tree
    int nDevice = 0;
    while (SetupDiEnumDeviceInfo(hDeviceInfo,            // Our device tree
                                 nDevice++,            // The member to look for
                                 &devInfoData))
    {
        DWORD regDataType;
        DWORD reqSize = 0;

        // find the size required to hold the device info
        SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, nullptr, nullptr, 0, &reqSize);
        BYTE* hardwareId = new BYTE[(reqSize > 1) ? reqSize : 1];
        // now store it in a buffer
        if (SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, &regDataType, hardwareId, sizeof(hardwareId) * reqSize, nullptr))
        {
            // find the size required to hold the friendly name
            reqSize = 0;
            SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, nullptr, nullptr, 0, &reqSize);
            BYTE* friendlyName = new BYTE[(reqSize > 1) ? reqSize : 1];
            // now store it in a buffer
            if (!SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, nullptr, friendlyName, sizeof(friendlyName) * reqSize, nullptr))
            {
                // device does not have this property set
                memset(friendlyName, 0, reqSize > 1 ? reqSize : 1);
            }
            // use friendlyName here
            delete[] friendlyName;
        }
        delete[] hardwareId;
    }
}

وسعيد أنه يعمل.

ويمكنك أن تحاول:

وRegex.Match (tmpstring، @ "COM \ ق \ د +"). ToString ()

ولمطابقة سلسلة الخاص بك.

وواسلوب النقاط .NET، فما استقاموا لكم فاستقيموا إضافة "باستخدام System.Text"، وأود أن لا تبدأ أسماء المتغيرات المحلية مع العواصم، وإذا كنت تشعر الفاضلة حقا، وأنا ربما وضع SetupDiDestroyDeviceInfoList في النهاية {} الشرط.

تستخدم طريقة نشرت من قبل LiGenChen.طريقة ComPortSetupAPISetupDiClassGuids أعطى أفضل وقت ودية اسم.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top