PowerShell 技能连载 - 使用编码标准

使用文本文件时,务必始终使用相同的文本编码进行读取和写入,否则特殊字符可能会损坏,或者文本文件可能变得不可读,这一点很重要。

在 PowerShell 7 中,除非您指定其他编码,否则所有 cmdlet 以及重定向操作符都将使用默认的 UTF8 文本编码。那挺好的。

在W indows PowerShell 中,不同的 cmdlet 使用不同的默认编码。所以,要为所有 cmdlet 和重定向操作符建立通用的默认默认编码,您应该为带有参数 -Encoding 的任何命令设置默认参数值。

将以下行放入您的配置文件脚本中:

1
$PSDefaultParameterValues.Add('*:Encoding', 'UTF8')

此外,在 Windows PowerShell 中,无论 cmdlet 是否具有参数 -Encoding,都指定一个唯一的值。当前推荐的编码为UTF8。

PowerShell 技能连载 - 修复 VSCode PowerShell 问题(第 2 部分)

如果在编辑 PowerShell 脚本时 VSCode 不会启动 PowerShell 引擎,而状态栏中的黄色消息“正在启动 PowerShell”不会消失,则可能的解决方法是使用全新独立的可移植 PowerShell 7 安装作为 VSCode 中的默认 PowerShell 引擎。

首先,运行以下这行代码以创建 Install-PowerShell cmdlet :

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

接下来,在本地文件夹中安装 PowerShell 7 的新副本,例如:

1
Install-PowerShell -Destination c:\portablePowerShell

安装完成后,请确保可以手动启动新的 PowerShell 实例:

1
c:\portablePowerShell\pwsh

现在,继续告诉 VSCode,您要在编辑 PowerShell 脚本时使用此新的 PowerShell 实例运行:在 VSCode 中,选择“文件/首选项/设置”,单击设置左栏中的“扩展”,然后单击子菜单中的“PowerShell 配置”。

接下来,搜索设置“PowerShell 默认版本”,然后输入任何名称,即“portable PowerShell 7”。在上面的“PowerShell Additional Exe Paths”部分中,单击链接“Edit in settings.json”。这将以 JSON 格式打开原始设置文件。

其中,新设置部分已经插入,需要像这样完成:

1
2
3
4
5
6
"powershell.powerShellAdditionalExePaths": [
        {
            "exePath": "c:\\portablePowerShell\\pwsh.exe",
            "versionName": "portable PowerShell 7"
        }
    ]

注意:所有标记和关键字均区分大小写,并且在路径中,反斜杠需要由另一个反斜杠转义。在 “exePath” 中,在下载的可移植 PowerShell 文件夹中指定 pwsh.exe 文件的路径。确保路径不仅指向文件夹,而且指向 pwsh.exe

在 “versionName” 中,使用之前在 “PowerShell Default Version” 中指定的相同标签名称。

保存 JSON 文件后,重新启动 VSCode。该编辑器现在使用您的 portable PowerShell 7,并且在许多情况下,这解决了 PowerShell 启动卡住的问题。

如果您想手动将其他 PowerShell 版本添加到 VSCode,则上面的方法也很有用。当您单击 VSCode 状态栏中的绿色 PowerShell 版本时,任何手动添加的 PowerShell 将出现在选择对话框中(除非已被使用,在这种情况下,该菜单将显示 PowerShell 类型和版本,而不是您的标签名称)。

PowerShell 技能连载 - 修复 VSCode PowerShell 问题(第 1 部分)

有时,VSCode 在尝试启动 PowerShell 引擎时停止,或者报告诸如 “Language Server Startup failed” 之类的错误。

如果您遇到后一种异常,则可能与企业中的安全设置有关。要解决此问题,请在 PowerShell 控制台中运行以下行(这是一长行代码):

1
Import-Module $HOME\.vscode\extensions\ms-vscode.powershell*\modules\PowerShellEditorServices\PowerShellEditorServices.psd1

如果您没有得到提示,那么这不是造成问题的原因。如果确实收到提示要求确认导入此模块的提示,则只需允许运行“来自不受信任的发布者的软件”。该确认仅需要一次,因此下次 VSCode 尝试使用此模块启动 PowerShell 引擎时,很可能会解决您的问题。

PowerShell 技能连载 - 查找 PowerShell 命令

Get-Command 可以帮助您查找给定任务的 PowerShell 命令,但是此 cmdlet 只能搜索命令名称和参数中的关键字。

可以从 PowerShell Gallery 中安装更复杂的搜索命令:

1
Install-Module -Name PSCommandDiscovery -Scope CurrentUser -Verbose

Find-PowerShellCommand 使用关键字并返回与此关键字相关的所有命令。它在命令名称,命令参数以及返回的对象属性中搜索关键字。如果找到的命令类型是已编译的应用程序,则该命令还将返回命令的类型(GUI 或基于控制台的命令)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
PS> Find-PowerShellCommand -Keyword user -CommandType Function,Cmdlet,Application

Command MatchType Member
------- --------- ------
Add-WinADUserGroups CommandName
Get-ComputerInfo Property [string] CsUserName (read/write)
Get-ComputerInfo Property [Nullable`1[[System.UInt32, Syst
Get-ComputerInfo Property [Nullable`1[[System.UInt32, Syst
Get-ComputerInfo Property [string] OsRegisteredUser (read/…
Get-ComputerInfo Property [Nullable`1[[Microsoft.PowerShel
Get-Credential Property [string] UserName (readonly)
Get-Culture Property [bool] UseUserOverride (readonly)
Get-LocalUser CommandName
Get-PnPAADUser CommandName
Get-PnPTeamsUser CommandName
Get-PnPUser CommandName
Get-PnPUserOneDriveQuota CommandName
Get-PnPUserProfileProperty CommandName
Get-Process Property [timespan] UserProcessorTime (re
Get-UICulture Property [bool] UseUserOverride (readonly)
DevModeRunAsUserConfig.msc Command .msc: DevModeRunAsUserConfig (Un
DsmUserTask.exe Command .exe: DsmUserTask (x64) [Gui] 10
quser.exe Command .exe: quser (x64) [Console] 10.0
(...)

MatchType“ 属性报告匹配的种类。可以根据命令名称,参数名称或返回对象的任何属性名称中的关键字匹配找到命令。

有关其他示例,源代码和所有参数的说明,请参见 https://github.com/TobiasPSP/PsCommandDiscovery

PowerShell 技能连载 - 修复 Install-Module (PowerShellGet)

使用 Install-Module ,您可以轻松地从 PowerShell Gallery (www.powershellgallery.com) 下载和安装其他 PowerShell 模块。但是,在 Windows 系统上,此命令可能会中断。许多 Windows 系统仍随附 1.x 版本,并且 PowerShell Gallery 已切换到 Internet 协议 TLS 1.2,较早的 Windows 版本不会自动支持该协议。

要解决 Install-Module 的问题,您应确保 PowerShell 可以使用 TLS 1.2 来访问 PowerShell Gallery:

1
2
3
[System.Net.ServicePointManager]::SecurityProtocol =
[System.Net.ServicePointManager]::SecurityProtocol -bor
[System.Net.SecurityProtocolType]::Tls12

接下来,您应该像这样手动重新安装 PowerShellGet 和 Packagemanagement 模块的当前版本(不需要管理员权限):

1
2
Install-Module -Name PowerShellGet -Scope CurrentUser -Force -AllowClobber
Install-Module -Name Packagemanagement -Scope CurrentUser -Force -AllowClobber

这应该能为大多数用户解决问题。

如果根本无法使用 Install-Module,则可以手动将 PowerShellGet 和 Packagemanagement 的模块文件夹从更新的 Windows 版本复制到另一个版本。运行以下行以查找可以在何处找到最新版本的 PowerShellGet:

1
Get-Module -Name powershellget -ListAvailable | Sort-Object -Property Version -Descending | Select-Object -First 1

最新版本是 2.2.5,并且您不应使用低于 2.x 的版本。如果您的 PowerShell 报告系统上同时存在版本 1.x 和 2.x,则一切正常。PowerShell始终会自动选择最新版本。

PowerShell 技能连载 - 跨平台的 Out-GridView

Out-GridView 是最常用的 cmdlet 之一,它会打开一个通用选择对话框。不幸的是,PowerShell 只能在 Windows 操作系统上显示图形元素,例如窗口。在 Linux 和 macOS 上,图形 cmdlet(例如 Out-GridView)不可用。

您可能想尝试使用新的基于文本的 Out-ConsoleGridView。此 cmdlet 仅适用于PowerShell 7(在Windows PowerShell中不起作用)。像这样安装它:

1
Install-Module -Name Microsoft.PowerShell.ConsoleGuiTools -Scope CurrentUser

安装完成后,在许多情况下,您现在可以轻松地将 Out-GridView 替换为 Out-ConsoleGridView,并享受类似于旧版 Norton Commander 的基于文本的选择对话框。这是旧版 Windows PowerShell 脚本,无法在 Linux 上使用:

1
2
3
4
5
6
Get-Process |
Where-Object MainWindowHandle |
Select-Object -Property Name, Id, Description |
Sort-Object -Property Name |
Out-GridView -Title 'Prozesse' -OutputMode Multiple |
Stop-Process -WhatIf

只需将 Out-GridView 替换为 Out-ConsoleGridView,便一切就绪。

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

在上一个技巧中,我们讨论了 “Chocolatey” 程序包管理器,如果您想为所有用户安装软件(需要管理员权限),该程序最有效。

另一个出色的软件包管理器是 “Scoop”,它针对没有管理员权限的普通用户。Scoop 严格为当前用户下载并安装软件,并且是便携式应用程序。

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

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

要安装此程序包管理器,请在 PowerShell中运行以下几行(无需管理员权限):

1
2
3
Invoke-RestMethod -UseBasicParsing -Uri 'https://get.scoop.sh' | Invoke-Expression
scoop install git
scoop bucket add extras

安装后,会生成一个名为 “Scoop” 的新命令。

现在,您可以安装可能需要的所有工具。以下几行安装 PowerShell 7、Windows Terminal、7Zip、Notepad ++ 和 Visual Studio Code 编辑器:

1
2
3
4
5
scoop install pwsh
scoop install windows-terminal
scoop install 7zip
scoop install notepadplusplus
scoop install vscode-portable

使用命令 “scoop search [phrase]“,您可以搜索其他可用的安装软件包。

Scoop 将所有软件作为便携式应用程序安装在其自己的文件夹中,您可以这样打开:

1
explorer $home\Scoop\Apps

某些安装包可能会向您的桌面和任务栏添加链接.但是通常您需要访问 scoop 安装文件夹,手动启动应用程序,然后将其固定到任务栏或开始菜单以方便访问。

重要说明:”Scoop” 下载并安装软件包,并尝试解决依赖关系。但是,”Windows Terminal” 之类的某些软件包可能有其他要求(例如Windows Build 1903 或更高版本),因此,如果软件在安装后无法启动,则可能需要检查其他要求。

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"