PowerShell 技能连载 - 探索 Windows 上的程序包管理器(第 1 部分)

在 Linux 世界中,程序包管理器是一种下载和安装软件的既定方法。在 Windows 上,包管理器对于许多人来说仍然是新概念。

如果您是 Windows 系统管理员,并且想为所有用户下载并安装标准软件包,那么 “Chocolatey” 将是首选。该程序包管理器在拥有完全管理员权限的情况下最有效,并使用其默认安装程序包安装软件。

注意:为了能够运行脚本和下载代码,作为先决条件,您可能必须运行以下代码:

1
2
3
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor
[System.Net.SecurityProtocolType]::Tls12
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force

要安装 Chocolatey,请在 PowerShell 中运行以下行:

1
Invoke-RestMethod -UseBasicParsing -Uri 'https://chocolatey.org/install.ps1' | Invoke-Expression

安装成功后,会有一个名为 choco 的新命令,您现在可以使用该命令下载和安装软件。

例如,如果您想为所有用户安装 PowerShell 7,请运行以下命令:

1
choco install powershell-core
评论

PowerShell 技能连载 - 在 Windows 上安装 PowerShell 7 的最简单方法

为 Windows 用户下载和安装 PowerShell 7 的最简单,最灵活的方法可能是运行以下单行代码:

1
Invoke-RestMethod -Uri https://aka.ms/install-powershell.ps1 | New-Item -Path function: -Name Install-PowerShell | Out-Null

它创建了一个拥有许多参数的 cmdlet Install-PowerShell。例如,要将 Windows 7 的最新生产版本作为便携式应用程序下载到您选择的文件夹中,请运行以下命令:

1
Install-PowerShell -Destination c:\ps7test -AddToPath

如果您希望以托管的 MSI 应用程序的形式安装 PowerShell 7,请运行以下命令:

1
Install-PowerShell -UseMSI -Quiet

注意:真正安静的安装需要管理员权限。

评论

PowerShell 技能连载 - 将文本翻译成莫尔斯电码

似乎几乎所有东西都有 Web Service。这是一个将文本转换为摩尔斯电码的 Web Service:

1
2
3
4
5
6
7
8
9
10
11
$Text = 'SOS This is an emergency!'

# URL-encode text
Add-Type -AssemblyName System.Web
$encoded = [System.Web.HttpUtility]::UrlEncode($Text)

# compose web service URL
$Url = "https://api.funtranslations.com/translate/morse.json?text=$encoded"

# call web service
(Invoke-RestMethod -UseBasicParsing -Uri $url).contents.translated

结果看起来像这样:

... --- ...     - .... .. ...     .. ...     .- -.     . -- . .-. --. . -. -.-. -.-- ---.

如果您确实对摩尔斯电码有兴趣,请解析结果文本并创建真正的哔哔声:

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
$Text = 'Happy New Year 2021!'

# URL-encode text
Add-Type -AssemblyName System.Web
$encoded = [System.Web.HttpUtility]::UrlEncode($Text)

# compose web service URL
$Url = "https://api.funtranslations.com/translate/morse.json?text=$encoded"

# call web service
$morse = (Invoke-RestMethod -UseBasicParsing -Uri $url).contents.translated

Foreach ($char in $morse.ToCharArray())
{
switch ($char)
{
'.' { [Console]::Beep(800, 300) }
'-' { [Console]::Beep(800, 900) }
' ' { Start-Sleep -Milliseconds 500 }
default { Write-Warning "Unknown char: $_"
[Console]::Beep(2000, 500) }

}
Write-Host $char -NoNewline
Start-Sleep -Milliseconds 200
}
Write-Host "OK"
评论

PowerShell 技能连载 - 使用 GitHub Web Service(第 2 部分)

在上一个技能中,我们研究了组织的 GitHub Web 服务 API。现在,让我们看看如何使用单个 GitHub 帐户。

Doug Finke has created a wonderful open-source PowerShell module called “ImportExcel” that makes working with Excel files a snap: https://github.com/dfinke/ImportExcel. His public GitHub user name is dfinke.
道格·芬克(Doug Finke)创建了一个名为 “ImportExcel” 的出色的开源 PowerShell 模块,该模块使处理 Excel 文件变得轻而易举:https://github.com/dfinke/ImportExcel。他的公共 GitHub 用户名是 dfinke。

要查找他的作品的最新版本以及在何处下载,请尝试以下操作:

1
2
3
4
5
$username = 'dfinke'
$reponame = 'ImportExcel'
$url = "https://api.github.com/repos/$username/$reponame/releases/latest"
Invoke-RestMethod -UseBasicParsing -Uri $url |
Select-Object -Property tag_name, published_at, zipball_url, name

结果看起来像这样:

tag_name published_at         zipball_url
-------- ------------         -----------
v7.1.0   2020-03-21T00:38:13Z https://api.github.com/repos/dfinke/ImportExcel/zipball/v7.1.0

请注意,下载 URL 将下载 GitHub 上所见的整个软件工程。如果您只想使用他的 PowerShell 模块,请选择发布到 PowerShell Gallery 的即用型 PowerShell 模块:

1
PS> Install-Module -Name ImportExcel -Scope CurrentUser

安装模块后,由于 Doug 的出色工作,您现在可以将任何数据通过管道传输到 Export-Excel。如果愿意,请创建包含 Doug 模块完整版本历史记录的 Excel 工作表:

1
2
3
4
5
6
7
8
9
10
11
12
13
$username = 'dfinke'
$reponame = 'ImportExcel'
$url = https://api.github.com/repos/$username/$reponame/releases

Invoke-RestMethod -UseBasicParsing -Uri $url |

# workaround needed for any JSON web service result that
# consists of more than one dataset
ForEach-Object { $_ } |

Sort-Object -Property published_at -Descending |
Select-Object -Property published_at, Name, Url, body |
Export-Excel
评论

PowerShell 技能连载 - 使用 GitHub Web Service(第 1 部分)

如今,GitHub 托管了许多开源软件。这包括诸如 Windows Terminal 或 Visual Studio Code 编辑器之类的强大工具。

GitHub 提供公共 web service 来查询已注册组织(例如 Microsoft)的 repository 详细信息,因此,如果您想了解特定软件是否有新版本,请尝试查询该 web service。

下面的示例查询组织 “Microsoft” 中 “Windows Terminal” repository 的详细信息:

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
PS> $url = 'https://api.github.com/repos/microsoft/terminal/releases/latest'
PS> Invoke-RestMethod -UseBasicParsing -Uri $url


url : https://api.github.com/repos/microsoft/terminal/releases/34250658
assets_url : https://api.github.com/repos/microsoft/terminal/releases/34250658/assets
upload_url : https://uploads.github.com/repos/microsoft/terminal/releases/34250658/asse
ts{?name,label}
html_url : https://github.com/microsoft/terminal/releases/tag/v1.4.3243.0
id : 34250658
author : @{login=DHowett; id=189190; node_id=MDQ6VXNlcjE4OTE5MA==;
avatar_url=https://avatars2.githubusercontent.com/u/189190?v=4;
gravatar_id=; url=https://api.github.com/users/DHowett;
html_url=https://github.com/DHowett;
followers_url=https://api.github.com/users/DHowett/followers; following_ur
l=https://api.github.com/users/DHowett/following{/other_user};
gists_url=https://api.github.com/users/DHowett/gists{/gist_id};
starred_url=https://api.github.com/users/DHowett/starred{/owner}{/repo};
subscriptions_url=https://api.github.com/users/DHowett/subscriptions;
organizations_url=https://api.github.com/users/DHowett/orgs;
repos_url=https://api.github.com/users/DHowett/repos;
events_url=https://api.github.com/users/DHowett/events{/privacy};
received_events_url=https://api.github.com/users/DHowett/received_events;
type=User; site_admin=False}
node_id : MDc6UmVsZWFzZTM0MjUwNjU4
tag_name : v1.4.3243.0
target_commitish : main
name : Windows Terminal v1.4.3243.0
draft : False
prerelease : False
created_at : 2020-11-20T21:34:28Z
published_at : 2020-11-20T21:43:33Z
assets : {@{url=https://api.github.com/repos/microsoft/terminal/releases/assets/285
75927; id=28575927; node_id=MDEyOlJlbGVhc2VBc3NldDI4NTc1OTI3;
name=Microsoft.WindowsTerminal_1.4.3243.0_8wekyb3d8bbwe.msixbundle;
label=; uploader=; content_type=application/octet-stream; state=uploaded;
size=22834909; download_count=28268; created_at=2020-11-20T21:43:26Z;
updated_at=2020-11-20T21:43:28Z; browser_download_url=https://github.com/m
icrosoft/terminal/releases/download/v1.4.3243.0/Microsoft.WindowsTerminal_
1.4.3243.0_8wekyb3d8bbwe.msixbundle}, @{url=https://api.github.com/repos/m
icrosoft/terminal/releases/assets/28575931; id=28575931;
node_id=MDEyOlJlbGVhc2VBc3NldDI4NTc1OTMx; name=Microsoft.WindowsTerminal_1
.4.3243.0_8wekyb3d8bbwe.msixbundle_Windows10_PreinstallKit.zip; label=;
uploader=; content_type=application/zip; state=uploaded; size=22311138;
download_count=5063; created_at=2020-11-20T21:43:31Z;
updated_at=2020-11-20T21:43:32Z; browser_download_url=https://github.com/m
icrosoft/terminal/releases/download/v1.4.3243.0/Microsoft.WindowsTerminal_
1.4.3243.0_8wekyb3d8bbwe.msixbundle_Windows10_PreinstallKit.zip}}
tarball_url : https://api.github.com/repos/microsoft/terminal/tarball/v1.4.3243.0
zipball_url : https://api.github.com/repos/microsoft/terminal/zipball/v1.4.3243.0
body : This is a quick servicing release to address a couple glaring issues in
the 1.4 stable release.

A [preinstallation](https://docs.microsoft.com/en-us/windows/msix/desktop/
deploy-preinstalled-apps) kit is available for system integrators and
OEMs interested in prepackaging Windows Terminal with a Windows image.
More information is available in the [DISM documentation on preinstallatio
n](https://docs.microsoft.com/windows-hardware/manufacture/desktop/preinst
all-apps-using-dism). Users who do not intend to preinstall Windows
Terminal should continue using the _msixbundle_ distribution.

Bugs fixed in this release:

* We reverted the tab switcher to _off by default_, because we changed
your defaults on you so that tab switching was both enabled and _in
most-recently-used order_. I'm sorry about that. (#8325)
* To turn the switcher back on, in MRU order, add the global setting
`"useTabSwitcher": true`.
* We'd previously said the default value for `backgroundImageStretch` was
`uniformToFill`, but it was actually `fill`. We've updated the code to
make it `uniformToFill`. (#8280)
* The tab switcher used to occasionally eat custom key bindings and
break, but @Don-Vito came through and helped it not do that. Thanks!
(#8250)

从这些丰富的信息中,您可以选择需要了解的详细信息,即各种格式的最新下载位置:

1
2
3
4
5
6
7
8
$url = 'https://api.github.com/repos/microsoft/terminal/releases/latest'
$info = Invoke-RestMethod -UseBasicParsing -Uri $url

[PSCustomObject]@{
TAR = $info.tarball_url
ZIP = $info.zipball_url
AppX = $info.Assets.Browser_Download_url[0]
} | Format-List

结果如下:

TAR  : https://api.github.com/repos/microsoft/terminal/tarball/v1.4.3243.0
ZIP  : https://api.github.com/repos/microsoft/terminal/zipball/v1.4.3243.0
AppX : https://github.com/microsoft/terminal/releases/download/v1.4.3243.0/Microsoft.WindowsT
       erminal_1.4.3243.0_8wekyb3d8bbwe.msixbundle
评论

PowerShell 技能连载 - 识别当前时区

显然,您可以这样向您的计算机查询当前时区:

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


Id : W. Europe Standard Time
DisplayName : (UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
StandardName : W. Europe Standard Time
DaylightName : W. Europe Daylight Time
BaseUtcOffset : 01:00:00
SupportsDaylightSavingTime : True

但是,此信息是否正确取决于您的实际配置。当您将笔记本电脑带到其他地方时,不一定会更新您的时区。

找出当前时区的另一种方法是调用公共 Web 服务。根据您当前的互联网连接,它会根据您当前所在的位置返回时区:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
PS> Invoke-RestMethod -Uri 'http://worldtimeapi.org/api/ip'


abbreviation : CET
client_ip : 84.183.236.178
datetime : 2021-01-04T13:31:57.398092+01:00
day_of_week : 1
day_of_year : 4
dst : False
dst_from :
dst_offset : 0
dst_until :
raw_offset : 3600
timezone : Europe/Berlin
unixtime : 1609763517
utc_datetime : 2021-01-04T12:31:57.398092+00:00
utc_offset : +01:00
week_number : 1
评论

PowerShell 技能连载 - 识别位置和公共 IP

下面的示例返回您的公共 IP 地址和位置:

1
2
3
4
5
6
7
8
9
10
11
12
13
PS> Invoke-RestMethod -Uri 'ipinfo.io/json'


ip : 84.183.236.178
hostname : p54b7ecb2.dip0.t-ipconnect.de
city : Hannover
region : Lower Saxony
country : DE
loc : 52.3705,9.7332
org : AS3320 Deutsche Telekom AG
postal : 30159
timezone : Europe/Berlin
readme : https://ipinfo.io/missingauth
评论

PowerShell 技能连载 - 检测未知的网络监听器

通常,当您检查网络连接时,您只能看到远程访问者使用的IP地址。IP 地址通常没有通过 DNS 解析,因此您实际上并不知道谁连接了您的计算机。

如果您想找出谁拥有未知 IP 地址,可以使用免费的 RESTful 网络服务。此行代码将显示指定 IP 地址的所有权:

1
2
3
4
5
6
7
8
9
10
11
12
PS> Invoke-RestMethod -Uri 'http://ipinfo.io/51.107.59.180/json'


ip : 51.107.59.180
city : Zürich
region : Zurich
country : CH
loc : 47.3667,8.5500
org : AS8075 Microsoft Corporation
postal : 8001
timezone : Europe/Zurich
readme : https://ipinfo.io/missingauth

将此命令与其他命令结合使用,可以找出与您的计算机进行通信的人员。例如,Get-NetTcpConnection 列出了您的网络连接,现在您可以查找谁是您所连接的 IP 地址背后的所有者。

在下面的示例中,Get-NetTcpConnection 返回所有当前活动的 HTTPS 连接(端口443)。远程 IP 被自动解析,因此您可以知道哪个软件正在保持连接,以及该软件正在与谁通信:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$Process = @{
Name='Process'
Expression={
# return process path
(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).Path

}
}

$IpOwner = @{
Name='RemoteAuthority'
Expression={
$ip = $_.RemoteAddress
$info = Invoke-RestMethod -Uri "http://ipinfo.io/$ip/json"
'{0} ({1})' -f $info.Org, $info.City
}
}

# get all connections to port 443 (HTTPS)
Get-NetTCPConnection -RemotePort 443 -State Established |
# where there is a remote address
Where-Object RemoteAddress |
# and resolve IP and Process ID
Select-Object -Property $IPOwner, RemoteAddress, OwningProcess, $Process

下面是一个实际示例:让我们转储本地管理员组。您可以按名称或不区分文化的 SID 来访问组:

RemoteAuthority                               RemoteAddress  OwningProcess Process
---------------                               -------------  ------------- -------
AS8075 Microsoft Corporation (Amsterdam)      52.114.74.221          14204 C:\Users\tobia\AppData\Local\Microsoft\Teams\current\Teams.exe
AS8075 Microsoft Corporation (Hampden Sydney) 52.114.133.169         13736 C:\Users\tobia\AppData\Local\Microsoft\Teams\current\Teams.exe
AS36459 GitHub, Inc. (Ashburn)                140.82.113.26          21588 C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
AS8068 Microsoft Corporation (Redmond)        13.107.42.12            9432 C:\Program Files (x86)\Microsoft Office\root\Office16\WINWORD.EXE
AS8075 Microsoft Corporation (Zürich)         51.107.59.180          14484 C:\Program Files\PowerShell\7\pwsh.exe
AS8068 Microsoft Corporation (Redmond)        13.107.42.12            9432 C:\Program Files (x86)\Microsoft Office\root\Office16\WINWORD.EXE
AS8075 Microsoft Corporation (San Antonio)    52.113.206.137         13736 C:\Users\tobia\AppData\Local\Microsoft\Teams\current\Teams.exe
AS8075 Microsoft Corporation (Paris)          51.103.5.186           12752 C:\Users\tobia\AppData\Local\Microsoft\OneDrive\OneDrive.exe

有趣吧?

评论

PowerShell 技能连载 - 更好的 NetStat(第 4 部分)

在上一个技巧中,我们介绍了 Get-NetTCPConnection cmdlet,它是 Windows 系统上 netstat.exe 网络实用程序的更好替代方案,但是此命令仅限于 Windows,并且需要大量其他代码才能将原始信息转化为有用的信息。解析的主机名和进程名。

netstat.exe 的最兼容替代方案是基于 .NET Core 的解决方案,无论 PowerShell 在哪里运行,它都可以跨平台使用。

只需自己获取开源的 GetNetStat 模块 (https://github.com/TobiasPSP/GetNetStat),它使用 .NET Core 代码来获取连接信息:

1
PS> Install-Module -Name GetNetStat -Scope CurrentUser

安装模块后,将有一个名为 Get-NetStat 的新命令。现在,列出打开的连接非常简单,现在您可以在 Windows PowerShell 和 PowerShell 7 中通过并行处理来解析主机名和进程名。

这个简单的命令列出了到 HTTPS(端口 443)的所有打开的连接,并解析主机名:

1
2
3
4
5
6
7
8
9
10
11
12
PS> Get-NetStat -RemotePort 443 -State Established -Resolve | Select-Object -Property RemoteIp, Pid, PidName

RemoteIp PID PIDName
-------- --- -------
1drv.ms 9432 WINWORD
lb-140-82-113-26-iad.github.com 21588 chrome
1drv.ms 9432 WINWORD
1drv.ms 9432 WINWORD
51.103.5.186 5464 svchost
51.103.5.186 12752 OneDrive
52.113.206.137 13736 Teams
51.107.59.180 14484 pwsh
评论

PowerShell 技能连载 - 更好的 NetStat(第 3 部分)

在上一个技巧中,我们介绍了 Get-NetTCPConnection cmdlet,它是 Windows 系统上网络实用程序 netstat.exe 的更好替代方法,并且通过一些技巧,您甚至可以解析 IP 地址和进程 ID。但是,这会大大降低命令的速度,因为 DNS 查找可能会花费一些时间,尤其是在网络超时的情况下。

让我们研究一下新的 PowerShell 7 并行处理功能如何加快处理速度。

以下是具有传统顺序处理的原始代码,该代码转储所有连接到端口 443 并解析主机名和进程(缓慢):

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
$Process = @{
Name='Process'
Expression={
# return process path
(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).Path

}
}

$HostName = @{
Name='Host'
Expression={
$remoteHost = $_.RemoteAddress
try {
# try to resolve IP address
[Net.Dns]::GetHostEntry($remoteHost).HostName
} catch {
# if that fails, return IP anyway
$remoteHost
}
}
}

# get all connections to port 443 (HTTPS)
Get-NetTCPConnection -RemotePort 443 -State Established |
# where there is a remote address
Where-Object RemoteAddress |
# and resolve IP and Process ID
Select-Object -Property $HostName, OwningProcess, $Process

这是一种利用 PowerShell 7 中新的“并行循环”功能的方法(快速):

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
# get all connections to port 443 (HTTPS)
Get-NetTCPConnection -RemotePort 443 -State Established |
# where there is a remote address
Where-Object RemoteAddress |
# start parallel processing here
# create a loop that runs with 80 consecutive threads
ForEach-Object -ThrottleLimit 80 -Parallel {
# $_ now represents one of the results emitted
# by Get-NetTCPConnection
$remoteHost = $_.RemoteAddress
# DNS resolution occurs now in separate threads
# at the same time
$hostname = try {
# try to resolve IP address
[Net.Dns]::GetHostEntry($remoteHost).HostName
} catch {
# if that fails, return IP anyway
$remoteHost
}
# compose the calculated information into one object
[PSCustomObject]@{
HostName = $hostname
OwningProcess = $_.OwningProcess
Process = (Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).Path
}
}

如您所见,第二种方法比以前快得多,并且是 PowerShell 7 中新的“并行循环”的好用例。

但是,不利的一面是,该代码现在的兼容性更低,只能在 Windows 系统上运行,并且只能在 PowerShell 7 中运行。在本系列的最后一部分中,我们将展示一个更简单的解决方案,该解决方案可以在所有版本的 PowerShell 上运行。

评论