PowerShell 技能连载 - Creating Aligned Headers

Reporting and writing log files is a common task in PowerShell. Here is a simple function to create nicely centered headers. Adjust $width to the desired width:

function Show-Header($Text)
{
  $Width=80
  $padLeft = [int]($width / 2) + ($text.Length / 2)
  $text.PadLeft($padLeft, "=").PadRight($Width, "=")
}

And this is the result:

PS> Show-Header Starting
====================================Starting====================================

PS> Show-Header "Processing Input Values"
=============================Processing Input Values============================

PS> Show-Header "Calculating..."
=================================Calculating...=================================

PS> Show-Header "OK"
=======================================OK=======================================

The additional learning points are:

  • Use PadLeft() and PadRight() to pad (expand) a string at either end, and fill space up with the characters you want
    With this learning point, you can now do many related things, i.e. create list of server names with fixed-length numbers:

1,4,12,888 | ForEach-Object { 'Server_' + "$_".PadLeft(8, "0") }

Server_00000001
Server_00000004
Server_00000012
Server_00000888

psconf.eu – PowerShell Conference EU 2019 – June 4-7, Hannover Germany – visit www.psconf.eu There aren’t too many trainings around for experienced PowerShell scripters where you really still learn something new. But there’s one place you don’t want to miss: PowerShell Conference EU - with 40 renown international speakers including PowerShell team members and MVPs, plus 350 professional and creative PowerShell scripters. Registration is open at www.psconf.eu, and the full 3-track 4-days agenda becomes available soon. Once a year it’s just a smart move to come together, update know-how, learn about security and mitigations, and bring home fresh ideas and authoritative guidance. We’d sure love to see and hear from you!

评论

PowerShell 技能连载 - 计算机名、DNS 名称,和 IP 地址

以下是一个单行的代码,返回您计算机的当前 IP 地址和它的完整 DNS 名:

1
2
3
4
5
PS> [System.Net.Dns]::GetHostEntry('')

HostName Aliases AddressList
-------- ------- -----------
DESKTOP-7AAMJLF {} {fe80::532:c4e:c409:b987%18, 192.168.2.129}

要检测一台远程的及其,只需要传入远程计算机的名字来代替空白字符串即可:

1
2
3
4
5
PS> [System.Net.Dns]::GetHostEntry('microsoft.com')

HostName Aliases AddressList
-------- ------- -----------
microsoft.com {} {40.113.200.201, 40.76.4.15, 104.215.148.63, 13.77.161.179...}

如果你只希望获取绑定的 IP 地址列表,请试试以下代码:

1
2
3
4
5
6
PS> [System.Net.Dns]::GetHostEntry('microsoft.com').AddressList.IPAddressToString
40.113.200.201
40.76.4.15
104.215.148.63
13.77.161.179
40.112.72.205

今日知识点:

  • System.Net.Dns 类包含许多有用的 DNS 相关方法。GetHostEntry() 非常有用,因为它既可以接受计算机名称也可以接受 IP 地址,并返回对应的 DNS 名和 IP 地址。
  • 传入空白字符串可以查看本机的设置。
评论

PowerShell 技能连载 - 管理 Windows 授权密钥(第 4 部分)

Slmgr.vbs 是一个用于自动化 Windows 许可证管理的古老的 VBScript。在前一个技能中我们开始直接读取 WMI,跳过 slmgr.vbs。除了已经介绍过的 SoftwareLicensingService 类,还有一个 SoftwareLicensingProduct 拥有许多实例并且获取需要一些时间:

1
Get-WmiObject -Class SoftwareLicensingProduct | Out-GridView

描述列展示了这个类描述了 Windows 中许多不同的可用的许可证类型,只有其中的一部分有获得授权。要获得有用的信息,您需要过滤出正在使用的许可证信息。

-Filter 参数来使用服务端过滤器可以大大加速查询速度。请确保 WMI 只返回 ProductKeyId 非空的实例:

1
Get-WmiObject -Class SoftwareLicensingProduct -Filter 'ProductKeyId != NULL' | Select-Object -Property Name, Description, LicenseStatus, EvaluationEndDate, PartialProductKey, ProductKeyChannel, RemainingAppRearmCount, trustedTime, UseLicenseUrl, ValidationUrl | Out-GridView

结果显示在一个网格视图窗口中,看起来类似这样:

Name                   : Office 16, Office16ProPlusR_Grace edition
Description            : Office 16, RETAIL(Grace) channel
LicenseStatus          : 5
EvaluationEndDate      : 16010101000000.000000-000
PartialProductKey      : XXXXX
ProductKeyChannel      : Retail
RemainingAppRearmCount : 1
trustedTime            : 20190203111404.180000-000
UseLicenseUrl          : https://activation.sls.microsoft.com/SLActivateProduct/SLActivateProduct.asmx?c
                         onfigextension=o14
ValidationUrl          : https://go.microsoft.com/fwlink/?LinkID=187557

Name                   : Office 16, Office16ProPlusMSDNR_Retail edition
Description            : Office 16, RETAIL channel
LicenseStatus          : 1
EvaluationEndDate      : 16010101000000.000000-000
PartialProductKey      : XXXXX
ProductKeyChannel      : Retail
RemainingAppRearmCount : 1
trustedTime            : 20190203111404.622000-000
UseLicenseUrl          : https://activation.sls.microsoft.com/SLActivateProduct/SLActivateProduct.asmx?c
                         onfigextension=o14
ValidationUrl          : https://go.microsoft.com/fwlink/?LinkID=187557

Name                   : Windows(R), Professional edition
Description            : Windows(R) Operating System, OEM_DM channel
LicenseStatus          : 1
EvaluationEndDate      : 16010101000000.000000-000
PartialProductKey      : XXXXX
ProductKeyChannel      : OEM:DM
RemainingAppRearmCount : 1001
trustedTime            : 20190203111405.221000-000
UseLicenseUrl          : https://activation-v2.sls.microsoft.com/SLActivateProduct/SLActivateProduct.asm
                         x?configextension=DM
ValidationUrl          : https://validation-v2.sls.microsoft.com/SLWGA/slwga.asmx

如您所见,日期是以 WMI 格式返回的。用 Get-CimInstance 代替 Get-WmiObject 来获取“真实的”日期对象:

1
PS> Get-CimInstance -Class SoftwareLicensingProduct -Filter 'ProductKeyId != NULL' | Select-Object -Property Name, Description, LicenseStatus, EvaluationEndDate, PartialProductKey, ProductKeyChannel, RemainingAppRearmCount, trustedTime, UseLicenseUrl, ValidationUrl

今日知识点:

  • 通过 SoftwareLicensingProduct WMI 类可以获取到独立的微软产品(包括 Office)许可证信息。
  • 如果您希望 PowerShell 返回可阅读的 DateTime 对象,而不是难阅读的 WMI 日期格式,请使用 Get-CimInstance 来代替 Get-WmiObject
评论

PowerShell 技能连载 - 管理 Windows 授权密钥(第 3 部分)

多数 Windows 许可证激活任务可以通过一个古老的名为 slmgr.vbs 的 VBScript 来实现自动化。不过,用这个工具来获取信息的意义不大。因为 slmgr.vbs 使用的事本地化的字符串,并且将所有数据转换为一个大字符串格式。

一个更好的方法是跳过 slmgr.vbs,而直接查询信息源。要搞清 slmgr.vbs 如何实现这些功能,您可以查看该脚本的源码。请在 PowerShell ISE 中运行这段代码:

1
2
3
4
# get the path to the script file
$Path = Get-Command slmgr.vbs | Select-Object -ExpandProperty Source
# load the script file
$file = $psise.CurrentPowerShellTab.Files.Add($Path)

让我开始将这部分功能转换为 PowerShell。例如 /dlv 参数显示许可证信息:

1
PS> slmgr.vbs /dlv

当您在 VBScript 源码中搜索 “dlv”,能快速找到所有相关的核心代码,有一个名为 GetServiceObject() 的函数,是关于简单 WMI 查询的:

1
g_objWMIService.ExecQuery("SELECT " & strQuery & " FROM " & ServiceClass)

实际上,该脚本展现了关于许可证方面的 WMI 类。从 PowerShell 中您可以方便地查询所有跟它有关的服务信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
PS> Get-WmiObject -Class SoftwareLicensingService


__GENUS : 2
__CLASS : SoftwareLicensingService
__SUPERCLASS :
__DYNASTY : SoftwareLicensingService
__RELPATH : SoftwareLicensingService.Version="10.0.17134.471"
__PROPERTY_COUNT : 38
__DERIVATION : {}
__SERVER : DESKTOP-7AAMJLF
__NAMESPACE : root\cimv2
__PATH : \\DESKTOP-7AAMJLF\root\cimv2:SoftwareLicensingService.Version="10.0.17134.471"
ClientMachineID :
DiscoveredKeyManagementServiceMachineIpAddress :
DiscoveredKeyManagementServiceMachineName :
DiscoveredKeyManagementServiceMachinePort : 0
IsKeyManagementServiceMachine : 0
KeyManagementServiceCurrentCount : 4294967295
KeyManagementServiceDnsPublishing : True
KeyManagementServiceFailedRequests : 4294967295
KeyManagementServiceHostCaching : True
KeyManagementServiceLicensedRequests : 4294967295
KeyManagementServiceListeningPort : 1688
KeyManagementServiceLookupDomain :
KeyManagementServiceLowPriority : False
KeyManagementServiceMachine :
KeyManagementServiceNonGenuineGraceRequests : 4294967295
KeyManagementServiceNotificationRequests : 4294967295
KeyManagementServiceOOBGraceRequests : 4294967295
KeyManagementServiceOOTGraceRequests : 4294967295
KeyManagementServicePort : 1688
KeyManagementServiceProductKeyID :
KeyManagementServiceTotalRequests : 4294967295
KeyManagementServiceUnlicensedRequests : 4294967295
OA2xBiosMarkerMinorVersion : 1
OA2xBiosMarkerStatus : 1
OA3xOriginalProductKey : XXXXXXXXXXXXXXXXXXXXXXXXX
OA3xOriginalProductKeyDescription : [4.0] Professional OEM
OA3xOriginalProductKeyPkPn : [TH]XXXXXXX
PolicyCacheRefreshRequired : 0
RemainingWindowsReArmCount : 1001
RequiredClientCount : 4294967295
TokenActivationAdditionalInfo :
TokenActivationCertificateThumbprint :
TokenActivationGrantNumber : 4294967295
TokenActivationILID :
TokenActivationILVID : 4294967295
Version : 10.0.17134.471
VLActivationInterval : 4294967295
VLRenewalInterval : 4294967295
PSComputerName : DESKTOP-7AAMJLF

slmgr.vbs 不同,您可以以面向对象的格式获得该信息,所以访问具体的项十分容易:

1
2
3
4
5
6
7
8
PS> $all = Get-WmiObject -Class SoftwareLicensingService

PS> $all.OA3xOriginalProductKeyDescription
[4.0] Professional OEM:DM


funcValue 1
}

还有更多内容可以发现。

今日知识点:

  • slmgr.vbs 返回的所有 Windows 许可证信息都来自 WMI。相比于 slmgr.vbs 收到的是难以阅读的文本,您可以直接查询 WMI 并跳过 slmgr.vbs
  • 一个大数据源是 SoftwareLicensingService WMI 类。
评论

PowerShell 技能连载 - 管理 Windows 授权密钥(第 2 部分)

大多数的授权密钥管理任务都可以通过 slmgr 命令完成。

This command is actually an ancient VBScript. To read all of your license settings, for example, try this:
这个命令实际上是一个古老的 VBScript。例如要读取所有许可证设置,请使用以下代码:

1
PS> slmgr.vbs /dlv

这将打开一个独立的窗口,并且显示许多许可证激活细节。在对话框窗口中显示信息对于 PowerShell 和自动化操作帮助不大,而且通过 cscript.exe 运行该 VBScript,可能会失败:

1
2
3
4
5
6
7
8
9
PS> slmgr.vbs /dlv

PS> cscript.exe slmgr.vbs /dlv
Microsoft (R) Windows Script Host, Version 5.812
Copyright (C) Microsoft Corporation. All Rights Reserved.

Script file "C:\Users\tobwe\slmgr.vbs" not found.

PS>

您可以将缺省的 VBS 宿主改为 cscript.exe,但是一个更好的不改变全局设置的做法是:找出这个 VBScript 的完整路径,然后用绝对路径执行它。以下是获得 VBScript 路径的办法:

1
2
PS> Get-Command slmgr.vbs | Select-Object -ExpandProperty Source
C:\WINDOWS\system32\slmgr.vbs

这段代码将读取该信息输出到 PowerShell 控制台:

1
2
3
$Path = Get-Command slmgr.vbs | Select-Object -ExpandProperty Source
$Data = cscript.exe //Nologo $Path /dlv
$Data

不过,$Data 包含了难以阅读的纯文本,而且是本地化的。用这种方法获取许可证和激活信息不太优雅。

由于 slmgr.exe 可以做许多神奇的许可证任务,就如打开它的帮助时看到的那样,让我们在随后的技能中检查它的源码,并且跳过以前的 VBScript 直接获取信息。

1
PS> slmgr /?

今日知识点:

  • Windows 许可证管理通常是通过一个 VBScript slmgr.vbs 来实现。当您通过 “/?“ 调用它,将会获得该命令参数的帮助信息。
  • PowerShell 可以调用 slmgr。要接收执行结果,请通过 cscript.exe 调用它,并且向 slmgr.vbs 提供完整的(绝对)路径。
  • Get-Command 是一个查找系统文件夹(在 $env:PATH 中列出的)中的文件的完整(绝对)路径的方法。
评论

PowerShell 技能连载 - 管理 Windows 许可证密钥(第 1 部分)

我们来看看这个单行的解析 Windows 许可证密钥的迷你系列:

1
2
3
4
PS> $key = (Get-WmiObject -Class SoftwareLicensingService).OA3xOriginalProductKey

PS> $key
KJU8F-XXUZH-UU776-IUZGT-HHGR5

今日知识点:

  • WMI 可以获取许多关于 Windows 许可证和 Windows 许可证状态的信息。
  • Windows 用于许可证管理的一个 WMI 名为 “SoftwareLicensingService”。它可以提供 Windows 许可证号码。
  • 同一个类叶包含了许多额外的信息。请看:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
PS> Get-WmiObject -Class SoftwareLicensingService


...
KeyManagementServiceUnlicensedRequests : 4294967295
OA2xBiosMarkerMinorVersion : 1
OA2xBiosMarkerStatus : 1
OA3xOriginalProductKey : XXXXXXXXX
OA3xOriginalProductKeyDescription : [4.0] Professional OEM:DM
OA3xOriginalProductKeyPkPn : [TH]X19-99481
PolicyCacheRefreshRequired : 0
RemainingWindowsReArmCount : 1001
RequiredClientCount : 4294967295
TokenActivationAdditionalInfo :
TokenActivationCertificateThumbprint :
TokenActivationGrantNumber : 4294967295
TokenActivationILID :
TokenActivationILVID : 4294967295
Version : 10.0.17134.471
VLActivationInterval : 4294967295
VLRenewalInterval : 4294967295
PSComputerName : DESKTOP-7AAMJLF

title: “PowerShell 技能连载 - 管理 Windows 许可证密钥”
description: PowerTip of the Day - Managing Windows License Key
categories:

  • powershell
  • tip
    tags:
  • powershell
  • tip
  • powertip
  • series

我们来看看这个单行的解析 Windows 许可证密钥的迷你系列:

1
2
3
4
PS> $key = (Get-WmiObject -Class SoftwareLicensingService).OA3xOriginalProductKey

PS> $key
KJU8F-XXUZH-UU776-IUZGT-HHGR5

今日知识点:

  • WMI 可以获取许多关于 Windows 许可证和 Windows 许可证状态的信息。
  • Windows 用于许可证管理的一个 WMI 名为 “SoftwareLicensingService”。它可以提供 Windows 许可证号码。
  • 同一个类叶包含了许多额外的信息。请看:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
PS> Get-WmiObject -Class SoftwareLicensingService


...
KeyManagementServiceUnlicensedRequests : 4294967295
OA2xBiosMarkerMinorVersion : 1
OA2xBiosMarkerStatus : 1
OA3xOriginalProductKey : XXXXXXXXX
OA3xOriginalProductKeyDescription : [4.0] Professional OEM:DM
OA3xOriginalProductKeyPkPn : [TH]X19-99481
PolicyCacheRefreshRequired : 0
RemainingWindowsReArmCount : 1001
RequiredClientCount : 4294967295
TokenActivationAdditionalInfo :
TokenActivationCertificateThumbprint :
TokenActivationGrantNumber : 4294967295
TokenActivationILID :
TokenActivationILVID : 4294967295
Version : 10.0.17134.471
VLActivationInterval : 4294967295
VLRenewalInterval : 4294967295
PSComputerName : DESKTOP-7AAMJLF
评论

PowerShell 技能连载 - 创建 ASCII 艺术

PowerShell 的功能令人惊叹:只需要几行代码,就可以将任意照片和图片转化为一段 ASCII 艺术。PowerShell 只需要加载图片,然后然后逐行逐列扫描它,然后基于每个像素的亮度将每个像素替换为一个 ASCII 字符。

以下是该函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
 function Convert-ImageToAsciiArt
{
param(
[Parameter(Mandatory)][String]
$Path,

[ValidateRange(20,20000)]
[int]$MaxWidth=80,

# character height:width ratio
[float]$ratio = 1.5
)

# load drawing functionality
Add-Type -AssemblyName System.Drawing

# characters from dark to light
$characters = '$#H&@*+;:-,. '.ToCharArray()
$c = $characters.count

# load image and get image size
$image = [Drawing.Image]::FromFile($path)
[int]$maxheight = $image.Height / ($image.Width / $maxwidth)/ $ratio

# paint image on a bitmap with the desired size
$bitmap = new-object Drawing.Bitmap($image,$maxwidth,$maxheight)


# use a string builder to store the characters
[System.Text.StringBuilder]$sb = ""

# take each pixel line...
for ([int]$y=0; $y -lt $bitmap.Height; $y++){
# take each pixel column...
for ([int]$x=0; $x -lt $bitmap.Width; $x++){
# examine pixel
$color = $bitmap.GetPixel($x,$y)
$brightness = $color.GetBrightness()
# choose the character that best matches the
# pixel brightness
[int]$offset = [Math]::Floor($brightness*$c)
$ch = $characters[$offset]
if (-not $ch){ $ch = $characters[-1] }
# add character to line
$null = $sb.Append($ch)
}
# add a new line
$null = $sb.AppendLine()
}

# clean up and return string
$image.Dispose()
$sb.ToString()
}

以下是它的使用方法:

1
2
3
4
5
6
7
8
$Path = "C:\Users\Tobias\Desktop\Somepic.jpg"
$OutPath = "$env:temp\asciiart.txt"

Convert-ImageToAsciiArt -Path $Path -MaxWidth 150 |
Set-Content -Path $OutPath -Encoding UTF8


Invoke-Item -Path $OutPath

请确保调整了代码中的路径。将会在缺省的文本编辑器中打开 ASCII 艺术。请确保禁用了换行,选择一个等宽的字体和一个足够小的字号!

                       ;@&&&&&&@&&&&@+-                                           
                     :@&&&&&&&&&&&&&&&&&&:.                                       
                   ,&&&&&&&&&&&&&&&&&&&&&&&&&&*                                   
                -@&&&&&&&&&&&HHHHHH&&&&&&&&&&&&&*                                 
             :&&&&&&&&&&&&H&&&&&&&&&&&&&&&&&&&&&&&@                               
            *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&,                             
           :&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&-                            
          *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*                           
         &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&                          
        @&&&&&&&&H&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&-                        
       &&&&&&&&H&&&@;:+&&&&&&&*-....,:@&&&&&&&&&&&&&&&&&&&@                       
      &&&&&&&&H&&;........................*&&&&&&&H&&&&&&&&&.                     
    .&&&&&&&&&H;...........................&&&&&&&&H&&&&&&&&&-                    
   ;&&&&&&&&&&:............................@@&&&&&&H&&&&&&&&&&                    
  &&&&&&&&&&&.+...........................-.;&&&H&&H&&&&&&&&&&@                   
 *&H&&&&&&&&;;..............................+@+&&HH&&&&&&&&&&&&                   
 ;&H&&&&&&&&................................@*.&&&H&&&&&&&&&&&&:                  
 :&H&&&&&&&*...............................:*..&H&&&&&&&&&&&&&&@                  
 ,&&H&&&@&@...................................,&&&&&&&&&&&&&&&&&,                 
 ,&&&&&&:+....................................+*.;:&&&&&&&&&&&&&&                 
 +&&&&&&............................................@*@+&&&&&&&&&,                
 &&&&&&;............................................,-..-+&&&&&&&                 
:&&&&&@-...................................................:&&&&&,                
&&&&&&&.....................................................&&&&&-                
&&&&&&+.....................................................&&&&&,,               
:&&&&&;.....................................................&&&H&                 
 &&&&&;.......................................,.,...........&&&&H&@               
*-&&&&:...*&&&&&&&&&&&&&@*,.............-*&&&&&&&&&&&&:.....@&&&&+                
  &&&&:.+&&HHHHHHHHHHHHH&&&&..........+&&&&HHHHHHHHHHHHH*...+&&&&@                
 ,###H*+;;:,...........-;*&&##########&&&*:..........:;*@:;*&###H:                
 :##H*.......................#@;---+#;.......................@###.                
,@###+............+HH&+.....-&......-*......;&H&*............&##:.                
 ,&&#-...........HHH&+H;....@;......,#.....@HHH;H@...........HH&-.                
 ..;#,...........HHHHHH+....#........H,....&HHHHH&..........-#&:-                 
 ...H*...........-;;;;;....-H........;@....,;;;;;,..........;#&..                 
 ...&#.....................#-.........#.....................&H*..                 
 ...:H&........,.........-#@..........-#;..........,,......:#&,..                 
  ...-,&###&+::-,,::+&###+......  ......-###H*:::,,::+@####,....                  
  ..........,,,,,,,,...........   ............,,,,,,,,..........                  
   ............................   ..............................                  
   ............................   .............................                   
    .....................,.....   ............................                    
     ....................,.....   .......,...................                     
       ..................,,,...   .......,.................                       
        ......................,.  ..,......................                       
        ........................,,,.......................                        
        ..................................................                        
         .................................................                        
         .............,-..................--.............                         
          ...............--,,-----:-,. --...............                          
           ..................,,----,,...................                          
            ...........................................                           
             .........................................                            
              ......................................                              
               ....................................                               
                 ................................                                 
                  ..............................                                  
                   .,,,,,,,,,,,,,,,,,,,,,,,,,,                                    
                 ,&...,,,,,,,,,,,,,,,,,,,,,,...@,                                 
              &HHH......,,,,,,,,,,,,,,,,,,.....-HHH&                              
          :HHHHHHH&.........,,,,,,,,,,,........HHHHHHHH;                          
       *HHHHHHHHHHHH+........................*HHHHHHHHHHHH@                       
    -HHHHHHHHHHHHHHHHH&;..................;&HHHHHHHHHHHHHHHHH,                    
   HHHHHHHHHHHHHHHHHHHHHHHH&*;:---::;*&HHHHHHHHHHHHHHHHHHHHHHH&                   
  HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH                  

这儿有一个很酷的优化技巧:在 Convert-ImageToAsciiArt 函数中,请注意 $characters。它是一个包含 ASCII 艺术中使用的字符的字符串,而这些字符是按亮度降序排列的。对于黑白作品,可以使用:

1
$characters = [char]0x2588, ' '
评论

PowerShell 技能连载 - 验证本地用户账户密码

在前一个技能VS,我们通过 Active Directory 来验证用户账户密码。同样的,对于本地账户也可以。PowerShell 代码可以使用本地账户密码来管理对脚本的存取,或部分限制脚本的功能。当然,您也可以用以下代码来创建自己的基本的密码穷举工具。

缺省情况下,以下代码使用您当前的用户名。请确保 $UserName 是某个本地账户的用户名:

1
2
3
4
5
6
7
8
9
# specify local user name and password to test
$UserName = $env:USERNAME
$Password = Read-Host -Prompt "Enter password to test"

# test password
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$type = [DirectoryServices.AccountManagement.ContextType]::Machine
$PrincipalContext = [DirectoryServices.AccountManagement.PrincipalContext]::new($type)
$PrincipalContext.ValidateCredentials($UserName,$Password)

今日的知识点:

  • PowerShell 可以请求本地的 Windows 用户数据库来验证密码。通过这种方式,您可以使用 Windows 维护的密码来决定一个脚本是否允许执行,或允许某个用户执行哪一部分。
  • 请注意向用户询问密码是一种不安全的做法,因为他们不知道密码将会被用在什么地方。
评论

PowerShell 技能连载 - 校验域账户密码

PowerShell 可以轻松地校验一个域账号的密码。换句话说,您可以为 Active Directory 维护的密码绑定一个脚本逻辑。

以下是将密码发送到 AD 并获取回一个 Boolean 值的代码:如果密码正确,返回 $true,否则返回 $false

1
2
3
4
5
6
7
8
9
10
# specify user name and user domain
$UserDomain = $env:USERDOMAIN
$UserName = $env:USERNAME
$Password = Read-Host -Prompt "Enter password to test"

# test password
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$ContextType = [System.DirectoryServices.AccountManagement.ContextType]::Domain
$PrincipalContext = [System.DirectoryServices.AccountManagement.PrincipalContext]::new($ContextType, $UserDomain)
$PrincipalContext.ValidateCredentials($UserName,$Password)

请注意这段代码需要 Active Directory 环境,并且不支持本地账号。缺省情况下,它使用您当前账号的详细信息。请根据实际情况调整 $UserDomain$UserName$Password 变量。也请注意 ValidateCredentials() 检查的是明文字符串密码。请谨慎处理并且不要在脚本存储明文密码。同时,不要要求用户以明文输入密码。

今日知识点:

  • PowerShell 可以轻松地连接到 Active Directory 并进行密码验证。
评论

PowerShell 技能连载 - 等待服务状态变化

当您启动或停止一个服务时,可能需要一些时间才能确保服务进入指定的状态——或者它当然可能会失败。当您使用 Stop-Service 时,PowerShell 将等待该服务状态已确认。如果您希望获得其它地方初始化的服务响应,以下是一段监听代码,它将会暂停 PowerShell 直到服务变为指定的状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
# wait 5 seconds for spooler service to stop
$serviceToMonitor = Get-Service -Name Spooler
$desiredStatus = [System.ServiceProcess.ServiceControllerStatus]::Stopped
$maxTimeout = New-TimeSpan -Seconds 5

try
{
$serviceToMonitor.WaitForStatus($desiredStatus, $maxTimeout)
}
catch [System.ServiceProcess.TimeoutException]
{
Write-Warning 'Service did not reach desired status within timeframe.'
}

您可以使用这段代码来响应由外部系统触发的服务改变,或者当您要求服务状态更改后做二次确认。

今日的知识点:

  • 您从 cmdlet 获得的多数对象(例如 Get-Service)有许多有用的方法。所有服务对象都有一个 WaitForStatus 方法。在我们的例子中演示了如何使用它。
  • 要发现隐藏在对象中的其它方法,请使用以下代码:
1
2
3
4
5
# get some object 
$objects = Get-Process

# dump the methods
$objects | Get-Member -MemberType *method* | Select-Object -Property Name, Definition
评论