PowerShell 技能连载 - 使用在线帮助(第 1 部分)

PowerShell 支持本地帮助文件和联机资源。请看区别:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# outputs help in same console window
# level of detail depends on whether local help was
# downloaded using Update-Help
PS C:\> help -Name Get-Process

NAME
Get-Process

SYNOPSIS
Gets the processes that are running on the local computer or a remote computer.


SYNTAX
Get-Process [[-Name] <String[]>] [-ComputerName <String[]>] [-FileVersionInfo] [-Module] []
...

# opens help in separate browser window
PS> help -Name Get-Process -Online

默认情况下,”help“(Get-Help 的别名)将帮助信息输出到 PowerShell 的输出窗口中。指定 -Online 开关参数时,浏览器会在单独的窗口中显示帮助文件。在线帮助文​​档采用了较好的格式,并且可以通过“复制”按钮轻松地复制和粘贴示例代码。并且由于联机文档是直接从 Microsoft 加载的,因此它们始终是最新的,因此无需通过 Update-Help 下载帮助。

这就是为什么许多用户喜欢在线帮助资源而不是本地帮助的原因。

线上还有许多有用的“关于”主题。关于主题涵盖了 PowerShell 语言和引擎的各个方面。您会在此处找到所有有关主题的很好的分类:https://docs.microsoft.com/zh-cn/powershell/module/microsoft.powershell.core/about/about

PowerShell 技能连载 - 在没有管理员特权的情况下更新帮助

在 Windows PowerShell 中,由于设计缺陷,更新帮助曾经需要管理员权限:帮助必须存储在模块所在的位置。更新 Windows 文件夹中存储的 Microsoft 模块的帮助需要对 Windows 文件夹的写权限。这就是普通用户无法下载和使用本地 PowerShell 帮助的原因。

在 PowerShell 7 中,此设计缺陷已得到纠正,现在可以将帮助安全地存储在用户配置文件中。不再需要涉及 PowerShell 模块的安装文件夹。

在 PowerShell 7 中使用 -Verbose 参数运行 Update-Help 以查看更改:

1
2
3
4
5
6
7
8
9
10
11
PS> Update-Help -Verbose
VERBOSE: Resolving URI: "https://go.microsoft.com/fwlink/?LinkId=717973"
VERBOSE: Your connection has been redirected to the following URI:
"https://pshelpprod.blob.core.windows.net/cabinets/powershell-5.1/"
VERBOSE: Performing the operation "Update-Help" on target "Microsoft.PowerShell.LocalAccounts, Current Version: 5.2.0.0, Available Version: 5.2.0.0, UICulture: en-US".
VERBOSE: Microsoft.PowerShell.LocalAccounts: Updated C:\Users\USERNAME\Dokumente\PowerShell\Help\Microsoft.PowerShell.LocalAccounts\1.0.0.0\en-US\Microsoft.Powershell.LocalAccounts.dll-Help.xml. Culture en-US Version 5.2.0.0
VERBOSE: Resolving URI: "https://go.microsoft.com/fwlink/?linkid=2113632"
VERBOSE: Your connection has been redirected to the following URI: "https://pshelp.blob.core.windows.net/powershell/help/7.0/Microsoft.PowerShell.Management/"
VERBOSE: Performing the operation "Update-Help" on target "Microsoft.PowerShell.Management, Current Version: 7.0.1.0, Available Version: 7.0.1.0, UICulture: en-US".
VERBOSE: Microsoft.PowerShell.Management: Updated C:\Users\USERNAME\Dokumente\PowerShell\Help\en-US\Microsoft.PowerShell.Commands.Management.dll-Help.xml. Culture en-US Version 7.0.1.0
...

要使用下载的本地帮助文件,您可以在想了解的命令后添加 “-?“ 通用参数:

1
2
3
4
5
6
7
8
PS> Get-Process -?

NAME
Get-Process

SYNOPSIS
Gets the processes that are running on the local computer or a remote computer.
...

如果您之前未下载本地帮助文件,则 “-“ 参数仅显示有限的语法帮助。

PowerShell 技能连载 - PowerShell技能连载-检查配置文件脚本(第 2 部分)

在上一个脚本中,我们介绍了一一行代码,用于检查哪些配置文件脚本是存在的。但是,此解决方案仅只适用于单个宿主,因为每个宿主都使用自己的特定于宿主的配置文件路径。

这是一种更通用的方法:它列出了系统上存在的所有 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
# calculate the parent paths that can contain profile scripts
$Paths = @{
AllUser_WPS = $pshome
CurrentUser_WPS = Join-Path -Path ([Environment]::GetFolderPath('MyDocuments')) -ChildPath "WindowsPowerShell"
AllUser_PS = "$env:programfiles\PowerShell\*"
CurrentUser_PS = Join-Path -Path ([Environment]::GetFolderPath('MyDocuments')) -ChildPath "PowerShell"
}

# check all paths for PowerShell scripts ending on "profile.ps1"
$Paths.Keys | ForEach-Object {
$key = $_
$path = Join-Path -Path $paths[$key] -ChildPath '*profile.ps1'
Get-ChildItem -Path $Path |
ForEach-Object {
# create a custom object with all relevant details for any
# found profile script

# name of PowerShell host is the prefix of profile file name
if ($_.Name -like '*_*')
{
$hostname = $_.Name.Substring(0, $_.Name.Length-12)
}
else
{
$hostname = 'any'
}
[PSCustomObject]@{
# scope and PowerShell version is found in the
# name of the parent folder
Scope = $key.Split('_')[0]
PowerShell = $key.Split('_')[1]

Host = $hostname
Path = $_.FullName
}
}
}

结果报告了所有主机的现有 PowerShell 配置文件脚本,看起来可能与此类似:

Scope       PowerShell Host                    Path
-----       ---------- ----                    ----
CurrentUser WPS        Microsoft.PowerShellISE C:\Users\tobia\OneDrive\Dokumente\WindowsPowerShell\Microsoft.PowerShellISE_...
CurrentUser WPS        any                     C:\Users\tobia\OneDrive\Dokumente\WindowsPowerShell\profile.ps1
CurrentUser PS         Microsoft.VSCode        C:\Users\tobia\OneDrive\Dokumente\PowerShell\Microsoft.VSCode_profile.ps1

PowerShell 技能连载 - PowerShell技能连载-检查配置文件脚本(第 1 部分)

PowerShell 最多使用四个配置文件脚本。当它们存在时,PowerShell 在启动时会静默执行所有内容。

重要的是要知道存在哪个配置文件脚本(如果有),因为它们的内容会减慢 PowerShell 的启动时间,并且恶意代码可以使用它们来偷偷运行。

手动测试配置文件路径可能很麻烦。这是一行有趣的代码,可以为您完成工作:

1
$profile.PSObject.Properties.Name | Where-Object { $_ -ne 'Length' } | ForEach-Object { [PSCustomObject]@{Profile=$_; Present=Test-Path $profile.$_; Path=$profile.$_}}

结果看起来像这样:

Profile                Present Path
-------                ------- ----
AllUsersAllHosts         False C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1
AllUsersCurrentHost      False C:\Windows\System32\WindowsPowerShell\v1.0\Microsoft.PowerShellISE_profile.ps1
CurrentUserAllHosts      False C:\Users\tobia\OneDrive\Dokumente\WindowsPowerShell\profile.ps1
CurrentUserCurrentHost    True C:\Users\tobia\OneDrive\Dokumente\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1

PowerShell 技能连载 - 使用 Profile 脚本

配置文件脚本的工作方式类似于 PowerShell 中的自动启动脚本。它们不一定存在,但是如果存在,PowerShell 会在每次启动时静默执行其内容。最多有四个配置文件脚本,此行代码显示它们的路径:

1
2
3
4
5
6
7
PS> $profile | Select-Object -Property *

AllUsersAllHosts : C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1
AllUsersCurrentHost : C:\Windows\System32\WindowsPowerShell\v1.0\Microsoft.PowerShellISE_profile.ps1
CurrentUserAllHosts : C:\Users\tobia\OneDrive\Dokumente\WindowsPowerShell\profile.ps1
CurrentUserCurrentHost : C:\Users\tobia\OneDrive\Dokumente\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1
Length : 87

不必担心属性 “Length”:它是基于 $profile 是字符串这一事实的产物。PowerShell已在其中添加了四个属性,以返回受支持的配置文件的路径。

请注意,任何包含 “AllHosts” 的配置文件的路径对于所有 PowerShell 宿主都是相同的。您添加到其中的任何内容都可以在任何宿主中执行,包括 powershell.exe、PowerShell ISE、Visual Studio Code 或 PowerShell 7。包含 “CurrentHost” 的属性中的路径仅限于正在执行此行代码的宿主。

默认情况下,所有这些路径哪儿也不指向。要使用一个或多个,请确保创建了路径指向的文件。

PowerShell 技能连载 - 识别用户 Profile

使用 $envuserprofile$home 创建用户文件的路径时要小心。当使用了 OneDrive,文档文件夹可能已重定向到名为“ OneDrive”的子文件夹。这里有些例子:

1
2
3
4
5
6
7
8
9
10
PS> $env:USERPROFILE
C:\Users\tobia

PS> $HOME
C:\Users\tobia

PS> $profile
C:\Users\tobia\OneDrive\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1

PS>

如您所见,PowerShell 配置文件脚本并不直接位于用户配置文件内的 Documents 文件夹中。而是将其改为名为 “OneDrive” 的子文件夹。

要查找当前的 Documents 文件夹,请改用 GetFolderPath()

1
2
PS> [Environment]::GetFolderPath('MyDocuments')
C:\Users\tobia\OneDrive\Documents

您甚至可以使用它来确定 OneDrive 是否重定向了用户文件:

1
2
$redirected = [Environment]::GetFolderPath('MyDocuments') -like '*\OneDrive\*'
$redirected

当 OneDrive 重定向文件夹时,此命令返回 $true,否则返回 $false

PowerShell 技能连载 - 摆脱 Get-EventLog

Get-EventLog 命令可以轻松访问主要的 Windows 事件日志中的事件日志条目,但是它既不能访问许多应用程序级事件日志,也不能在PowerShell 7中使用。

如果计划在 PowerShell 7 中运行代码,则应该开始习惯其后继程序:Get-WinEvent。此cmdlet功能强大,并支持许多参数。这是一个类似于 Get-EventLog 的示例:

1
2
3
Get-WinEvent -FilterHashtable @{Logname = 'System';Level=2,3} -MaxEvents 10 |
Select-Object TimeCreated, LevelDisplayName, Id, ProviderName, Message |
Format-Table

您的查询以哈希表的形式提交,您可以看到如何指定日志名称和想要获取的事件数量。与 Get-EventLog 相比,您现在可以指定和检索任何日志,而不仅仅是少数经典日志。您可能需要运行 Show-EventLog 来打开事件日志查看器,并发现许多可用的应用程序级别的日志。

哈希表 “Level” 键定义您要查看的事件日志条目的类型。数字越低,条目越严重。“2” 代表错误,“3”代表警告。如您所见,您可以将级别组合为逗号分隔的列表。

结果看起来像这样:

TimeCreated         LevelDisplayName    Id ProviderName                     Message
-----------         ----------------    -- ------------                     -------
04.08.2020 13:03:42 Warning          10016 Microsoft-Windows-DistributedCOM The Anwendungsspezifisch permission settings do...
04.08.2020 13:03:20 Error                1 MTConfig                         An attempt to configure the input mode of a mul...
04.08.2020 13:03:19 Error                1 MTConfig                         An attempt to configure the input mode of a mul...
04.08.2020 12:58:18 Error                1 MTConfig                         An attempt to configure the input mode of a mul...
04.08.2020 11:53:38 Error            10010 Microsoft-Windows-DistributedCOM The server Microsoft.SkypeApp_15.61.100.0_x86__...
04.08.2020 11:23:48 Error            10010 Microsoft-Windows-DistributedCOM The server microsoft.windowscommunicationsapps_...
04.08.2020 11:23:41 Error            10010 Microsoft-Windows-DistributedCOM The server Microsoft.SkypeApp_15.61.100.0_x86__...
04.08.2020 11:23:37 Warning            701 Win32k                           Power Manager has not requested suppression of ...
04.08.2020 11:23:37 Warning            701 Win32k                           Power Manager has not requested suppression of ...
04.08.2020 11:23:37 Error            10317 Microsoft-Windows-NDIS           Miniport Microsoft Wi-Fi Direct Virtual Adapter...

PowerShell 技能连载 - 设置和清除信任的主机

PowerShell 远程处理在客户端(发出命令并在服务器上进行身份验证的计算机)上维护受信任的 IP 地址和/或计算机名称的列表。此列表对您很重要,因为它控制着您如何对远程计算机进行身份验证。

默认情况下,PowerShell 仅支持 Kerberos 身份验证,因为它最安全,并且可以同时对客户端和服务器进行身份验证。但是,它需要一个 Active Directory,并且不能与 IP 地址一起使用。

1
2
# execute PowerShell code remotely
Invoke-Command { Get-Service } -ComputerName storage2 -Credential AdminUser

在此示例中,AdminUser 必须是在 storage2 上具有适当权限才能访问的域帐户。

通过将 IP 地址和/或计算机名称添加到 TrustedHosts,您也可以使用 NTLM身份验证。这样,您可以使用本地帐户进行身份验证,并使用远程帐户访问独立系统,域外的系统以及通过IP地址指定的系统。

也允许使用通配符,因此当将 TrustedHosts 设置为 “*” 时,任何计算机都可以使用 NTLM 身份验证。但是,这并不太明智,因为现在黑客可以断开服务器并用另一台机器代替它来捕获密码,因为您不会注意到它不再是您要访问的机器。因此,仅对于您知道的位于“信任”的安全环境中的计算机,对 TrustedHosts 进行更改。

仅管理员和 WinRM 服务运行时才能访问 TrustedHosts 列表。启动提升的 PowerShell 环境,并确保 WinRM 服务正在运行:

1
PS> Start-Service -Name WinRM

要查看 TrustedHosts 的当前内容,请运行以下命令:

1
2
3
4
5
6
7
8
PS> Get-ChildItem -Path WSMan:\localhost\Client\TrustedHosts


WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Client

Type Name SourceOfValue Value
---- ---- ------------- -----
System.String TrustedHosts

默认情况下,列表为空。要重置其内容(即指定IP范围),请使用 Set-Item

1
PS> Set-Item -Path WSMan:\localhost\Client\TrustedHosts -Value 192.168.* -Force

要添加更多条目,请添加 -Concatenate 参数。这将添加一个不同的计算机名称:

1
PS> Set-Item -Path WSMan:\localhost\Client\TrustedHosts -Value storage2 -Concatenate -Force

现在尝试转储更改的内容。结果是一个逗号分隔的列表,支持通配符:

1
2
3
4
5
6
7
8
PS> Get-ChildItem -Path WSMan:\localhost\Client\TrustedHosts


WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Client

Type Name SourceOfValue Value
---- ---- ------------- -----
System.String TrustedHosts 192.168.*,storage2

要将 TrustedHosts 还原为默认值并将其清空,请使用 Clear-Item 命令:

1
PS> Clear-Item -Path WSMan:\localhost\Client\TrustedHosts -Force

PowerShell 技能连载 - 在 PowerShell ISE 中使用 PowerShell 7

Windows 内置的 PowerShell ISE 仅能与 Windows PowerShell 一起使用,并且停留在 PowerShell 5.1 版。通常,当您想使用编辑器编写 PowerShell 7 代码时,可以使用 Visual Studio Code 和 PowerShell 扩展。

尽管如此,您仍可以使 PowerShell ISE 兼容 PowerShell 7。然后,它为 PowerShell 7 提供了丰富的 IntelliSense,并包含 PowerShell 7 中引入的所有语言功能。

为此,您可以从 PowerShell ISE 中启动本地远程会话,并指定配置名称 “powershell.7”。

1
PS> Enter-PSSession -ComputerName localhost -ConfigurationName powershell.7

当然,这需要满足一些先决条件:

  • 您需要先安装 PowerShell 7,然后才能使用它。 Windows 7 并不附带 PowerShell 7。
  • 您需要在 PowerShell 7中启用远程处理。您可以在安装期间通过选中安装对话框中的相应框来执行此操作。或者,您从提升权限的 PowerShell 7 控制台运行此命令:Enable-PSRemoting -SkipNetworkProfileCheck -Force
  • 您可能需要在提升权限的 Windows PowerShell 中再次运行此行命令:Enable-PSRemoting -SkipNetworkProfileCheck -Force

现在您已经准备就绪,并使用上述参数运行 Enter-PSSession 时,您将远程连接到 PowerShell 7。

如果您当前的用户不是管理员,或者您使用电子邮件地址和 Microsoft 帐户登录,则需要创建一个具有管理员权限的本地用户帐户,并将其明确用于身份验证:

1
PS> Enter-PSSession -ComputerName localhost -ConfigurationName powershell.7 -Credential localAdminUser

PowerShell 技能连载 - 使用 $Is* 变量

在PowerShell 7 中,有一组新的变量都以 “Is” 开头。它们可帮助您了解脚本运行的环境:

1
2
3
4
5
6
7
PS> Get-Variable -Name is*
Name Value
---- -----
IsCoreCLR True
IsLinux False
IsMacOS False
IsWindows True

在 Windows 附带的 Windows PowerShell 中,这些变量尚不存在。这是可以理解的,因为 Windows PowerShell 是 Windows 的一部分,而且无论如何都不能跨平台兼容。

要在Windows(或任何其他受支持的平台)上运行PowerShell 7,请访问发布页面https://github.com/PowerShell/PowerShell/releases ,向下滚动到 “Assets” 标题,然后下载最适合您的安装软件包。

在 Windows PowerShell中,只需运行以下代码即可:

1
iex "& { $(irm https://aka.ms/install-powershell.ps1) } -UseMSI"

要启动 PowerShell 7,请运行 pwsh.exe