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

在上一个技能中,我们使用自定义代理功能对原始的 Get-Help cmdlet 进行了“影子”处理。该功能检查命令是否存在联机帮助,如果存在,则默认情况下会打开丰富的联机帮助。这极大地改善了 PowerShell 中的帮助体验。

但是,通过简单的调整,您可以使该功能更进一步:为什么不同时检查另一种方式呢?如果用户使用 -Online 参数,但是没有在线帮助,则 Get-Help 会抛出一个丑陋的异常。显示内置的本地帮助而不是抛出异常,不是更好吗?

当用户将 Get-Help 的默认值设置为 -Online 时,也可使该函数能适应 $PSDefaultParameterValue 的调整。

这是更新的函数:

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
function Get-Help{
\# clone the original param block taken from Get-Help [CmdletBinding(DefaultParameterSetName='AllUsersView', HelpUri='https://go.microsoft.com/fwlink/?LinkID=113316')]
param(
[Parameter(Position=0, ValueFromPipelineByPropertyName)]
[string]
$Name, [Parameter(ParameterSetName='Online', Mandatory)]
[switch]
$Online, [ValidateSet('Alias','Cmdlet','Provider','General','FAQ','Glossary','HelpFile','ScriptCommand','Function','Filter','ExternalScript','All','DefaultHelp','Workflow','DscResource','Class','Configuration')]
[string[]]
$Category, [string]
$Path, [string[]]
$Component, [string[]]
$Functionality, [string[]]
$Role, [Parameter(ParameterSetName='DetailedView', Mandatory)]
[switch]
$Detailed, [Parameter(ParameterSetName='AllUsersView')]
[switch]
$Full, [Parameter(ParameterSetName='Examples', Mandatory)]
[switch]
$Examples, [Parameter(ParameterSetName='Parameters', Mandatory)]
[string]
$Parameter, [Parameter(ParameterSetName='ShowWindow', Mandatory)]
[switch]
$ShowWindow )

begin {
\# we do the adjustments only when the user has submitted \# the -Name, -Category, and -Online parameters
if ( (@($PSBoundParameters.Keys) -ne 'Name' -ne 'Category' -ne 'Online'). Count -eq 0 )
{
\# check whether there IS online help available at all
\# retrieve the help URI $help = Microsoft.PowerShell.Core\Get-Command -Name $Name
\# reset the parameter -Online based on availability of online help $PSBoundParameters['Online']= [string]::IsNullOrWhiteSpace($help.HelpUri) -eq $false }

\# once the parameter adjustment has been processed, call the original \# Get-Help cmdlet with the parameters found in $PSBoundParameters
\# turn the original Get-Help cmdlet into a proxy command receiving the \# adjusted parameters \# with a proxy command, you can invoke its begin, process, and end \# logic separately. That's required to preserve pipeline functionality $cmd = Get-Command -Name 'Get-Help' -CommandType Cmdlet $proxy = {& $cmd @PSBoundParameters}. GetSteppablePipeline($myInvocation.CommandOrigin)

\# now, call its default begin, process, and end blocks in the appropriate \# script blocks so it integrates in real-time pipelines $proxy.Begin($PSCmdlet)
}

process { $proxy.Process($_) }

end { $proxy.End() }

\# use the original help taken from Get-Help for this function <#
.ForwardHelpTargetName Microsoft.PowerShell.Core\Get-Help .ForwardHelpCategory Cmdlet \#>}

运行这段代码之后,无论使用 Get-Helphelp 还是公共参数 -?,您的帮助系统现在都变得更加智能。

如果有可用于命令的联机帮助,则默认情况下显示:

1
2
3
PS> Get-Help Get-Service

PS> Get-Service -?

如果没有可用的联机帮助,它将始终显示本地帮助(即使您不小心指定了 -Online 或使用 $PSDefaultParameterValue 来显式使用 -Online):

1
2
3
PS> Connect-IscsiTarget -?

PS> Get-Help Connect-IscsiTarget -Online

并且,如果您指定其他参数,它们仍然可以按预期继续工作:

1
PS> Get-Help Get-Service -ShowWindow

本质上,该调整仅包含同时提供丰富在线帮助内容,并在可用时显示它。

如果您喜欢此功能,请将其添加到配置文件脚本中,以便在启动 PowerShell 时对其进行定义。路径可以在这里找到:$profile.CurrentUserAllHosts

PowerShell 技能连载 - 更好的 PowerShell 帮助(第 2 部分)

在上一个技能中,我们更改了 Get-Help 的默认参数值,以在您使用 Get-Help 或通用参数 -? 时自动显示丰富的联机帮助。但是,当 cmdlet 没有联机帮助时,此方法会产生错误。

更好的方法是首先检查给定命令是否存在联机帮助,然后才打开联机帮助。如果没有在线帮助,则应显示默认的本地帮助。

此方法无法通过默认参数实现。相反,Get-Help cmdlet 本身需要进行调整。要将逻辑添加到 Get-Help,可以使用以下代理函数:

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
function Get-Help{
\# clone the original param block taken from Get-Help [CmdletBinding(DefaultParameterSetName='AllUsersView', HelpUri='https://go.microsoft.com/fwlink/?LinkID=113316')]
param(
[Parameter(Position=0, ValueFromPipelineByPropertyName)]
[string]
$Name, [Parameter(ParameterSetName='Online', Mandatory)]
[switch]
$Online, [ValidateSet('Alias','Cmdlet','Provider','General','FAQ','Glossary','HelpFile','ScriptCommand','Function','Filter','ExternalScript','All','DefaultHelp','Workflow','DscResource','Class','Configuration')]
[string[]]
$Category, [string]
$Path, [string[]]
$Component, [string[]]
$Functionality, [string[]]
$Role, [Parameter(ParameterSetName='DetailedView', Mandatory)]
[switch]
$Detailed, [Parameter(ParameterSetName='AllUsersView')]
[switch]
$Full, [Parameter(ParameterSetName='Examples', Mandatory)]
[switch]
$Examples, [Parameter(ParameterSetName='Parameters', Mandatory)]
[string]
$Parameter, [Parameter(ParameterSetName='ShowWindow', Mandatory)]
[switch]
$ShowWindow )

begin {
\# determine whether -Online should be made a default if (
\# user submitted -Name only ( $PSBoundParameters.Count -eq 1 -and
$PSBoundParameters.ContainsKey('Name')
) -or \# system submitted -Name and -Category (when using -?) (
$PSBoundParameters.Count -eq 2 -and
$PSBoundParameters.ContainsKey('Name') -and
$PSBoundParameters.ContainsKey('Category')
)
)
{
\# prerequisites are OK, now check whether there IS online help \# available at all
\# retrieve the help URI $help = Microsoft.PowerShell.Core\Get-Command -Name $Name
\# set the -Online parameter only if there is a help URI $PSBoundParameters['Online']= [string]::IsNullOrWhiteSpace($help.HelpUri) -eq $false }

\# once the parameter adjustment has been processed, call the original \# Get-Help cmdlet with the parameters found in $PSBoundParameters
\# turn the original Get-Help cmdlet into a proxy command receiving the \# adjusted parameters \# with a proxy command, you can invoke its begin, process, and end \# logic separately. That's required to preserve pipeline functionality $cmd = Get-Command -Name 'Get-Help' -CommandType Cmdlet $proxy = {& $cmd @PSBoundParameters}. GetSteppablePipeline($myInvocation.CommandOrigin)

\# now, call its default begin, process, and end blocks in the appropriate \# script blocks so it integrates in real-time pipelines $proxy.Begin($PSCmdlet)
}

process { $proxy.Process($_) }

end { $proxy.End() }

\# use the original help taken from Get-Help for this function <#
.ForwardHelpTargetName Microsoft.PowerShell.Core\Get-Help .ForwardHelpCategory Cmdlet \#>}

运行此代码时,Get-Help 函数现在将覆盖原始的 Get-Help cmdlet。在内部,该函数调用原生的 cmdlet,但在此之前,该函数检查 -Online 是否应设为默认参数。

现在,仅当用户未提交任何有冲突的参数时才发生这种情况,并且仅当首先有可用于所请求命令的联机帮助时才发生这种情况。

现在,无论何时使用 Get-Help 或通用参数 -?,您都会获得丰富的在线帮助(如果可用)或本地默认帮助。

试试以下代码:

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

PS> Connect-IscsiTarget -?

PS> Get-Help Get-Service

PS> Get-Help Get-Service -ShowWindow

由于有可用于 Get-Service 的联机帮助,因此第一个调用将打开浏览器窗口并显示帮助。第二个调用说明了没有可用的联机帮助时发生的情况:此处未将 “-Online“ 作为默认参数,而是显示了默认的本地帮助。

第三和第四次调用说明 Get-Help 仍然可以正常运行。默认情况下,该命令现在会打开联机帮助,但是如果您添加其他参数(例如 -ShowWindow),它们仍将按预期运行。

如果您喜欢此功能,则应将其添加到您的配置文件脚本中。

注意:如果您已通过 $PSDefaultParameterGet-Help 设置了任何默认参数(即,按照前面的提示进行操作时),则这些参数将生效,并且上面的功能无法为您带来任何改善。

确保您没有定义任何会影响 “Get-Help“ 的默认参数:

1
PS> $PSDefaultParameterValues.Keys.ToLower() -like 'get-help*'

PowerShell 技能连载 - 更好的 PowerShell 帮助(第 1 部分)

许多 cmdlet 提供了丰富的联机帮助,您可以使用 Get-Help 并加上 -Online 参数来自动打开 cmdlet 的网页:

1
PS> Get-Help -Name Get-Service -Online

每个 cmdlet 还支持公用参数 -?。不过,它仅显示了有限的内置本地帮助:

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

NAME
Get-Service

SYNTAX
Get-Service [-ComputerName <System.String[]>] [-DependentServices] -DisplayName <System.String[]> [-Exclude
<System.String[]>] [-Include <System.String[]>] [-RequiredServices] []
...

但是,您可以通过一个简单的技巧告诉 PowerShell 也对内置参数 -? 使用丰富的联机帮助。请运行这段代码:

1
PS> $PSDefaultParameterValues['Get-Help:Online'] = $true

此命令自动为 Get-Help -Online 参数设置一个新的默认值,并且因为 -? 内部使用 Get-Help,您现在只需添加 -? 到命令名称就可以获得大多数 PowerShell cmdlet 的丰富在线帮助。

1
PS> Get-Service -?

真是太棒了,因此您可能需要将该命令添加到自动启动配置文件脚本中。该脚本的路径可以在 $profile.CurrentUserAllHosts 中找到。它可能尚不存在,所以您可能必须创建它。

但是,有一个警告:如果命令没有在线帮助,那么您现在会收到一条错误消息,提示没有在线帮助。在即将发布的技能中,我们将单独解决此问题。

PowerShell 技能连载 - 检测 Wi-Fi 信号强度(第 3 部分)

在上一个技巧中,我们介绍了免费的 PowerShell 模块 Get-WLANs ,该模块可以访问 Windows Wi-Fi 框架并返回信息,例如信号强度。这是下载并安装它的命令:

1
Install-Module -Name Get-WLANs -Scope CurrentUser -Force

尽管您可以简单地使用其新命令 Get-WLANs(如上一技巧中所述),但该模块还添加了一个新的 .NET 类型,您可以在运行该命令后使用它。首先运行此命令以初始化新的 .NET 类型:

1
2
# "initialize" the new type
$null = Get-WLANs

接下来,创建一个原生的 “WlanClient” 对象:

1
$wc = [NativeWifi.WlanClient]::New()

现在,您可以转储有关系统中所有可用的 Wi-Fi 适配器的所有技术细节:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
PS> $wc.Interfaces


Autoconf : True
BssType : Any
InterfaceState : Connected
Channel : 36
RSSI : 29
RadioState : NativeWifi.Wlan+WlanRadioState
CurrentOperationMode : ExtensibleStation
CurrentConnection : NativeWifi.Wlan+WlanConnectionAttributes
NetworkInterface : System.Net.NetworkInformation.SystemNetworkInterface
InterfaceGuid : 7d6c33b7-0354-4ad7-a72f-5a1a5cbb1a9b
InterfaceDescription : Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)
InterfaceName : WLAN

Interfaces“ 属性返回一个数组,因此您的第一个 Wi-Fi 适配器由以下形式表示:

1
$wc.Interfaces[0]

它提供了很多方法,例如,检索可访问的可用 Wi-Fi 网络列表。这将扫描新的网络:

1
2
$wc.Interfaces[0].Scan()
Start-Sleep -Seconds 1

以下代码转储可使用的网络列表(包括信号强度,频率和信道):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
PS> $wc.Interfaces[0].GetAvailableNetworkList(3)


Dot11PhyTypes : {8}
profileName : internetcafe
dot11Ssid : NativeWifi.Wlan+Dot11Ssid
dot11BssType : Infrastructure
numberOfBssids : 3
networkConnectable : True
wlanNotConnectableReason : Success
morePhyTypes : False
wlanSignalQuality : 81
securityEnabled : True
dot11DefaultAuthAlgorithm : RSNA_PSK
dot11DefaultCipherAlgorithm : CCMP
flags : Connected, HasProfile

(...)

此对象模型为提供了丰富的方法和属性来控制和管理 Wi-Fi 网络适配器。例如,此代码转储可用的 SSID 列表及其信号强度:

1
2
3
4
5
6
7
8
9
10
11
$ssid = @{
N='SSID'
E={ [System.Text.Encoding]::Ascii.GetString( $_.dot11ssid.SSID,
0,
$_.dot11ssid.SSIDLength )
}
}

$wc.Interfaces[0].GetAvailableNetworkList(3) |
Select-Object -Property $ssid, wlanSignalQuality, profileName |
Where-Object SSID

结果看起来类似这样:

SSID                       wlanSignalQuality profileName
----                       ----------------- -----------
internetcafe                              81 internetcafe
internetcafe                              87 internetcafe 2
internetcafe                              87
DIRECT-fb-HP M477 LaserJet                31
Guest                                     67

PowerShell 技能连载 - 检测 Wi-Fi 信号强度(第 2 部分)

在上一个技能中,我们使用 netsh.exe 来确定 Wi-Fi 信号强度。由于 netsh.exe 返回的是原始格式的文本,因此需要大量的文本运算符技巧来提取实际的信号强度。通过调用结构化的 API 和对象成员直接访问信息始终是更优的方法。

坦白地说,没有内置的 PowerShell 方法可以以面向对象和结构化的方式访问 Wi-Fi 信息。但是,借助 PowerShell Gallery 中的免费 PowerShell 模块,您可以检索大量有用的 Wi-Fi 信息:

1
Install-Module -Name Get-WLANs -Scope CurrentUser -Force

该模块基本上随附访问任何最新 Windows 操作系统中存在的内置 Windows “Managed Wi-Fi” 框架所需的 C# 代码。

安装该模块后,新命令 Get-WLANs 将返回有关所有可访问的 Wi-Fi 网络的面向对象的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
PS> Get-WLANs

SSID : internetcafe
BSSID : 38:96:ED:0E:31:AD
RSSI : -63
QUALITY : 81
FREQ : 5180
CHANNEL : 36
PHY : VHT
CAPABILITY : 0x1511
IESIZE : 393

SSID : guests
BSSID : 3E:96:ED:0E:31:AD
RSSI : -69
QUALITY : 70
FREQ : 5180
CHANNEL : 36
PHY : VHT
CAPABILITY : 0x1511
IESIZE : 286
(...)

这也包括有关信号强度的信息(在 Quality 属性中)。

PowerShell 技能连载 - 检测 Wi-Fi 信号强度(第 1 部分)

如果您已连接到无线网络,则以下这行代码可提供当前信号强度:

1
2
PS> @(netsh wlan show interfaces) -match '^\s+Signal' -replace '^\s+Signal\s+:\s+',''
80%

信号强度来自 netsh.exe 提供的文本输出。将其包含在 @() 中可确保它始终返回一个数组。然后,-match 运算符使用正则表达式来标识在行首包含单词 “Signal” 的行。后面的 -replace 运算符使用正则表达式删除信号强度之前的文本。

如果您不喜欢正则表达式,则可以使用其他方法来实现,例如:

1
2
PS> (@(netsh wlan show interfaces).Trim() -like 'Signal*').Split(':')[-1].Trim()
80%

这段代码中,将首先修剪 netsh.exe 返回的每一行(删除两端的空白)。接下来,经典的 -like 运算符选择以 “Signal” 开头的行。然后用 “:” 分隔该行,并使用最后一部分(索引为 -1)。再次清除信号强度两端的空白。

如果两个命令均未返回任何内容,请检查您的计算机是否已连接到无线网络。您可能还希望仅使用 netsh.exe 命令的参数来运行它,而没有任何文本运算符来查看命令的原始输出。

PowerShell 技能连载 - Linux 如何保护安全字符串(实际未保护)

当您在非 Windows 系统上的 PowerShell 中将对象序列化为 XML 时,即通过使用 Export-CliXml,所有 SecureString 数据仅被编码,而不被加密。这是根本的区别,也是安全代码一旦移植到非 Windows 操作系统后可能变得不安全的原因。

例如,如果序列化凭据,则结果仅在 Windows 操作系统上是安全的:

1
Get-Credential | Export-Clixml -Path $env:temp\secret.xml

在 XML 文件中,您可以看到 Export-CliXml 如何更改 SecureString 的表示形式并将其转换为十六进制值的列表。在 Windows 上,SecureString 数据已安全加密,并且只有加密数据的人员(并且正在使用该计算机时)才能读取。在 Linux 和 macOS 上并非如此。由于此处缺少 Windows 加密API,因此仅对 SecureString 进行编码而不是加密。

要在非 Windows 操作系统上解码序列化 XML 内容中的纯文本内容,请尝试如下代码:

1
2
3
$secret = '53007500700065007200530065006300720065007400' $bytes = $secret -split '(?<=\G.{2})(?=.)' |ForEach-Object {
[Convert]::ToByte($_, 16)}
$plain = [Text.Encoding]::Unicode.GetString($bytes)$plain

它采用编码字符串,将其分成两对,将十六进制值转换为十进制值,并通过相应的 Unicode 解码器运行结果字节。结果就是原始的密文。

简而言之,请记住,仅在 Windows 操作系统上对序列化的 SecureString 进行安全加密。在 Linux 和 macOS 上,将敏感数据发送到 Export-CliXml 不会对其进行保护。

PowerShell 技能连载 - 快速初始化多个PowerShell控制台

假设您是许多领域的管理员,例如,Azure、SharePoint、SQL、Microsoft 365。对于每种环境,您可能需要运行一些先决条件,登录某些系统并运行一些命令,直到您的 PowerShell 环境准备好为止。

这是一个简单的策略,可以帮助您自动启动不同的PowerShell控制台。在新文件夹中,放置一个具有以下内容的脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# safely serialize a credential
$credPath = "$PSScriptRoot\secret.xml"
$exists = Test-Path -Path $credPath
if (!$exists)
{
$cred = Get-Credential
$cred | Export-Clixml -Path $credPath
}

# define your different environments
$action = @{
'Azure' = "$PSScriptRoot\azure.ps1"
'Teams' = "$PSScriptRoot\teams.ps1"
'Office' = "$PSScriptRoot\office.ps1"
}

# run a new PowerShell for each environment, and run the
# associated "spin-up" script:
$action.Keys | ForEach-Object {
$path = $action[$_]
Start-Process -FilePath powershell -ArgumentList "-noexit -noprofile -executionpolicy bypass -file ""$path"""
}

该示例启动了三个 PowerShell 控制台,并为每个控制台运行一个单独的启动脚本。通过将脚本 azure.ps1,teams.ps1 和 office.ps1 添加到您的文件夹,您现在可以定义初始化和准备每个控制台所需的代码。您还可以通过从任何其他脚本中读取主凭据来使用公共凭据。这是一个例子:

1
2
3
4
# set the console title bar
$host.UI.RawUI.WindowTitle = 'Administering Office'
# read the common credential from file
$cred = Import-Clixml -Path "$PSScriptRoot\secret.xml"

PowerShell 技能连载 - 识别组成员身份

如果您的脚本需要知道当前用户是否是给定组的成员,那么最快且耗费最少资源的方法是使用如下代码:

1
2
3
4
5
6
$token = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$xy = 'S-1-5-64-36'
if ($token.Groups -contains $xy)
{
"You're in this group."
}

当当前用户是由 SID S-1-5-64-36 标识的组的直接或间接成员时,该示例将执行代码(将该 SID 替换为所需的组的 SID)。

这段代码访问用户已经存在并且始终有权访问的访问令牌。无需额外耗时进行 AD 查询,并且嵌套组成员身份也没有问题。访问令牌具有当前用户所属的直接和间接组的完整列表。

所有组均按 SID 列出,这很有意义。再次解析 SID 名称既耗时又毫无意义。如果您只想知道用户是否是组的成员,则只需找出该组的 SID(即使用 Get-AdGroup),然后在上述方法中使用此 SID 即可。

PowerShell 技能连载 - 查找系统路径

有时,脚本需要知道用户桌面或开始菜单等的路径。这些路径可能会有所不同,尤其是在用户使用 OneDrive 时。要找到当前系统路径,请使用以下代码:

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

您可以使用 [System.Environment+SpecialFolder] 类型中定义的所有常量:

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
PS> [Enum]::GetNames([System.Environment+SpecialFolder])
Desktop
Programs
MyDocuments
Personal
Favorites
Startup
Recent
SendTo
StartMenu
MyMusic
MyVideos
DesktopDirectory
MyComputer
NetworkShortcuts
Fonts
Templates
CommonStartMenu
CommonPrograms
CommonStartup
CommonDesktopDirectory
ApplicationData
PrinterShortcuts
LocalApplicationData
InternetCache
Cookies
History

CommonApplicationData
Windows
System
ProgramFiles
MyPictures
UserProfile
SystemX86
ProgramFilesX86
CommonProgramFiles
CommonProgramFilesX86
CommonTemplates
CommonDocuments
CommonAdminTools
AdminTools
CommonMusic
CommonPictures
CommonVideos
Resources
LocalizedResources
CommonOemLinks
CDBurning

如果您知道该路径,并且想知道是否有可以使用的已注册系统路径,请尝试相反的方法并转储所有文件夹常量及其关联的路径:

1
2
3
4
5
6
7
8
9
[Enum]::GetNames([System.Environment+SpecialFolder]) |
ForEach-Object {
# ...for each, create a new object with the constant, the associated path
# and the code required to get that path
[PSCustomObject]@{
Name = $_
Path = [Environment]::GetFolderPath($_)
}
}

结果看起来像这样:

Name                   Path
----                   ----
Desktop                C:\Users\tobia\OneDrive\Desktop
Programs               C:\Users\tobia\AppData\Roaming\Microsoft\Windows\Start Menu\Pr...
MyDocuments            C:\Users\tobia\OneDrive\Dokumente
Personal               C:\Users\tobia\OneDrive\Dokumente
Favorites              C:\Users\tobia\Favorites
Startup                C:\Users\tobia\AppData\Roaming\Microsoft\Windows\Start Menu\Pr...
Recent                 C:\Users\tobia\AppData\Roaming\Microsoft\Windows\Recent
SendTo                 C:\Users\tobia\AppData\Roaming\Microsoft\Windows\SendTo
StartMenu              C:\Users\tobia\AppData\Roaming\Microsoft\Windows\Start Menu
MyMusic                C:\Users\tobia\Music
MyVideos               C:\Users\tobia\Videos
DesktopDirectory       C:\Users\tobia\OneDrive\Desktop
MyComputer
NetworkShortcuts       C:\Users\tobia\AppData\Roaming\Microsoft\Windows\Network Short...
Fonts                  C:\WINDOWS\Fonts
Templates              C:\Users\tobia\AppData\Roaming\Microsoft\Windows\Templates
CommonStartMenu        C:\ProgramData\Microsoft\Windows\Start Menu
CommonPrograms         C:\ProgramData\Microsoft\Windows\Start Menu\Programs
CommonStartup          C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup
CommonDesktopDirectory C:\Users\Public\Desktop
ApplicationData        C:\Users\tobia\AppData\Roaming
PrinterShortcuts       C:\Users\tobia\AppData\Roaming\Microsoft\Windows\Printer Short...
LocalApplicationData   C:\Users\tobia\AppData\Local
InternetCache          C:\Users\tobia\AppData\Local\Microsoft\Windows\INetCache
Cookies                C:\Users\tobia\AppData\Local\Microsoft\Windows\INetCookies
History                C:\Users\tobia\AppData\Local\Microsoft\Windows\History
CommonApplicationData  C:\ProgramData
Windows                C:\WINDOWS
System                 C:\WINDOWS\system32
ProgramFiles           C:\Program Files
MyPictures             C:\Users\tobia\OneDrive\Bilder
UserProfile            C:\Users\tobia
SystemX86              C:\WINDOWS\SysWOW64
ProgramFilesX86        C:\Program Files (x86)
CommonProgramFiles     C:\Program Files\Common Files
CommonProgramFilesX86  C:\Program Files (x86)\Common Files
CommonTemplates        C:\ProgramData\Microsoft\Windows\Templates
CommonDocuments        C:\Users\Public\Documents
CommonAdminTools       C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administr...
AdminTools             C:\Users\tobia\AppData\Roaming\Microsoft\Windows\Start Menu\Pr...
CommonMusic            C:\Users\Public\Music
CommonPictures         C:\Users\Public\Pictures
CommonVideos           C:\Users\Public\Videos
Resources              C:\WINDOWS\resources
LocalizedResources
CommonOemLinks
CDBurning              C:\Users\tobia\AppData\Local\Microsoft\Windows\Burn\Burn   #
PowerShell 技术 QQ 群