PowerShell 技能连载 - 神秘的 Windows 10 透明模式

When you open a native PowerShell console in Windows 10, you can hold down CTRL+SHIFT, then move your mouse wheel, to adjust console background color transparency, and let other windows shine through. The same works for cmd.exe as well, of course.
当您在 Windows 10 中打开一个原生的 PowerShell 控制台,按下 CTRL + SHIFT 键,然后滚动鼠标滚轮,就可以调节控制台背景色的透明度,并且让其它窗口的内容透射出来。当然这对 cmd.exe 也是有效的。

PowerShell 技能连载 - 清空 DNS 缓存

Windows 使用了 DNS 缓存技术,如果改变了 DNS 服务器,您需要刷新 DNS 缓存以使新的设置生效。PowerShell 对传统的控制台命令是有好的,所以只需要在 PowerShell 中运行这行代码:

1
PS> ipconfig /flushdns

PowerShell 技能连载 - 显示文件夹树

PowerShell 对旧的控制台命令是十分友好的,所以要显示文件夹的树形结构,使用旧的 “tree” 命令是十分简单的。它最好工作在一个原生的 PowerShell 控制台中,因为编辑器往往使用不同的字符集。请试试这个命令:

1
PS> Tree $home

请确保您是在一个原生的 PowerShell 控制台中或 VSCode 中运行这段代码。您还可以将结果通过管道输出到 clip.exe 并将它粘贴到一个文本文档中:

1
PS> Tree $home | clip.exe

PowerShell 技能连载 - 使用缓存的端口文件

在前一个技能中我们介绍了如何用 PowerShell 通过 IANA 下载端口分配信息。这个过程需要 Internet 连接并且需要一段时间。所以以下代码会查找缓存的 CSV 文件。如果缓存文件存在,端口信息会从离线文件中加载,否则将在线加载数据,并写入缓存文件。请特别注意如何使用 Tee-Object 命令创建缓存文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$url = 'https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.csv'
$CSVFile = "$env:temp\ports.csv"
$exists = Test-Path -Path $CSVFile

if (!$exists)
{
Write-Warning "Retrieving data online..."

$portinfo = Invoke-WebRequest -Uri $Url -UseBasicParsing | `
Select-Object -ExpandProperty Content | `
Tee-Object -FilePath $CSVFile | ConvertFrom-Csv
}
else
{
Write-Warning "Loading cached file..."
$portinfo = Import-Csv -Path $CSVFile
}

$portinfo | Out-GridView

PowerShell 技能连载 - 获取端口分配列表

IANA(互联网数字分配机构)维护了一个包含所有已知的端口分配的 CSV 文件。PowerShell 可以为您下载这个列表:

1
2
3
4
$out = "$env:temp\portlist.csv"
$url = 'https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.csv'
$web = Invoke-WebRequest -Uri $url -UseBasicParsing -OutFile $out
Import-Csv -Path $out -Encoding UTF8

返回的结果是一个包含所有的端口分配的面向对象格式的列表。接下来您可以使用这个信息例如过滤特定的端口:

1
2
3
Import-Csv -Path $out -Encoding UTF8 |
Where-Object 'transport protocol' -eq 'tcp' |
Where-Object 'Port Number' -lt 1000

PowerShell 技能连载 - 世界时钟

PowerShell 提供了 Get-TimeZone 命令,能返回所有定义过的时区和它们的时差。以下是列出世界时钟相关的代码:

1
2
3
4
5
6
7
8
9
10
11
12
$isSummer = (Get-Date).IsDaylightSavingTime()


Get-TimeZone -ListAvailable | ForEach-Object {
$dateTime = [DateTime]::UtcNow + $_.BaseUtcOffset
$cities = $_.DisplayName.Split(')')[-1].Trim()
if ($isSummer -and $_.SupportsDaylightSavingTime)
{
$dateTime = $dateTime.AddHours(1)
}
'{0,-30}: {1:HH:mm"h"} ({2})' -f $_.Id, $dateTime, $cities
}

结果类似如下:

Dateline Standard Time         : 18:41h ()
UTC-11                         : 19:41h (Coordinated Universal Time-11)
Aleutian Standard Time         : 21:41h (Aleutian Islands)
Hawaiian Standard Time         : 20:41h (Hawaii)
Marquesas Standard Time        : 21:11h (Marquesas Islands)
Alaskan Standard Time          : 22:41h (Alaska)
UTC-09                         : 21:41h (Coordinated Universal Time-09)
Pacific Standard Time (Mexico) : 23:41h (Baja California)
UTC-08                         : 22:41h (Coordinated Universal Time-08)
Pacific Standard Time          : 23:41h ()
US Mountain Standard Time      : 23:41h (Arizona)
Mountain Standard Time (Mexico): 00:41h (Chihuahua, La Paz, Mazatlan)
Mountain Standard Time         : 00:41h ()
Central America Standard Time  : 00:41h (Central America)
Central Standard Time          : 01:41h ()
Easter Island Standard Time    : 01:41h (Easter Island)
Central Standard Time (Mexico) : 01:41h (Guadalajara, Mexico City, Monterrey)
Canada Central Standard Time   : 00:41h (Saskatchewan)
SA Pacific Standard Time       : 01:41h (Bogota, Lima, Quito, Rio Branco)
Eastern Standard Time (Mexico) : 02:41h (Chetumal)
Eastern Standard Time          : 02:41h ()

PowerShell 技能连载 - 设置时区

只有拥有了管理员特权才可以修改电脑的时间和日期,但任何用户都可以修改时区,例如当您在旅游时。PowerShell 5 提供了一系列非常简单的 cmdlet 来管理时区。首先,检查您的当前设置:

1
2
3
4
5
6
7
8
9
PS> Get-TimeZone


Id : W. Europe Standard Time
DisplayName : (UTC+01:00) Amsterdam, Berlin, Bern, Rom, Stockholm, Wien
StandardName : Mitteleuropäische Zeit
DaylightName : Mitteleuropäische Sommerzeit
BaseUtcOffset : 01:00:00
SupportsDaylightSavingTime : True

下一步,尝试修改时区。以下代码打开一个包含所有可用时区的窗口:

1
PS> Get-TimeZone -ListAvailable | Out-GridView

当您知道您希望设置的时区的正式 ID 后,请使用 Set-TimeZone 命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
PS> Set-TimeZone -Id 'Chatham Islands Standard Time'

PS> Get-Date

Samstag, 27. Mai 2017 18:32:53



PS> Set-TimeZone -Id 'W. Europe Standard Time'

PS> Get-Date

Samstag, 27. Mai 2017 07:48:02

PowerShell 技能连载 - 查找一个脚本中的所有变量

在前一个技能中我们掩饰了如何分析一段脚本块的内容并且搜索变量或命令。这种技术也适用于基于文本的脚本。以下脚本将会检查自己并且提取出变量和命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$filepath = $PSCommandPath
$tokens = $errors = $null

$ast = [System.Management.Automation.Language.Parser]::ParseFile($filepath, [ref]$tokens, [ref]$errors )

# find variables
$ast.FindAll( { $true }, $true) |
Where-Object { $_.GetType().Name -eq 'VariableExpressionAst' } |
Select-Object -Property VariablePath -ExpandProperty Extent |
Select-Object -Property * -ExcludeProperty *ScriptPosition |
Out-GridView -Title 'Variables'


# find commands
$ast.FindAll( { $true }, $true) |
Where-Object { $_.GetType().Name -eq 'CommandAst' } |
Select-Object -ExpandProperty Extent |
Select-Object -Property * -ExcludeProperty *ScriptPosition |
Out-GridView -Title 'Commands'

请确保将脚本保存到硬盘,或为 $filepath 指定一个不同的实际存在的脚本路径。

PowerShell 技能连载 - 查找一个脚本块中的所有变量

要分析一个脚本快中的内容,您可以简单地检查 AST,并且,例如创建一个包含代码中所有变量的清单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$code = {

$a = "Test"
$b = 12
Get-Service
Get-Process
$berta = 100

}


$code.Ast.FindAll( { $true }, $true) |
Where-Object { $_.GetType().Name -eq 'VariableExpressionAst' } |
Select-Object -Property VariablePath -ExpandProperty Extent |
Out-GridView

如果您想查看所有的命令,请试试以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$code = {

$a = "Test"
$b = 12
Get-Service
Get-Process
$berta = 100

}


$code.Ast.FindAll( { $true }, $true) |
Where-Object { $_.GetType().Name -eq 'CommandAst' } |
Select-Object -ExpandProperty Extent |
Select-Object -Property * -ExcludeProperty *ScriptPosition |
Out-GridView

这在根据脚本块自动生成文档的时候非常有用。