【问题标题】:How to programatically disable "Enhanced Power Management" for certain USB devices?如何以编程方式禁用某些 USB 设备的“增强型电源管理”?
【发布时间】:2014-04-17 00:28:24
【问题描述】:

我正在开发与自定义 USB 设备交互的软件。该设备将自身呈现为 HID 设备,软件通过文件 I/O 与其交互。

由于 Windows 8.1 的更改,操作系统不断重启设备,这导致软件出现问题。

根据此知识库文章:http://support.microsoft.com/kb/2900614,如果 USB 设备遇到此问题,Microsoft 建议禁用增强型电源管理功能,并且手动执行此操作后问题确实消失了。

现在,我想修改软件的安装程序,为我们所有的设备禁用此设置,而不仅仅是针对特定的设备实例。

有没有办法做到这一点?是通过 Windows API 调用,还是通过会影响特定 ProductID/VendorID 组合的所有实例的注册表设置?

例如我想修改以下所有实例:

  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_11AE&PID_07CE

包括安装程序执行后可能连接到系统的任何未来实例。

【问题讨论】:

    标签: windows usb registry


    【解决方案1】:

    这是我编写的一个示例脚本,用于在所有 Datalogic 品牌 USB 设备(供应商 ID 0x05F9)上禁用电源管理。您可能只需在 For Each 循环的条件下更改“VID_05F9&”,使其与您需要修改的键匹配。请注意,必要的 UAC 提升也会得到处理。

    'Filename: USBPMFIX.VBS
    'Author:   Matthew Mellon <mmellon@ecrs.com>
    'Date:     2014-12-12
    'Desc:     Disables enhanced power management on all Datalogic USB devices.
    'License:  This source code is released into the public domain.    
    
    'Checks if the script is running elevated (UAC)
    function isElevated
      Set shell = CreateObject("WScript.Shell")
      Set whoami = shell.Exec("whoami /groups")
      Set whoamiOutput = whoami.StdOut
      strWhoamiOutput = whoamiOutput.ReadAll
    
      If InStr(1, strWhoamiOutput, "S-1-16-12288", vbTextCompare) Then 
        isElevated = True
      Else
          isElevated = False
      End If
    end function
    
    'Re-runs the process prompting for priv elevation on re-run
    sub uacPrompt
    
      'Check if we need to run in C or W script
      interpreter = "wscript.exe"
      If Instr(1, WScript.FullName, "CScript", vbTextCompare) = 0 Then
        interpreter = "wscript.exe"
      else
        interpreter = "cscript.exe"
      end if
    
      'Start a new instance with an elevation prompt first
      Set shellApp = CreateObject("Shell.Application")
      shellApp.ShellExecute interpreter, Chr(34) & WScript.ScriptFullName & Chr(34) & " uac", "", "runas", 1
    
      'End the non-elevated instance
      WScript.Quit
    end sub
    
    if not isElevated Then uacPrompt
    
    Const HKEY_LOCAL_MACHINE = &H80000002
    strComputer = "."
    
    Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
     strComputer & "\root\default:StdRegProv")
    
    strKeyPath = "SYSTEM\CurrentControlSet\Enum\USB"
    objReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubKeys
    
    For Each Subkey in arrSubKeys
      If Left(Subkey,9) = "VID_05F9&" And Left(Right(Subkey,6),5) = "&MI_0" Then
        strKeyPath = "SYSTEM\CurrentControlSet\Enum\USB\"+Subkey
        objReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrInnerSubKeys
        For Each InnerSubkey in arrInnerSubKeys
          strFullKey = "SYSTEM\CurrentControlSet\Enum\USB\"+Subkey+"\"+InnerSubkey+"\Device Parameters"
          objReg.SetDWORDValue HKEY_LOCAL_MACHINE, strFullKey, "EnhancedPowerManagementEnabled", 0
        Next   
      End If
    Next
    

    【讨论】:

      【解决方案2】:

      您应该能够使用Registry Functions 来检查并动态更改导致您的问题的键。我以前没有这样做过,但我认为您可以将此作为安装步骤添加到您的设备的自定义 INF 中,以确保在每次安装新设备时都会发生这种情况。

      我不知道您是否可以控制设备固件,但您可以更改描述符,以便它预先告诉操作系统它不支持电源管理,如挂起或远程唤醒。

      【讨论】:

      • I think you could add this in as an install step in a custom INF for your device to ensure it happens on each installation of a new device. - 这就是我要找的。知道如何准确地做到这一点,或者在哪里可以找到相关文档?
      • 再想一想,该设备是一个 HID 设备,它没有任何自定义驱动程序(或 INF 文件)。 Windows 将其检测为通用 HID 并愉快地使用通用 HID 驱动程序对其进行设置。所以 INF 解决方案行不通。
      • 您仍然可以为您的设备提供 INF,请查看 this post。在您的自定义 INF 中,您需要提供一个 AddReg 部分以根据您的设置添加注册表项 documented here
      【解决方案3】:

      另一种选择是将MS OS Descriptor 添加到设备固件中。您可以通过该描述符修改您需要的注册表属性。 所有必要的信息都可以在spec 中找到。以下是此类描述符的外观。

      const uint8_t msOs20DescriptorSet[10 + 76 + 6] =
      {
          //
          // Microsoft OS 2.0 Descriptor Set Header
          //
          0x0A, 0x00,             // wLength - 10 bytes
          0x00, 0x00,             // wDescriptorType, MSOS20_SET_HEADER_DESCRIPTOR
          0x00, 0x00, 0x03, 0x06, // dwWindowsVersion – 0x06030000 for Windows Blue
          0x5C, 0x00,             // wTotalLength – 92 bytes
      
          //
          // Microsoft OS 2.0 Registry Value Feature Descriptor
          //
          0x4C, 0x00, // wLength - 76 bytes
          0x04, 0x00, // wDescriptorType – 4 for Registry Property
          0x04, 0x00, // wPropertyDataType - 4 for REG_DWORD
          0x3E, 0x00, // wPropertyNameLength – 62 bytes
          'E', 0, // Property Name - EnhancedPowerManagementEnabled
          'n', 0,
          'h', 0,
          'a', 0,
          'n', 0,
          'c', 0,
          'e', 0,
          'd', 0,
          'P', 0,
          'o', 0,
          'w', 0,
          'e', 0,
          'r', 0,
          'M', 0,
          'a', 0,
          'n', 0,
          'a', 0,
          'g', 0,
          'e', 0,
          'm', 0,
          'e', 0,
          'n', 0,
          't', 0,
          'E', 0,
          'n', 0,
          'a', 0,
          'b', 0,
          'l', 0,
          'e', 0,
          'd', 0,
          0, 0,
          0x04, 0x00,             // wPropertyDataLength – 4 bytes
          0x00, 0x00, 0x00, 0x00,  // PropertyData - 0x00000000
      
          // Microsoft OS 2.0 vendor revision descriptor
          0x06, 0x00, // wLength - 6 bytes
          0x08, 0x00, // wDescriptorType, MS_OS_20_FEATURE_VENDOR_REVISION
          0x01, 0x00, /* VendorRevision, if this value changes between enumerations the registry 
          property descriptors will be updated in registry during that enumeration. */
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-05
        • 2010-10-06
        • 1970-01-01
        • 2011-08-09
        • 2011-05-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多