PowerShell 技能连载 - 为文件夹快速打开 PowerShell

在 Windows 资源管理器中导航到文件夹时,您可以轻松打开传统的 cmd 或 PowerShell 控制台,并将当前文件夹设置为当前路径。

只需单击 Windows 资源管理器窗口中的地址栏然后输入 cmdpowershellpwsh,然后按 ENTER 键。

cmd 命令将打开经典命令行,powershell 命令将打开 Windows PowerShell 控制台,pwsh 命令将打开 PowerShell 7 控制台(如果已安装)。

仅当存在具有命令名称的文件夹时,此技巧才会失败。如果您打开 Documents 文件夹,单击地址栏,然后输入 “powershell”,那么只有在任何地方都没有名为 “PowerShell” 的子文件夹时,按下 ENTER 键才会打开一个 PowerShell 控制台。因为如果有,资源管理器只会打开此文件夹。

要解决此问题,只需将 “.exe” 添加到在地址栏中输入的命令中。”powershell.exe” 始终打开 Windows PowerShell 控制台,并将当前资源管理器的文件夹设置为默认路径。

PowerShell 技能连载 - 在 Windows 中用 PowerShell 来管理文件共享(第 2 部分)

在上一个技能中,我们介绍了 Windows 附带的 “SmbShare” PowerShell 模块,使您能够管理文件共享。我们学习了代表您在网络上共享的本地文件夹的 “SmbShare” 名词。今天我们来看看 “SbmMapping” 这个名词。

“SmbMapping” 名词从另一端查看共享:它表示您映射为本地驱动器的远程共享。Get-SmbMapping 列出您已映射的所有网络驱动器:

1
2
3
4
5
6
PS> Get-SmbMapping

Status Local Path Remote Path
------ ---------- -----------
Disconnected Z: \\127.0.0.1\c$
OK Y: \\storage3\scanning

New-SmbMapping“ 添加更多网络驱动器并将驱动器号映射到远程共享文件夹。这是一个映射网络驱动器并以纯文本形式提交登录凭据的示例:

1
2
3
4
5
PS> New-SmbMapping -LocalPath y: -RemotePath \\storage3\scanning -UserName Freddy -Password topSecret123

Status Local Path Remote Path
------ ---------- -----------
OK y: \\storage3\scanning

与往常一样,查看 cmdlet 文档可以更好地了解整个工作原理:

1
PS> Get-Help -Name New-SmbMapping -Online

这将在您的默认浏览器中打开一个文档页面,您可以检查可用参数并查看其他示例。

例如,您会发现 -Persistent 开关参数。它确定网络驱动器是永久可用且永久可用,还是仅用于当前会话。-SaveCredentials 将缓存输入的登录凭据,以便下次访问远程共享时不再需要密码。

PowerShell 技能连载 - 在 Windows 中用 PowerShell 来管理文件共享(第 1 部分)

Windows 附带一个名为 “SMBShare” 的模块,其中包含 42 个用于管理网络共享的 cmdlet。此模块适用于 Windows PowerShell 和 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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
PS> Get-Command -Module SMBShare

CommandType Name Version Source
----------- ---- ------- ------
Function Block-SmbShareAccess 2.0.0.0 SMBShare
Function Close-SmbOpenFile 2.0.0.0 SMBShare
Function Close-SmbSession 2.0.0.0 SMBShare
Function Disable-SmbDelegation 2.0.0.0 SMBShare
Function Enable-SmbDelegation 2.0.0.0 SMBShare
Function Get-SmbBandwidthLimit 2.0.0.0 SMBShare
Function Get-SmbClientConfiguration 2.0.0.0 SMBShare
Function Get-SmbClientNetworkInterface 2.0.0.0 SMBShare
Function Get-SmbConnection 2.0.0.0 SMBShare
Function Get-SmbDelegation 2.0.0.0 SMBShare
Function Get-SmbGlobalMapping 2.0.0.0 SMBShare
Function Get-SmbMapping 2.0.0.0 SMBShare
Function Get-SmbMultichannelConnection 2.0.0.0 SMBShare
Function Get-SmbMultichannelConstraint 2.0.0.0 SMBShare
Function Get-SmbOpenFile 2.0.0.0 SMBShare
Function Get-SmbServerCertificateMapping 2.0.0.0 SMBShare
Function Get-SmbServerConfiguration 2.0.0.0 SMBShare
Function Get-SmbServerNetworkInterface 2.0.0.0 SMBShare
Function Get-SmbSession 2.0.0.0 SMBShare
Function Get-SmbShare 2.0.0.0 SMBShare
Function Get-SmbShareAccess 2.0.0.0 SMBShare
Function Grant-SmbShareAccess 2.0.0.0 SMBShare
Function New-SmbGlobalMapping 2.0.0.0 SMBShare
Function New-SmbMapping 2.0.0.0 SMBShare
Function New-SmbMultichannelConstraint 2.0.0.0 SMBShare
Function New-SmbServerCertificateMapping 2.0.0.0 SMBShare
Function New-SmbShare 2.0.0.0 SMBShare
Function Remove-SmbBandwidthLimit 2.0.0.0 SMBShare
Function Remove-SmbComponent 2.0.0.0 SMBShare
Function Remove-SmbGlobalMapping 2.0.0.0 SMBShare
Function Remove-SmbMapping 2.0.0.0 SMBShare
Function Remove-SmbMultichannelConstraint 2.0.0.0 SMBShare
Function Remove-SmbServerCertificateMapping 2.0.0.0 SMBShare
Function Remove-SmbShare 2.0.0.0 SMBShare
Function Revoke-SmbShareAccess 2.0.0.0 SMBShare
Function Set-SmbBandwidthLimit 2.0.0.0 SMBShare
Function Set-SmbClientConfiguration 2.0.0.0 SMBShare
Function Set-SmbPathAcl 2.0.0.0 SMBShare
Function Set-SmbServerConfiguration 2.0.0.0 SMBShare
Function Set-SmbShare 2.0.0.0 SMBShare
Function Unblock-SmbShareAccess 2.0.0.0 SMBShare
Function Update-SmbMultichannelConnection 2.0.0.0 SMBShare

要开始学习使用这些 cmdlet,请从使用动词 “Get” 的那些开始:它们读取信息并且不会意外更改系统设置。

例如,Get-SmbShare 列出了您机器上所有可用的网络共享:

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

Name ScopeName Path Description
---- --------- ---- -----------
ADMIN$ * C:\WINDOWS Remoteadmi...
C$ * C:\ Standardfr...
HP Universal Printing PCL 6 * S/W Laser HP,LocalsplOnly S/W Laser HP
IPC$ * Remote-IPC
OKI PCL6 Class Driver 2 * OKI PCL6 Class Driver 2,LocalsplOnly OKI PCL6 C...
print$ * C:\Windows\system32\spool\drivers Printerdr...

要了解如何添加、配置或删除 SmbShares,请尝试查看带有名词 “smbshare” 的 cmdlet:

1
2
3
4
5
6
7
8
PS> Get-Command -Module SMBShare -Noun SmbShare

CommandType Name Version Source
----------- ---- ------- ------
Function Get-SmbShare 2.0.0.0 SMBShare
Function New-SmbShare 2.0.0.0 SMBShare
Function Remove-SmbShare 2.0.0.0 SMBShare
Function Set-SmbShare 2.0.0.0 SMBShare

New-SmbShare 允许您添加新的基本网络共享。在继续运行更改系统的命令之前,最好阅读 cmdlet 文档并查看包含的示例:

1
PS> Get-Help -Name New-SmbShare -Online

这将在您的默认浏览器中打开文档页面。该文档解释了可用的参数,并提供了如下示例:

1
PS> New-SmbShare -Name VMSFiles -Path C:\ClusterStorage\Volume1\VMFiles -FullAccess Contoso\Administrator, Contoso\Contoso-HV1$

它说明了创建新文件共享并使用访问权限保护它是多么简单。在运行命令之前,您必须调整示例的参数,并且至少更新您要共享的本地文件夹路径,以及应该具有完全访问权限的帐户名称。

PowerShell 技能连载 - 自定义基于控制台的对话框

使用第三方对话框并不总是一个好的选择。复用内置的 PowerShell 对话框会更有意思。这是一个名为 Show-ConsoleDialog 的函数,您可以用各种选项灵活地构造这样的对话框。

该对话框在纯控制台环境(如 PowerShell 7 或 VSCode)和 PowerShell ISE(作为自定义对话框弹出)中同样显示良好。

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
function Show-ConsoleDialog
{
param
(
[Parameter(Mandatory)]
[string]
$Message,

[string]
$Title = 'PowerShell',

# do not use choices with duplicate first letter
# submit any number of choices you want to offer
[string[]]
$Choice = ('Yes', 'No')



)


# turn choices into ChoiceDescription objects
$choices = foreach ($_ in $choice)
{
[System.Management.Automation.Host.ChoiceDescription]::new("&$_", $_)
}

# translate the user choice into the name of the chosen choice
$choices[$host.ui.PromptForChoice($title, $message, $choices, 1)].Label.Substring(1)
}

你可以像这样使用它:

1
2
3
4
5
6
7
8
9
10
$result = Show-ConsoleDialog -Message 'Restarting Server?' -Title 'Will restart server for maintenance' -Choice 'Yes','No','Later','Never','Always'

switch ($result)
{
'Yes' { 'restarting' }
'No' { 'doing nothing' }
'Later' { 'ok, later' }
'Never' { 'will not ask again' }
'Always' { 'restarting without notice now and ever' }
}

返回值为用户选择的名称。例如,使用 switch 语句来响应用户的选择。

另请注意,每个选项的第一个字母会变成键盘快捷键,因此不要使用具有重复首字母的选项。

PowerShell 技能连载 - 通过 PowerShell 休眠或待机

在上一个技能中,我们说明了虽然很难直接访问 Windows 电源管理 API,但还有其他 API 可以为您做到这一点。这段代码可让您将 Windows 系统关闭到所需的电源管理状态,即您可以将其休眠并使其进入无能耗状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# use the built-in pwmgmt support in Windows Forms
Add-Type -AssemblyName System.Windows.Forms

# define the power status you want to enable
$PowerState = [System.Windows.Forms.PowerState]::Hibernate

# allow or refuse force to be applied
$Force = $false

# turn off wake off capabilities as well
$DisableWake = $false

# apply the setting:
[System.Windows.Forms.Application]::SetSuspendState($PowerState, $Force, $DisableWake)

PowerShell 技能连载 - 检测电源状态

虽然很难直接访问 Windows 电源管理 API,但还有其他 API 可以实现相同需求。以下代码返回您机器的当前电源状态。如果您使用的是笔记本电脑并且没有交流电源,它可以告诉您剩余电池电量:

1
2
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.SystemInformation]::PowerStatus

结果类似这样:

PowerLineStatus      : Offline
BatteryChargeStatus  : 0
BatteryFullLifetime  : -1
BatteryLifePercent   : 0,45
BatteryLifeRemaining : 13498

PowerShell 技能连载 - 检测计划外的关机

如果 Windows 崩溃或意外停止,当下次重启时,它会产生一条 ID 为 41 的内核错误日志。如果您想检查回顾您的 Windows 是否正常关闭,请尝试以下代码:

1
2
3
Get-EventLog -Logname System -Source "Microsoft-Windows-Kernel-Power" |
Where-Object EventID -eq 41 |
Select-Object Index,TimeWritten,Source,EventID

一种更现代且与 PowerShell 7 兼容的方式是使用 Get-WinEvent,而不是使用过滤器哈希表:

1
2
3
4
5
Get-WinEvent -FilterHashtable @{
LogName = 'System'
ProviderName = 'Microsoft-Windows-Kernel-Power'
Id = 41
}

PowerShell 技能连载 - 奇怪的 Cmdlet:New-TemporaryFile

这是一个 PowerShell(和 Windows PowerShell)中比较隐藏的 cmdlet:New-TemporaryFile。看到这样一个相对无用的 cmdlet 成为 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
# load module that defines the function:
PS C:\> New-TemporaryFile -WhatIf
What if: Performing the operation "New-TemporaryFile" on target "C:\Users\tobia\AppData\Local\Temp".

# dump function source code:
PS C:\> ${function:New-TemporaryFile}

[CmdletBinding(
HelpURI='https://go.microsoft.com/fwlink/?LinkId=526726',
SupportsShouldProcess=$true)]
[OutputType([System.IO.FileInfo])]
Param()

Begin
{
try
{
if($PSCmdlet.ShouldProcess($env:TEMP))
{
$tempFilePath = [System.IO.Path]::GetTempFileName()
}
}
catch
{
$errorRecord = [System.Management.Automation.ErrorRecord]::new($_.Exception,"NewTemporaryFileWriteError", "WriteError", $env:TEMP)
Write-Error -ErrorRecord $errorRecord
return
}

if($tempFilePath)
{
Get-Item $tempFilePath
}
}

它的核心是这样的:

1
2
PS> [System.IO.Path]::GetTempFileName()
C:\Users\tobia\AppData\Local\Temp\tmp671.tmp
方法具有误导性,因为它实际上在您每次调用它时都会创建一个新的临时文件。`New-TemporaryFile` 返回的是临时文件对象,而不是字符串路径,这更好地说明了上面的问题。它的本质上是这样的:
1
2
3
4
5
6
7
8
9
10
11

```powershell
PS C:\> Get-Item ([System.IO.Path]::GetTempFileName())


Directory: C:\Users\tobia\AppData\Local\Temp


Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 26.01.2022 12:48 0 tmpC6DF.tmp

PowerShell 技能连载 - 本地化日期和时间标签(第 2 部分)

在上一个技能中,我们解释了如何查看所有受支持的 Windows 文化并让 Windows 翻译工作日名称。让我们玩得更开心一些,翻译月份名称。

这是一种特别简单的方法,可以确认您想要使用的文化的简称:

1
2
3
4
[System.Globalization.CultureInfo]::GetCultures('AllCultures') |
Where-Object Name |
Select-Object -Property Name, DisplayName |
Out-GridView -Title 'Select Culture' -OutputMode Single

这将打开一个包含所有支持的文化的网格视图窗口。使用位于其顶部的空文本框来过滤文化,然后选择一个并单击右下角的确定。您需要的是要使用的文化的简称。例如,要使用俄罗斯文化,简称为 “ru”。

现在,在以下调用中替换选定的文化名称:

1
2
3
4
5
6
7
8
9
10
11
12
13
PS> [System.Globalization.CultureInfo]::GetCultureInfo( 'ru' ).DateTimeFormat.MonthNames
Январь
Февраль
Март
Апрель
Май
Июнь
Июль
Август
Сентябрь
Октябрь
Ноябрь
Декабрь

同样,您可以调整我们之前技巧中的代码来创建两种语言的翻译表:

1
2
3
4
5
6
7
8
9
10
11
12
$english = [System.Globalization.CultureInfo]::GetCultureInfo( 'en' ).DateTimeFormat.MonthNames
$russian = [System.Globalization.CultureInfo]::GetCultureInfo( 'ru' ).DateTimeFormat.MonthNames

for($x=0; $x-lt 12; $x++)
{

[PSCustomObject]@{
Id = $x+1
English = $english[$x]
Russian = $russian[$x]
}
}

结果类似这样:

Id English   Russian
-- -------   -------
 1 January   Январь
 2 February  Февраль
 3 March     Март
 4 April     Апрель
 5 May       Май
 6 June      Июнь
 7 July      Июль
 8 August    Август
 9 September Сентябрь
10 October   Октябрь
11 November  Ноябрь
12 December  Декабрь

PowerShell 技能连载 - 本地化日期和时间标签(第 1 部分)

Windows 内置了对各种文化的支持。以下是支持的文化列表及其简称:

1
2
3
4
5
6
7
8
9
10
11
12
PS> [System.Globalization.CultureInfo]::GetCultures('AllCultures') | Select-Object -Property Name, DisplayName

Name DisplayName
---- -----------
aa Afar
aa-DJ Afar (Djibouti)
aa-ER Afar (Eritrea)
aa-ET Afar (Ethiopia)
af Afrikaans
af-NA Afrikaans (Namibia)
af-ZA Afrikaans (South Africa)
...

它还带有完全翻译的日期和时间组件表达。如果您想知道 Kikuyu(肯尼亚)中使用的工作日名称,请查找适当的文化名称( “ki”),然后尝试以下操作:

1
2
3
4
5
6
7
8
PS> [System.Globalization.CultureInfo]::GetCultureInfo( 'ki' ).DateTimeFormat.DayNames
Kiumia
Njumatatu
Njumaine
Njumatana
Aramithi
Njumaa
Njumamothi

你甚至可以为多种语言创建一个“翻译表”,因为你在 DayNames 中看到的是一个带有数字索引的数组:

1
2
PS> [System.Globalization.CultureInfo]::GetCultureInfo( 'ki' ).DateTimeFormat.DayNames[0]
Kiumia

这是一个显示英文和中文日期名称的翻译表:

1
2
3
4
5
6
7
8
9
10
11
$english = [System.Globalization.CultureInfo]::GetCultureInfo( 'en' ).DateTimeFormat.DayNames
$chinese = [System.Globalization.CultureInfo]::GetCultureInfo( 'zh' ).DateTimeFormat.DayNames

for($x=0; $x-lt7; $x++)
{

[PSCustomObject]@{
English = $english[$x]
Chinese = $chinese[$x]
}
}

结果如下所示:

English   Chinese
-------   -------
Sunday    星期日
Monday    星期一
Tuesday   星期二
Wednesday 星期三
Thursday  星期四
Friday    星期五
Saturday  星期六