Проверка 13-го бита (установка тени) из элемента реестра (reg_binary)? - PullRequest
3 голосов
/ 17 января 2020

Используя следующий код PowerShell:

$RegConnect = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]"CurrentUser", "$env:COMPUTERNAME")
$RegCursors = $RegConnect.OpenSubKey("Control Panel\Desktop", $true)
$myVal = $RegCursors.GetValue("UserPreferencesMask")
write-output $myVal
$RegCursors.Close()
$RegConnect.Close()

Возвращает:

190
30
7
128
18
1
0
0

Из справки MS в UserPreferencesMask, бит Я после 13-го, тень курсора .

13 тень курсора - 1 По умолчанию

Тень курсора включена. Этот эффект появляется, только если система имеет глубину цвета более 256 цветов.

Как извлечь из этого логическое значение для текущей тени мыши?


Вот значения во включенном и выключенном состоянии.

on = "UserPreferencesMask"=hex:be,3e,07,80,12,01,00,00

off = "UserPreferencesMask"=hex:be,1e,07,80,12,01,00,00

Ответы [ 2 ]

3 голосов
/ 17 января 2020

Похоже, вы добавляете 32 или 0x20 ко второму байту, чтобы включить его:

$myval[1] += 32 # on
$myval[1] -= 32 # off

Битовый, "или" установить "и" с "дополнением бита (не)" для сброса.

0x1e -bor 0x20 # on
62

0x3e -band -bnot 0x20 # off
30

Возможно, вы могли бы сделать перечисление флагов для всех настроек, но вам нужно было бы преобразовать массив байтов в одно большое целое число.

РЕДАКТИРОВАТЬ: О, если Вы просто хотите проверить, установлен ли бит:

$shadowbit = 0x20
if (0x3e -band $shadowbit ) { 'yep' } else { 'nope' } # 32
yep

if (0x1e -band $shadowbit ) { 'yep' } else { 'nope' } # 0
nope

См. также Как установить, очистить и переключить один бит?

РЕДАКТИРОВАТЬ:

Я немного переборщил. Имея это в подготовке:

[Flags()] enum UserPreferencesMask {
  ActiveWindowTracking       = 0x1
  MenuAnimation              = 0x2
  ComboBoxAnimation          = 0x4
  ListBoxSmoothScrolling     = 0x8
  GradientCaptions           = 0x10
  KeybordCues                = 0x20
  ActiveWindowTrackingZOrder = 0x40
  HotTracking                = 0x80
  Reserved8                  = 0x100
  MenuFade                   = 0x200
  SelectionFade              = 0x400
  ToolTipAnimation           = 0x800
  ToolTipFade                = 0x1000
  CursorShadow               = 0x2000 # 13
  Reserved14                 = 0x4000
  Reserved15                 = 0x8000
  Reserved16                 = 0x10000
  Reserved17                 = 0x20000
  Reserved18                 = 0x40000
  Reserved19                 = 0x80000
  Reserved20                 = 0x100000
  Reserved21                 = 0x200000
  Reserved22                 = 0x400000
  Reserved23                 = 0x800000
  Reserved24                 = 0x1000000
  Reserved25                 = 0x2000000
  Reserved26                 = 0x4000000
  Reserved27                 = 0x8000000
  Reserved28                 = 0x10000000
  Reserved29                 = 0x20000000
  Reserved30                 = 0x40000000
  UIEffects                  = 0x80000000 # 31
}                

Вы можете сделать:

$myVal = get-itemproperty 'HKCU:\Control Panel\Desktop' UserPreferencesMask |
  % UserPreferencesMask
$b = [bitconverter]::ToInt32($myVal,0)

'0x{0:x}' -f $b
0x80073e9e

[UserPreferencesMask]$b
MenuAnimation, ComboBoxAnimation, ListBoxSmoothScrolling,
 GradientCaptions, HotTracking, MenuFade, SelectionFade,
 ToolTipAnimation, ToolTipFade, CursorShadow, Reserved16, Reserved17,
 Reserved18, UIEffects

[UserPreferencesMask]$b -band 'CursorShadow'
CursorShadow

if ([UserPreferencesMask]$b -band 'CursorShadow') { 'yes' }
yes

Обратите внимание, что 3 недокументированных зарезервированных бита уже используются в моем Windows 10. Это с "show shadows" под указателем мыши "проверено в" параметрах производительности "(расширенная система) на панели управления

ИЛИ, получая просто без перечислений:

$b = [bitconverter]::ToInt32($myVal,0)  # 4 bytes from reg_binary to int
if ($b -band [math]::pow(2,13)) { 'cursor shadow' } 

Я заметил, что эта запись реестра на самом деле длина 8 байтов, но ввод всех 8 байтов не меняет ответ, даже если некоторые из этих дополнительных битов установлены в windows 10.

2 голосов
/ 17 января 2020

Чтобы найти указанный c бит:

Вам необходимо вычислить индекс байт (начиная с 0) путем деления индекса абсолютный бит 8:
[math]::floor(13 / 8) → байт 1 для абсолютного бита 13
* Примечание: как указано @ mklement0 , для этого нельзя использовать [Int] как не округляется, см .: деление и округление

Затем вычислить индекс относительный бит в этом байте, найдя остаток ( по модулю ) деления:
$BitIndex - 8 * $ByteIndex → 13 - (8 * 1) = 5
* Примечание: я не , используя арифметику Оператор c (%) для модуля из-за операции по модулю с отрицательными числами , и я использовал [math]::floor против [math]::truncate для округления. Таким образом, функция также поддерживает отрицательные битовые индексы, причем -1 относится к старшему значимому биту

Затем создайте байтовую маску из относительного бита:
[Byte][math]::pow(2, <relative bit>) → 2 5 = 32 (20h)

И, наконец, замаскируйте (-bAnd) соответствующий байт:
[Bool]($ByteArray[$ByteIndex] -bAnd $ByteMask) → 62 bAnd 32 = 32 (true), 30 bAnd 32 = 0 ( false)

Чтобы сделать это более ясным, я поместил это в Test-Bit функцию:

Function Test-Bit([Int]$BitIndex, [Byte[]]$ByteArray) {
    $ByteIndex = [math]::floor($BitIndex / 8)
    $ByteMask = [Byte][math]::pow(2, ($BitIndex - 8 * $ByteIndex))
    [Bool]($ByteArray[$ByteIndex] -bAnd $ByteMask)
}

* Примечание: Test-Bit функция основана на порядке байтов с прямым порядком байтов (см .: Endianness )

Тест:

Test-Bit 13 ([Byte[]](0xbe, 0x3e, 0x07, 0x80, 0x12, 0x01, 0x00, 0x00)) # True
Test-Bit 13 ([Byte[]](0xbe, 0x1e, 0x07, 0x80, 0x12, 0x01, 0x00, 0x00)) # False

Специфика c на ваш вопрос:

$RegConnect = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]"CurrentUser", "$env:COMPUTERNAME")
$RegCursors = $RegConnect.OpenSubKey("Control Panel\Desktop", $true)
$MyVal = $RegCursors.GetValue("UserPreferencesMask")
$State = Test-Bit 13 $MyVal
If ($State) {
    # Cursor shadow is enabled
} Else {
    # Cursor shadow is disabled
}
$RegCursors.Close()
$RegConnect.Close()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...