Find com-port used by serial mouse

邮差的信 提交于 2019-12-14 02:45:02

问题


How to find which com-port is occupied by serial mouse

Here is how I detect mouse in C# (adapted code from this answer)

var info = IntPtr.Zero;
try
{
    var guid = new Guid("{4d36e96f-e325-11ce-bfc1-08002be10318}"); // mouses
    info = SetupDiGetClassDevsW(ref guid, null, IntPtr.Zero, 0);
    if ((int)info == -1) // INVALID_HANDLE_VALUE
        throw new Exception(string.Format("Error({0}) SetupDiGetClassDevsW", Marshal.GetLastWin32Error()));
    // enumerate mouses
    var device = new SP_DEVINFO_DATA();
    device.cbSize = (UInt32)Marshal.SizeOf(device);
    for (uint i = 0; ; i++)
    {
        // get device info
        if (!SetupDiEnumDeviceInfo(info, i, out device))
        {
            var error = Marshal.GetLastWin32Error();
            if (error == 259) // ERROR_NO_MORE_ITEMS
                break;
            else
                throw new Exception(string.Format("Error({0}) SetupDiEnumDeviceInfo", error));
        }
        string id = GetStringPropertyForDevice(info, device, 1); // SPDRP_HARDWAREID
        if (id != null && id.Contains("*PNP0F09")) // Microsoft BallPoint Serial Mouse
        {
            // ...
            // here I want to check com-port, how?
            // ...
        }
    }
}
finally
{
    if (info != IntPtr.Zero)
        SetupDiDestroyDeviceInfoList(info);
}

Edit

Removing C# tag. Looking for general info (any language).


回答1:


You can use Process Monitor from SysInternalSuite and open device manager then find out from where does the device manager getting its values

I tried it on USB Mouse and was able to get (on USB Input Device) as shown below 1. Open Mouse Properties (From Control Panel)

2. Open ProcMon 3. Click on the target icon and choose the mouse properties window

4. From the Mouse Properties window open the Hardware tab 5. In ProcMon Click on File-> Captuer Events 6. In ProcMon Edit->Find and look for "com" without quotation mark 7. Double click the found row (If you where able to find it)

Another solution would be to get device information using device manager command line utility devcon and parse the information from the output stream

More information on devcon: * http://support.microsoft.com/kb/311272 * https://superuser.com/questions/414280/how-do-i-view-a-list-of-devices-from-the-command-line-in-windows

Hope this help




回答2:


The subroutine that generates the "Location" string in Device Manager is devmgr.dll!GetLocationInformation.

The path in it that interests you - generating the value that is appended in brackets - can be represented with the following code (based on Hex-Rays' decompilation):

int __stdcall GetLocationInformation(DEVINST dnDevInst, wchar_t *lpsResult,
                                     int cchBufferMax, HMACHINE hMachine)
{
  int dwUiNumber;
  HKEY hKey;
  DWORD pulLength;
  wchar_t sRawLocationInfo[260];

  sRawLocationInfo[0] = 0;
  DWORD Type = REG_SZ;
  pulLength = 520;
  if ( !CM_Open_DevNode_Key_Ex(dnDevInst, KEY_READ, 0, 1u, &hKey, 1u, hMachine) )
  {
    RegQueryValueExW(hKey, L"LocationInformationOverride", 0, &Type,
      sRawLocationInfo, &pulLength);
    RegCloseKey(hKey);
  }
  if ( !sRawLocationInfo[0] )
  {
    pulLength = 520;
    CM_Get_DevNode_Registry_Property_ExW(
      dnDevInst,
      CM_DRP_LOCATION_INFORMATION,
      0,
      sRawLocationInfo,
      &pulLength,
      0,
      hMachine);
  }
  pulLength = 4;
  if ( CM_Get_DevNode_Registry_Property_ExW(
         dnDevInst,
         CM_DRP_UI_NUMBER,
         0,
         &dwUiNumber,
         &pulLength,
         0,
         hMachine)
    || pulLength <= 0 )
  {
    <...>   //this block always returns
  }
  else
  {
      <...>
      if ( sRawLocationInfo[0] )
      {
        lstrcatW(lpsResult, L" (");
        lstrcatW(lpsResult, sRawLocationInfo);
        lstrcatW(lpsResult, L")");
      }
      return 0;
  }
}

In a nutshell, the bracketed value is the device node's LocationInformationOverride or LocationInformation property and is only produced if the UiNumber property is absent (or bogus).


The CM_Open_DevNode_Key_Ex and CM_Get_DevNode_Registry_Property_ExW functions are marked "reserved" in the docs. You can

  • find their signatures e.g. in CM_Open_DevNode_Key_Ex - FileLog and Enumerate Properties of an Installed Device - The Code Project, respectively, or
  • use the publicly-documented CM_Open_DevNode_Key and CM_Get_DevNode_Registry_Property instead. They are exactly the same as the former ones save for missing the hMachine argument (they essentially directly call them substituting NULL for it).
  • There are corresponding SetupDi equivalents, SetupDiOpenDevRegKey and SetupDiGetDeviceRegistryProperty, as well but note that this API is new in Vista and uses different data types.
    • Seeing that you use it already though means that this is probably the way to go for you unless you need XP support.

If my guess is right, the "USB Serial Port (COM6)" you see in Device Manager is actually the name of the parent device (=the device this one is connected to as seen in Device Manager in "view devices by connection" mode). If this is correct, the "COM6" is but a part of the name rather than some independent property.



来源:https://stackoverflow.com/questions/25686657/find-com-port-used-by-serial-mouse

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