【问题标题】:Powershell Hex, Int and Bit flag checkingPowershell Hex、Int 和 Bit 标志检查
【发布时间】:2022-10-20 15:58:46
【问题描述】:

我正在尝试处理来自 MECM 命令的标志获取 CMTaskSequenceDeployment称为“广告标志”。

来自 Microsoft 的与此值相关的信息是 HERE

返回的值指定为:数据类型:UInt32

在标志表中,我需要检查的标志如下:

Hexadecimal (Bit) Description
0x00000020 (5) IMMEDIATE. Announce the advertisement to the user immediately.

作为我的 Powershell 脚本的一部分,我试图确定是否设置了此标志。

我可以通过将其转换为二进制来看到某个特定位被设置。

启用设置时:

DRIVE:\> [convert]::ToString((Get-CMTaskSequenceDeployment -AdvertisementID ABC20723).AdvertFlags, 2) 
100110010000000000100000

当设置被禁用时:

DRIVE:\> [convert]::ToString((Get-CMTaskSequenceDeployment -AdvertisementID ABC20723).AdvertFlags, 2) 
100110010000000000000000

第 6 位已更改。伟大的!不过到目前为止,我一直无法找到一种方法来检查该位是否已设置。我怀疑按位运算符(-band -bor 等)中的某些东西会在这里帮助我,但我一直无法让它工作。

我尝试的任何按位运算都会返回错误:

"System.UInt64". Error: "Value was either too large or too small for a UInt64."

我的意思是,我可以逐字比较字符串,但其他选项可能随时更改。

非常感谢任何帮助。

编辑:作为我看到的错误的一个例子,我可以看到设置的位是'32',根据我有限的理解,我应该能够:

PS:\> '100110010000000000100000' -band '32'
Cannot convert value "100110010000000000100000" to type "System.UInt64". Error: "Value was either too large or too small for a UInt64."
At line:1 char:1
+ '100110010000000000100000' -band '32'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvalidCastIConvertible

但我总是返回一个错误

【问题讨论】:

  • $enabled = [bool]((Get-CMTaskSequenceDeployment -AdvertisementID ABC20723).AdvertFlags -band 32) 不会给你想要的结果吗?

标签: powershell bit-manipulation bitwise-operators bit


【解决方案1】:

测试bit6 in

$AdvertFlags = (Get-CMTaskSequenceDeployment -AdvertisementID ABC20723).AdvertFlags

应该只是:

if ($AdvertFlags -band 32) { 'bit6 is set' } else { 'bit6 is not set' }

我无法使用Get-CMTaskSequenceDeployment cmdlet 访问部署环境,但要确认我在说什么:

$AdvertFlags = [Convert]::ToUInt32("100110010000000000100000", 2)
$AdvertFlags
10027040
if ($AdvertFlags -band 32) { 'bit6 is set' } else { 'bit6 is not set' }
bit6 is set
$AdvertFlags = [Convert]::ToUInt32("100110010000000000000000", 2)
$AdvertFlags
10027008
if ($AdvertFlags -band 32) { 'bit6 is set' } else { 'bit6 is not set' }
bit6 is not set

您使用[bigint]'100110010000000000100000' -band "32" 测试bit6 的自我回答仅仅是它返回预期值的巧合:

10027035..10027045 |ForEach-Object {
    $Binary = [convert]::ToString($_, 2)
    [pscustomobject]@{
        Binary = $Binary
        bAnd   = $_ -bAnd 32
        Bigint = [bigint]$Binary -band "32"
    }
}

产量:

Binary                   bAnd Bigint
------                   ---- ------
100110010000000000011011    0      0
100110010000000000011100    0      0
100110010000000000011101    0      0
100110010000000000011110    0     32 # ← incorrect
100110010000000000011111    0     32 # ← incorrect
100110010000000000100000   32     32
100110010000000000100001   32     32
100110010000000000100010   32     32
100110010000000000100011   32     32
100110010000000000100100   32      0 # ← incorrect
100110010000000000100101   32      0 # ← incorrect

enumerations as flags

但是 PowerShell 有一个更好的方法来按名称测试它们:

[Flags()] enum AdvertFlags {
    IMMEDIATE                         = 0x00000020 # Announce the advertisement to the user immediately.
    ONSYSTEMSTARTUP                   = 0x00000100 # Announce the advertisement to the user on system startup.
    ONUSERLOGON                       = 0x00000200 # Announce the advertisement to the user on logon.
    ONUSERLOGOFF                      = 0x00000400 # Announce the advertisement to the user on logoff.
    OPTIONALPREDOWNLOAD               = 0x00001000 # If the selected architecture and language matches that of the client, the package content will be downloaded in advance
    WINDOWS_CE                        = 0x00008000 # The advertisement is for a device client.
    ENABLE_PEER_CACHING               = 0x00010000 # This information applies to System Center 2012 Configuration Manager SP1 or later, and System Center 2012 R2 Configuration Manager or later.
    DONOT_FALLBACK                    = 0x00020000 # Do not fall back to unprotected distribution points.
    ENABLE_TS_FROM_CD_AND_PXE         = 0x00040000 # The task sequence is available to removable media and the pre-boot execution environment (PXE) service point.
    APTSINTRANETONLY                  = 0x00080000 #
    OVERRIDE_SERVICE_WINDOWS          = 0x00100000 # Override maintenance windows in announcing the advertisement to the user.
    REBOOT_OUTSIDE_OF_SERVICE_WINDOWS = 0x00200000 # Reboot outside of maintenance windows.
    WAKE_ON_LAN_ENABLED               = 0x00400000 # Announce the advertisement to the user with Wake On LAN enabled.
    SHOW_PROGRESS                     = 0x00800000 # Announce the advertisement to the user showing task sequence progress.
    NO_DISPLAY                        = 0x02000000 # The user should not run programs independently of the assignment.
    ONSLOWNET                         = 0x04000000 # Assignments are mandatory over a slow network connection.
    TARGETTOWINPE                     = 0x10000000 # Target this deployment to WinPE only.
    HIDDENINWINPE                     = 0x20000000 # Target this deployment to WinPE only but hide in WinPE. It can only be used by TS variable SMSTSPreferredAdvertID.
}

# $AdvertFlags = [AdvertFlags](Get-CMTaskSequenceDeployment -AdvertisementID ABC20723).AdvertFlags
$AdvertFlags = [AdvertFlags][Convert]::ToUInt32("100110010000000000100000", 2)
# or: $AdvertFlags = [AdvertFlags]('IMMEDIATE', 'ENABLE_PEER_CACHING', 'APTSINTRANETONLY', 'OVERRIDE_SERVICE_WINDOWS', 'SHOW_PROGRESS')
$AdvertFlags
IMMEDIATE, ENABLE_PEER_CACHING, APTSINTRANETONLY, OVERRIDE_SERVICE_WINDOWS, SHOW_PROGRESS
$AdvertFlags -bAnd [AdvertFlags]'IMMEDIATE'
IMMEDIATE

【讨论】:

  • 哇,感谢您的深入回复。我今天将对其进行测试并标记为已回答。当我找到我的答案时,我怀疑它可能不正确。再次感谢!
【解决方案2】:

编辑:如上所述,我的回答不正确。离开这里是为了繁荣!

与往常一样,我相信我在发布后几分钟就找到了答案(花了几个小时之后!)。

通过将类型调整为 [bigint],比较能够完成并返回预期的答案:

DRIVE:> [bigint]'100110010000000000100000' -band "32"
32

所以一个简单的:

If (([bigint]'100110010000000000100000' -band "32") -gt 0){$true}else{$false}
True

和:

If (([bigint]'100110010000000000000000' -band "32") -gt 0){$true}else{$false}
False

解决了我的问题。如果这不是理想的继续方式,请随时提供任何额外的建议。

我虽然在自动定义类型等时 PS 会很聪明。但这是针对 Server 2012 R2 上的 PS5。

【讨论】:

  • 您可以在不将标志转换为字符串的情况下执行此操作:if( (Get-CMTaskSequenceDeployment -AdvertisementID ABC20723).AdvertFlags -band 0x20) ) {$true} else {$false}
猜你喜欢
  • 2012-12-26
  • 1970-01-01
  • 2021-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-15
  • 2015-11-08
  • 2015-06-16
相关资源
最近更新 更多