PowerShell 技能连载 - 打开 Windows 设置对话框(快速)(第 1 部分)

大多数对话框和 Windows 中的设置可以通过内部命令直接打开。Windows 10 的设置对话框可以用如下命令打开:

1
PS> Start-Process ms-settings:

要打开特定的设置页面,请添加其名称。例如,要快速打开“镜像显示”设置页面,请尝试如下代码:

1
PS> Start-Process ms-settings:quietmomentspresentation

以下是 Paolo Maffezzoli 整理的支持命令列表(谢谢):

Page Command (URI)
**Settings home page**
Settings home page ms-settings:
**System**
Display ms-settings:display
Night light settings ms-settings:nightlight
Advanced scaling settings ms-settings:display-advanced
Connect to a wireless display ms-settings-connectabledevices:devicediscovery
Graphics settings ms-settings:display-advancedgraphics
Display orientation ms-settings:screenrotation
Sound (build 17063+) ms-settings:sound
Manage sound devices ms-settings:sound-devices
App volume and device preferences ms-settings:apps-volume
Notifications & actions ms-settings:notifications
Focus assist (build 17074+) ms-settings:quiethours, OR ms-settings:quietmomentshome
During these hours ms-settings:quietmomentsscheduled
Duplicating my display (When I'm duplicating my display) ms-settings:quietmomentspresentation
Playing a game full screen (When I'm playing a game) ms-settings:quietmomentsgame
Power & sleep ms-settings:powersleep
Battery ms-settings:batterysaver
See which apps are affecting your battery life ms-settings:batterysaver-usagedetails
Battery Saver settings ms-settings:batterysaver-settings
Storage ms-settings:storagesense
Configure Storage Sense or run it now ms-settings:storagepolicies
Change where new content is saved ms-settings:savelocations
Tablet mode ms-settings:tabletmode
Multitasking ms-settings:multitasking
Projecting to this PC ms-settings:project
Shared experiences ms-settings:crossdevice
Clipboard ms-settings:clipboard
Remote Desktop ms-settings:remotedesktop
Device Encryption (where available) ms-settings:deviceencryption
About ms-settings:about
**Devices**
Bluetooth & other devices ms-settings:bluetooth, OR ms-settings:connecteddevices
Printers & scanners ms-settings:printers
Mouse ms-settings:mousetouchpad
Touchpad ms-settings:devices-touchpad
Typing ms-settings:typing
Hardware keyboard - Text suggestions ms-settings:devicestyping-hwkbtextsuggestions
Wheel (where available) ms-settings:wheel
Pen & Windows Ink ms-settings:pen
AutoPlay ms-settings:autoplay
USB ms-settings:usb
**Phone**
Phone ms-settings:mobile-devices
Add a phone ms-settings:mobile-devices-addphone
Your Phone (opens app) ms-settings:mobile-devices-addphone-direct
**Network & Internet**
Network & Internet ms-settings:network
Status ms-settings:network-status
Show available networks ms-availablenetworks:
Cellular & SIM ms-settings:network-cellular
Wi-Fi ms-settings:network-wifi
Show available networks ms-availablenetworks:
Manage known networks ms-settings:network-wifisettings
Wi-Fi Calling ms-settings:network-wificalling
Ethernet ms-settings:network-ethernet
Dial-up ms-settings:network-dialup
DirectAccess (where available) ms-settings:network-directaccess
VPN ms-settings:network-vpn
Airplane mode ms-settings:network-airplanemode, OR ms-settings:proximity
Mobile hotspot ms-settings:network-mobilehotspot
NFC ms-settings:nfctransactions
Data usage ms-settings:datausage
Proxy ms-settings:network-proxy
**Personalization**
Personalization ms-settings:personalization
Background ms-settings:personalization-background
Colors ms-settings:personalization-colors, OR ms-settings:colors
Lock screen ms-settings:lockscreen
Themes ms-settings:themes
Fonts (build 17083+) ms-settings:fonts
Start ms-settings:personalization-start
Choose which folders appear on Start ms-settings:personalization-start-places
Taskbar ms-settings:taskbar
**Apps**
Apps & features ms-settings:appsfeatures OR ms-settings:appsfeatures-app
Manage optional features ms-settings:optionalfeatures
Default apps ms-settings:defaultapps
Offline maps ms-settings:maps
Download maps ms-settings:maps-downloadmaps
Apps for websites ms-settings:appsforwebsites
Video playback (build 16215+) ms-settings:videoplayback
Startup (build 17017+) ms-settings:startupapps
**Accounts**
Your info ms-settings:yourinfo
Email & accounts ms-settings:emailandaccounts
Sign-in options ms-settings:signinoptions
Windows Hello face setup ms-settings:signinoptions-launchfaceenrollment
Windows Hello fingerprint setup ms-settings:signinoptions-launchfingerprintenrollment
Security Key setup ms-settings:signinoptions-launchsecuritykeyenrollment
Dynamic Lock ms-settings:signinoptions-dynamiclock
Access work or school ms-settings:workplace
Family & other people ms-settings:otherusers OR ms-settings:family-group
Set up a kiosk ms-settings:assignedaccess
Sync your settings ms-settings:sync
**Time & language**
Date & time ms-settings:dateandtime
Region ms-settings:regionformatting
Japan IME settings (where available) ms-settings:regionlanguage-jpnime
Pinyin IME settings (where available) ms-settings:regionlanguage-chsime-pinyin
Wubi IME settings (where available) ms-settings:regionlanguage-chsime-wubi
Korea IME settings (where available) ms-settings:regionlanguage-korime
Language ms-settings:regionlanguage OR ms-settings:regionlanguage-languageoptions
Windows Display language ms-settings:regionlanguage-setdisplaylanguage
Add Display language ms-settings:regionlanguage-adddisplaylanguage
Keyboard (removed in build 17083+) ms-settings:keyboard
Speech ms-settings:speech
**Gaming**
Game bar ms-settings:gaming-gamebar
Captures ms-settings:gaming-gamedvr
Broadcasting ms-settings:gaming-broadcasting
Game Mode ms-settings:gaming-gamemode
TruePlay (removed in version 1809+) ms-settings:gaming-trueplay
Xbox Networking (build 16226+) ms-settings:gaming-xboxnetworking
**Extras**
Extras (available when Settings app extensions installed) ms-settings:extras
**Ease of Access**
Display (build 17025+) ms-settings:easeofaccess-display
Mouse Pointer (Cursor & pointer, build 17040+) ms-settings:easeofaccess-cursorandpointersize OR ms-settings:easeofaccess-MousePointer
Text Cursor ms-settings:easeofaccess-cursor
Magnifier ms-settings:easeofaccess-magnifier
Color Filters (build 17025+) ms-settings:easeofaccess-colorfilter
Adaptive Color Filters Link ms-settings:easeofaccess-colorfilter-adaptivecolorlink
Night Light Link ms-settings:easeofaccess-colorfilter-bluelightlink
High Contrast ms-settings:easeofaccess-highcontrast
Narrator ms-settings:easeofaccess-narrator
Start Narratorafter sign-in for me ms-settings:easeofaccess-narrator-isautostartenabled
Audio (build 17035+) ms-settings:easeofaccess-audio
Closed captions ms-settings:easeofaccess-closedcaptioning
Speech (build 17035+) ms-settings:easeofaccess-speechrecognition
Keyboard ms-settings:easeofaccess-keyboard
Mouse ms-settings:easeofaccess-mouse
Eye Control (build 17035+) ms-settings:easeofaccess-eyecontrol
Other options (removed in version 1809+) ms-settings:easeofaccess-otheroptions
**Search (version 1903+)**
Permissions & history ms-settings:search-permissions
Searching Windows ms-settings:cortana-windowssearch
More details ms-settings:search-moredetails
**Cortana (build 16188+)**
Cortana ms-settings:cortana
Talk to Cortana ms-settings:cortana-talktocortana
Permissions ms-settings:cortana-permissions
More details ms-settings:cortana-moredetails
**Privacy**
General ms-settings:privacy
Speech ms-settings:privacy-speech
Inking & typing personalization ms-settings:privacy-speechtyping
Diagnostics & feedback ms-settings:privacy-feedback
View Diagnostic Data ms-settings:privacy-feedback-telemetryviewergroup
Activity history (build 17040+) ms-settings:privacy-activityhistory
Location ms-settings:privacy-location
Camera ms-settings:privacy-webcam
Microphone ms-settings:privacy-microphone
Voice activation ms-settings:privacy-voiceactivation
Notifications ms-settings:privacy-notifications
Account info ms-settings:privacy-accountinfo
Contacts ms-settings:privacy-contacts
Calendar ms-settings:privacy-calendar
Phone calls (removed in version 1809+) ms-settings:privacy-phonecalls
Call history ms-settings:privacy-callhistory
Email ms-settings:privacy-email
Eye tracker (requires eyetracker hardware) ms-settings:privacy-eyetracker
Tasks ms-settings:privacy-tasks
Messaging ms-settings:privacy-messaging
Radios ms-settings:privacy-radios
Other devices ms-settings:privacy-customdevices
Background apps ms-settings:privacy-backgroundapps
App diagnostics ms-settings:privacy-appdiagnostics
Automatic file downloads ms-settings:privacy-automaticfiledownloads
Documents ms-settings:privacy-documents
Pictures ms-settings:privacy-pictures
Videos ms-settings:privacy-documents
File system ms-settings:privacy-broadfilesystemaccess
**Update & security**
Windows Update ms-settings:windowsupdate
Check for updates ms-settings:windowsupdate-action
View update history ms-settings:windowsupdate-history
Restart options ms-settings:windowsupdate-restartoptions
Advanced options ms-settings:windowsupdate-options
Change active hours ms-settings:windowsupdate-activehours
Optional updates ms-settings:windowsupdate-optionalupdates OR ms-settings:windowsupdate-seekerondemand
Delivery Optimization ms-settings:delivery-optimization
Windows Security / Windows Defender ms-settings:windowsdefender
Open Windows Security windowsdefender:
Backup ms-settings:backup
Troubleshoot ms-settings:troubleshoot
Recovery ms-settings:recovery
Activation ms-settings:activation
Find My Device ms-settings:findmydevice
For developers ms-settings:developers
Windows Insider Program ms-settings:windowsinsider, OR ms-settings:windowsinsider-optin
**Mixed reality**
Mixed reality ms-settings:holographic
Audio and speech ms-settings:holographic-audio
Environment ms-settings:privacy-holographic-environment
Headset display ms-settings:holographic-headset
Uninstall ms-settings:holographic-management
**Surface Hub**
Accounts ms-settings:surfacehub-accounts
Team Conferencing ms-settings:surfacehub-calling
Team device management ms-settings:surfacehub-devicemanagenent
Session cleanup ms-settings:surfacehub-sessioncleanup
Welcome screen ms-settings:surfacehub-welcome

PowerShell 技能连载 - 高级排序(第 4 部分)

在上一个部分中,我们说明了如何使用脚本块对排序进行更多的控制。例如,您可以使用 “-as“ 运算符来转换数据以控制排序算法。

这样,您可以“修正”传入数据的数据类型。例如将某些或所有数字数据转为字符串类型,再传给 Sort-Object。看看第一个例子的结果,以及下方的修正结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
PS> 1,2,"13",4,11,3,"2" | Sort-Object
1
13
2
3
4
11
2

PS> 1,2,"13",4,11,3,"2" | Sort-Object -Property { $_ -as [double] }
1
2
2
3
4
11
13

同样,您可以完全随机化列表,快速地创建简单的随机密码:

1
2
3
4
5
PS> -join ('abcdefghkmnrstuvwxyz23456789*+#'.ToCharArray() | Get-Random -count 5 | Sort-Object -Property { Get-Random } )
m2v6u

PS> -join ('abcdefghkmnrstuvwxyz23456789*+#'.ToCharArray() | Get-Random -count 5 | Sort-Object -Property { Get-Random } )
b+g7t

或者,您可以根据计算值进行排序。下面的示例按文件年龄排序,通过从创建时间中减去上次写入时间计算得出:

1
2
3
Get-ChildItem -Path c:\windows -Filter *.log -Depth 1 -ErrorAction Ignore |
Sort-Object -Property { $_.LastWriteTime - $_.CreationTime } |
Select-Object -Property Name, LastWriteTime, CreationTime, @{Name='Age (Days)';Expression={ [int]($_.LastWriteTime - $_.CreationTime).TotalDays }}

结果看起来类似这样:

Name                                 LastWriteTime       CreationTime        Age (Days)
----                                 -------------       ------------        ----------
setupapi.upgrade.log                 28.09.2020 15:04:56 28.09.2020 15:40:12          0
setuperr.log                         11.07.2021 14:37:51 11.07.2021 14:37:51          0
setupact.log                         16.10.2021 12:59:17 16.10.2021 12:59:17          0
setupapi.setup.log                   28.09.2020 17:48:22 28.09.2020 17:47:36          0
setupapi.offline.20191207_091437.log 07.12.2019 10:14:37 07.12.2019 10:13:02          0
setupapi.offline.log                 28.09.2020 15:40:12 28.09.2020 15:09:47          0
setupapi.dev.20201120_180252.log     20.11.2020 18:02:52 28.09.2020 17:51:43         53
setupapi.dev.20210514_095516.log     14.05.2021 09:55:16 27.02.2021 04:17:58         76
setupapi.dev.20210226_041725.log     26.02.2021 04:17:25 22.11.2020 04:18:58         96
lvcoinst.log                         23.10.2021 15:30:45 19.07.2021 08:46:48         96
PFRO.log                             25.10.2021 13:54:27 11.07.2021 14:41:28        106
WindowsUpdate.log                    26.10.2021 10:47:38 10.07.2021 15:05:05        108
setupapi.dev.20210710_201855.log     10.07.2021 20:18:55 27.02.2021 04:17:58        134
setupapi.dev.20210915_082529.log     15.09.2021 08:25:29 27.02.2021 04:17:58        200
NetSetup.LOG                         17.04.2020 15:19:26 26.08.2019 17:23:11        235
setupapi.dev.log                     26.10.2021 06:27:25 27.02.2021 04:17:58        241
mrt.log                              13.10.2021 08:30:39 12.11.2020 07:16:17        335
PASSWD.LOG                           25.10.2021 13:54:28 28.09.2020 17:47:22        392
ReportingEvents.log                  26.10.2021 09:37:23 03.09.2019 10:42:58        784
Gms.log                              25.10.2021 13:54:32 26.08.2019 17:27:50        791

请注意如何以非常相似的方式将哈希表与 Select-Object 一起使用。在示例中,通过将哈希表提交给 Select-Object,将“Age (Days)”属性添加到输出中。在内部,哈希表定义了新属性的名称并提供了一个脚本块来计算属性值。此脚本块的工作原理与此处讨论的脚本块基本相同:$_ 表示整个对象,您可以使用任何 PowerShell 表达式来转换或计算该值。

PowerShell 技能连载 - 高级排序(第 3 部分)

在上一个提示中,您已经看到 Sort-Object 如何接受哈希表作为参数,对排序进行高级控制。 例如,此行代码按状态排序,然后显示名称,并为每个属性使用单独的排序方向:

1
2
3
Get-Service |
Sort-Object -Property @{Expression='Status'; Descending=$true}, @{Expression='DisplayName'; Descending=$false } |
Select-Object -Property DisplayName, Status

但是,当您查看结果时,”Status” 属性的排序方向似乎是错的。我们已经澄清了这一点,因为 “Status” 实质上是一个数字常量,而 Sort-Object 排序的底层逻辑是对原始数据进行排序。所以它是根据内部的数值型常量对 “Status” 进行排序,而不是根据可见的友好名称。

要确保 Sort-Object 是按照用户“看见”对象的内容对它们排序,请使用哈希表的另一个功能:”Expression” 键不仅能接受属性的名称,而且用支持脚本块(代码)转换为任何数据,再对该数据排序。在脚本块内,$_ 表示完整的传入对象。

要确保 “Status” 根据文本来排序而不是根据背后的数值来排序,请将其转换为字符串,如下所示:

1
2
3
Get-Service |
Sort-Object -Property @{Expression={[string]$_.Status}; Descending=$true}, @{Expression='DisplayName'; Descending=$false } |
Select-Object -Property DisplayName, Status

事实上,在排序之前改变数据的能力,能改变所有排序的游戏规则。

假设您有一个 HTTPS 连接列表,用于保存浏览器连接到的远程 IP 地址,并且您正在尝试通过 Sort-Object 来对这些 IP 地址进行排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
PS C:\> Get-NetTCPConnection -RemotePort 443 | Select-Object -Property RemoteAddress, RemotePort, State, OwningProcess | Sort-Object -Property RemoteAddress

RemoteAddress RemotePort State OwningProcess
------------- ---------- ----- -------------
142.250.185.74 443 TimeWait 0
142.250.186.46 443 TimeWait 0
20.199.120.182 443 Established 3552
20.199.120.182 443 Established 5564
20.42.65.89 443 Established 9836
20.42.65.89 443 TimeWait 0
20.42.73.24 443 TimeWait 0
35.186.224.25 443 TimeWait 0
45.60.13.212 443 Established 7644
51.104.30.131 443 Established 10220

如果您将仔细查看结果,您将看到 “RemoteAddress” 未正确排序:例如 “20.199.120.182” 列在了 “20.42.65.89” 的前面。

这是因为这些 IPv4 地址被视为字符串,因此 Sort-Object 使用默认的字母数字排序算法。

您现在知道如何以更合适的数据类型转换数据。例如,IPv4 地址可以被视为软件版本(数据类型[版本])正确排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
PS> Get-NetTCPConnection -RemotePort 443 | Select-Object -Property RemoteAddress, RemotePort, State, OwningProcess | Sort-Object -Property @{Expression={ $_.RemoteAddress -as [version] }}

RemoteAddress RemotePort State OwningProcess
------------- ---------- ----- -------------
20.42.65.89 443 Established 9836
20.42.65.89 443 TimeWait 0
20.199.120.182 443 Established 3552
20.199.120.182 443 Established 5564
35.186.224.25 443 TimeWait 0
45.60.13.212 443 Established 7644
51.104.30.131 443 Established 10220
142.250.185.74 443 TimeWait 0
142.250.186.46 443 TimeWait 0

现在 IP 地址已可以正确排序。

注意:当将数据转换为其他数据类型(如此处所示)时,始终优先使用 -as 运算符进行直接类型转换。如果数据不能转换为所需的数据类型,则 -as 运算符只会返回 $null,而直接类型转换将会产生异常。

在前面的例子中,如果 “RemoteAddress” 会显示一个 IPv6 地址(不能转换为 [version]),幸亏 -as 操作符,这些项目不会被排序,而会放在排序数据的开头.

要缩短代码,您可以简写哈希表的键(只要它们保持唯一):

1
2
3
Get-NetTCPConnection -RemotePort 443 |
Select-Object -Property RemoteAddress, RemotePort, State, OwningProcess |
Sort-Object -Property @{E={ $_.RemoteAddress -as [version] }}

如果您需要的只是数据转换,则可以完全跳过哈希表并将脚本块直接传给 -Property 参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
PS> Get-NetTCPConnection -RemotePort 443 | Select-Object -Property RemoteAddress, RemotePort, State, OwningProcess | Sort-Object -Property { $_.RemoteAddress -as [version] }

RemoteAddress RemotePort State OwningProcess
------------- ---------- ----- -------------
20.42.65.89 443 Established 9836
20.42.65.89 443 TimeWait 0
20.199.120.182 443 Established 3552
20.199.120.182 443 Established 5564
35.186.224.25 443 TimeWait 0
45.60.13.212 443 Established 7644
51.104.30.131 443 Established 10220
142.250.185.74 443 TimeWait 0
142.250.186.46 443 TimeWait 0

PowerShell 技能连载 - 高级排序(第 2 部分)

Sort-Object 支持高级排序,并在您传入哈希表时提供更多控制。例如,哈希表可以单独控制多个属性的排序方向。

例如,此行代码按状态对服务进行排序,然后按名称排序。排序方向可以通过 -Descending 开关参数控制,但始终适用于所有选定的属性:

1
2
3
Get-Service | Sort-Object -Property Status, DisplayName | Select-Object -Property DisplayName, Status

Get-Service | Sort-Object -Property Status, DisplayName -Descending | Select-Object -Property DisplayName, Status

要单独控制排序方向,请传入哈希表并使用 ExpressionDescending 键。这首先按状态(降序)对服务进行排序,然后按显示名称(升序):

1
2
3
Get-Service |
Sort-Object -Property @{Expression='Status'; Descending=$true}, @{Expression='DisplayName'; Descending=$false } |
Select-Object -Property DisplayName, Status

注意:当您查看结果时,您可能会对“状态”属性的内容排序方式感到恼火。尽管代码要求降序排序,但您首先会看到正在运行的服务,然后是停止的服务。

这个问题的简单答案是:您现在知道如何单独控制排序,因此如果排序顺序错误,只需尝试颠倒排序顺序,看看是否适合您。

深入的答案是:”Status“ 属性实际上是一个数字常量,而 Sort-Object 始终对底层数据进行排序。因此,当您使数字常量可见时,会发现排序顺序是正确的:

1
2
3
Get-Service |
Sort-Object -Property @{Expression='Status'; Descending=$true}, @{Expression='DisplayName'; Descending=$false } |
Select-Object -Property DisplayName, { [int]$_.Status }

正如您现在所看到的,”Running“ 实际上是常量 “4”,而 “Stopped” 由常量 1 表示。

不要错过我们的下一个技能,以获得更多控制(以及对由底层数字常量引起的问题的优雅修复)。

PowerShell 技能连载 - 高级排序(第 1 部分)

Sort-Object easily sorts results for you. For primitive data such as numbers or strings, simply add Sort-Object to your pipeline. This gets you a sorted list of lottery numbers:
Sort-Object 能轻松对结果排序。对于数字或字符串等原始数据,只需将 Sort-Object 添加到您的管道中。这将为您提供一个排序的彩票号码列表:

1
2
3
4
$lottery = 1..49 | Get-Random -Count 7 | Sort-Object
# set the string you want to use to separate numbers in your output
$ofs = ','
"Your numbers are $lottery"

具有多个属性的对象数据要求您定义要排序的属性。此行代码按状态对服务进行排序:

1
Get-Service | Sort-Object -Property Status

Sort-Object 甚至支持多种排序。此行代码按状态对服务进行排序,然后按服务名称排序:

1
Get-Service | Sort-Object -Property Status, DisplayName | Select-Object -Property DisplayName, Status

要反转排序顺序,请添加 -Descending 开关参数。

有关排序的更多控制,例如,对一个属性升序排序和另一个属性降序排序,请参阅我们的下一个提示。

PowerShell 技能连载 - 速度很重要

PowerShell 是一种通用自动化语言,因此它的目标是多功能且易于使用。速度不是首要任务。

如果您确实关心最大速度,那么有一些 cmdlet 几乎可以完全满足 .NET 调用的功能。在这些实例中使用直接 .NET 调用会更快,尤其是在经常调用这些 cmdlet 时(例如在循环中)。但另一方面是它使您的代码更难阅读。

这里有一些例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# cmdlet
PS> Join-Path -Path $env:temp -ChildPath test.txt
C:\Users\tobia\AppData\Local\Temp\test.txt

# direct .NET
PS> [System.IO.Path]::Combine($env:temp, 'test.txt')
C:\Users\tobia\AppData\Local\Temp\test.txt


# cmdlet
PS> Get-Date

Monday, October 4, 2021 12:34:46

# direct .NET
PS> [DateTime]::Now

Monday, October 4, 2021 12:34:52

PowerShell 技能连载 - 读取文本文件(快速)

如果您需要加载大文本文件并使用 Get-Content,那么您可以节省大量时间。

如果您没有立即通过管道处理通过管道发出的结果,则可能需要添加参数 -ReadCount 0。这可以使读取文本文件的速度提升 100 倍。

如果没有此参数,Get-Content 会单独对每个文本行产生一次输出。如果这些行要传递给管道处理,那么没有问题。但是如果要将文本存储在变量中并使用其他处理方式,则这是浪费时间,例如经典的 foreach 循环。

PowerShell 技能连载 - Working with Get-WinEvent

如果您想从 Windows 事件日志中读取系统事件,Get-Eventlog 是个易于使用且简单的选择。这段代码能够获取最新的 10 个错误和警告事件:

1
PS> Get-EventLog -LogName System -EntryType Error,Warning -Newest 10

不幸的是,Get-Eventlog 已被弃用,并且它不再可用于 PowerShell 7。弃用有很明显的原因:该 cmdlet 只能从“经典”日志文件中读取,它很缓慢并且具有其他限制。

这就是为什么 PowerShell 在3.0版中推出更好的替代命令:Get-WinEvent。PowerShell 7 也有此 cmdlet。

Unfortunately, Get-WinEvent is much harder to use because there are no intuitive parameters, and instead your filter criteria needs to be specified as a hash table.
不幸的是,Get-Winevent 更难使用,因为没有直观的参数,而是需要通过哈希表指定过滤条件。

但是,通过“代理函数”,您可以指导 Get-WinEvent 使用您所熟悉的旧式参数。以下是代码:

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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
<#Suggestion to improve Get-WinEvent in order to make it compatible to the commonly used Get-EventLog callsBelow is a prototype using a proxy function. Run it to enhance Get-WinEvent.To get rid of the enhancement, either restart PowerShell or run:Remove-Item -Path function:Get-WinEventNote that the prototype emits the composed hash table to the console (green)
\#>function Get-WinEvent
{ [CmdletBinding(DefaultParameterSetName='GetLogSet', HelpUri='https://go.microsoft.com/fwlink/?LinkID=138336')]
param(

[Parameter(ParameterSetName='ListLogSet', Mandatory=$true, Position=0)]
[AllowEmptyCollection()]
[string[]]
${ListLog}, [Parameter(ParameterSetName='LogNameGetEventlog', Mandatory=$true, Position=0)] <#NEW\#>
[Parameter(ParameterSetName='GetLogSet', Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
[string[]]
${LogName}, [Parameter(ParameterSetName='ListProviderSet', Mandatory=$true, Position=0)]
[AllowEmptyCollection()]
[string[]]
${ListProvider}, <# Get-EventLog supports wildcards, Get-WinEvent does not. Needs to be corrected. #> [Parameter(ParameterSetName='GetProviderSet', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
[string[]]
${ProviderName}, [Parameter(ParameterSetName='FileSet', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
[Alias('PSPath')]
[string[]]
${Path}, [Parameter(ParameterSetName='FileSet')]
[Parameter(ParameterSetName='GetProviderSet')]
[Parameter(ParameterSetName='GetLogSet')]
[Parameter(ParameterSetName='HashQuerySet')]
[Parameter(ParameterSetName='XmlQuerySet')]
[ValidateRange(1, 9223372036854775807)]
[long]
${MaxEvents},
<# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog')]
[ValidateRange(0, 2147483647)]
[int]
${Newest},
[Parameter(ParameterSetName='GetProviderSet')]
[Parameter(ParameterSetName='ListProviderSet')]
[Parameter(ParameterSetName='ListLogSet')]
[Parameter(ParameterSetName='GetLogSet')]
[Parameter(ParameterSetName='HashQuerySet')]
[Parameter(ParameterSetName='XmlQuerySet')]
[Parameter(ParameterSetName='LogNameGetEventlog')] <#NEW\#>
[Alias('Cn')]
[ValidateNotNullOrEmpty()] <#CORRECTED\#> [string] <# used to be [String[]], Get-WinEvent accepts [string] only, should be changed to accept string arrays \#> ${ComputerName}, [Parameter(ParameterSetName='GetProviderSet')]
[Parameter(ParameterSetName='ListProviderSet')]
[Parameter(ParameterSetName='ListLogSet')]
[Parameter(ParameterSetName='GetLogSet')]
[Parameter(ParameterSetName='HashQuerySet')]
[Parameter(ParameterSetName='XmlQuerySet')]
[Parameter(ParameterSetName='FileSet')]
[pscredential]
[System.Management.Automation.CredentialAttribute()]
${Credential}, [Parameter(ParameterSetName='FileSet')]
[Parameter(ParameterSetName='GetProviderSet')]
[Parameter(ParameterSetName='GetLogSet')]
[ValidateNotNull()]
[string]
${FilterXPath}, [Parameter(ParameterSetName='XmlQuerySet', Mandatory=$true, Position=0)]
[xml]
${FilterXml}, [Parameter(ParameterSetName='HashQuerySet', Mandatory=$true, Position=0)]
[hashtable[]]
${FilterHashtable}, [Parameter(ParameterSetName='GetProviderSet')]
[Parameter(ParameterSetName='ListLogSet')]
[Parameter(ParameterSetName='GetLogSet')]
[Parameter(ParameterSetName='HashQuerySet')]
[switch]
${Force}, [Parameter(ParameterSetName='GetLogSet')]
[Parameter(ParameterSetName='GetProviderSet')]
[Parameter(ParameterSetName='FileSet')]
[Parameter(ParameterSetName='HashQuerySet')]
[Parameter(ParameterSetName='XmlQuerySet')]
[switch]
${Oldest},
<# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog')]
[ValidateNotNullOrEmpty()]
[datetime]
${After}, <# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog')]
[ValidateNotNullOrEmpty()]
[datetime]
${Before},
<# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog')]
[ValidateNotNullOrEmpty()]
[string[]]
${UserName}, <# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog', Position=1)]
[ValidateRange(0, 9223372036854775807)]
[ValidateNotNullOrEmpty()]
[long[]]
${InstanceId}, <# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog')]
[ValidateNotNullOrEmpty()]
[ValidateRange(1, 2147483647)]
[int[]]
${Index}, <# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog')]
[Alias('ET')]
[ValidateNotNullOrEmpty()]
[ValidateSet('Error','Information','FailureAudit','SuccessAudit','Warning')]
[string[]]
${EntryType}, <# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog')]
[Alias('ABO')]
[ValidateNotNullOrEmpty()]
[string[]]
${Source}, <# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog')]
[Alias('MSG')]
[ValidateNotNullOrEmpty()]
[string]
${Message}, <# NEW \#> [Parameter(ParameterSetName='LogNameGetEventlog')]
[switch]
${AsBaseObject},
[Parameter(ParameterSetName='ListGetEventlog')]
[switch]
${List}, [Parameter(ParameterSetName='ListGetEventlog')]
[switch]
${AsString}



)

begin {
try {
$outBuffer = $null if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
{
$PSBoundParameters['OutBuffer'] = 1 }
$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Diagnostics\Get-WinEvent', [System.Management.Automation.CommandTypes]::Cmdlet)

\# if the user chose the Get-EventLog compatible parameters, \# compose the appropriate filter hash table $scriptCmd = if ($PSCmdlet.ParameterSetName -eq 'LogNameGetEventlog')
{
\# mandatory parameter $filter = @{
LogName = $PSBoundParameters['Logname']
}
$null = $PSBoundParameters.Remove('LogName')

if ($PSBoundParameters.ContainsKey('Before'))
{
$filter['EndTime'] = $PSBoundParameters['Before']
$null = $PSBoundParameters.Remove('Before')
}
if ($PSBoundParameters.ContainsKey('After'))
{
$filter['StartTime'] = $PSBoundParameters['After']
$null = $PSBoundParameters.Remove('After')
}
if ($PSBoundParameters.ContainsKey('EntryType'))
{
\# severity is translated to an integer array
$levelFlags = [System.Collections.Generic.List[int]]@()

\# string input converted to integer array if ($PSBoundParameters['EntryType'] -contains 'Error')
{
$levelFlags.Add(1) \# critical $levelFlags.Add(2) \# error }
if ($PSBoundParameters['EntryType'] -contains 'Warning')
{
$levelFlags.Add(3) \# warning }
if ($PSBoundParameters['EntryType'] -contains 'Information')
{
$levelFlags.Add(4) \# informational $levelFlags.Add(5) \# verbose }


\# default to 0 if ($levelFlags.Count -gt 0)
{
$filter['Level'] = [int[]]$levelFlags }

\# audit settings stored in Keywords key if ($PSBoundParameters['EntryType'] -contains 'FailureAudit')
{
$filter['Keywords'] += 0x10000000000000 }
if ($PSBoundParameters['EntryType'] -contains 'SuccessAudit')
{
$filter['Keywords'] += 0x20000000000000 }
$null = $PSBoundParameters.Remove('EntryType')
}
if ($PSBoundParameters.ContainsKey('InstanceId'))
{
$filter['ID'] = $PSBoundParameters['InstanceId']
$null = $PSBoundParameters.Remove('InstanceId')
}
if ($PSBoundParameters.ContainsKey('Source'))
{
$filter['ProviderName'] = $PSBoundParameters['Source']
$null = $PSBoundParameters.Remove('Source')
}

$PSBoundParameters['FilterHashtable'] = $filter Write-Host ($filter | Out-String) -ForegroundColor Green
if ($PSBoundParameters.ContainsKey('Newest'))
{
$PSBoundParameters['MaxEvents'] = $PSBoundParameters['Newest']
$null = $PSBoundParameters.Remove('Newest')
}
}


$scriptCmd =
{
& $wrappedCmd @PSBoundParameters }
$steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
$steppablePipeline.Begin($PSCmdlet)
} catch {
throw }
}

process {
try {
$steppablePipeline.Process($_)
} catch {
throw }
}

end {
try {
$steppablePipeline.End()
} catch {
throw }
}
<#

.ForwardHelpTargetName Microsoft.PowerShell.Diagnostics\Get-WinEvent .ForwardHelpCategory Cmdlet \#>}

当您执行完这个函数,就可以通过您在 Get-EventLog 中熟悉的相同参数使用 Get-WinEvent

1
2
3
4
5
6
PS> Get-WinEvent -LogName System -EntryType Error,Warning -Newest 10

Name Value
---- -----
LogName {System}
Level {1, 2, 3}

您还可以获得基于参数使用的哈希表过滤器的键和值。

PowerShell 技能连载 - 调整脚本性能

如果脚本运行速度速度慢,找出导致延迟的地方并优化并不是一件很简单的事。使用名为 “psprofiler” 的 PowerShell 模块,可以测试脚本中的每行所需的时间。它在 Windows PowerShell 和 PowerShell 7 中都能运行。

首先安装模块:

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

下一步,用 Measure-Script 执行脚本:

1
PS> Measure-Script -Path 'C:\Users\tobias\test123.ps1'

Once your script completes, you get a sophisticated report telling you exactly how often each line of your script was executed, and how long it took:
脚本完成后,就会获得一份复杂的报告,告诉您脚本每行执行的次数,以及消耗的时间:

  Count  Line       Time Taken Statement
  -----  ----       ---------- ---------
      1     1    00:00.0033734 $Path = "$env:temp\tv.json"
      0     2    00:00.0000000
      1     3    00:28.1602885 $data = Get-Content -Path $Path -Raw |
      0     4    00:00.0000000 ConvertFrom-Json |
      1     5    00:26.6558438 ForEach-Object { $_ } |
      0     6    00:00.0000000 ForEach-Object {
      0     7    00:00.0000000
 101000     8    00:01.4408993   $title = '{0,5} [{2}] "{1}" ({3})' -f ([Object[]]$_)
 101000     9    00:13.6815132   $title | Add-Member -MemberType NoteProperty -Name Data -Value $_ -PassThru
      0    10    00:00.0000000 }
      0    11    00:00.0000000
...

PowerShell 技能连载 - 将 Ticks 转换为 DateTime

偶尔,日期和时间信息以所谓的“缺陷”的格式存储为 “Ticks”。 Ticks 是自 01/01/1601 以来,100 纳秒的单位数。Active Directory 在内部使用此格式,但您也可以在其他地方找到它。 以下是以 “Ticks” 为单位的 Windows 安装时间的示例:

1
2
3
4
$values = Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion'
$installDateTicks = $values.InstallTime

$installDateTicks

结果是(非常)大的 64 比特数字:

132457820129777032

要将 Ticks 转换为 DateTime,请使用 [DateTimeOffset]

1
2
3
4
5
$values = Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion'
$installDateTicks = $values.InstallTime

$installDate = [DateTimeOffset]::FromFileTime($installDateTicks)
$installDate.DateTime