PowerShell 技能连载 - 远程读取配置表(第 1 部分)
如果您无法使用 PowerShell 远程处理,那么您需要通过 DCOM 从另一个系统中读取注册表值,以下是一些您可能希望试验的示例代码:
1 | $ComputerName = 'pc01' |
只需要做一些小改动,该代码就能返回一个 AD 使用的列表
这段示例代码需要:
- 您有目标机器的本地管理员特权
RemoteRegistry
服务在对方机器上运行- 对方机器的本地防火墙启用了“远程管理例外”
如果您无法使用 PowerShell 远程处理,那么您需要通过 DCOM 从另一个系统中读取注册表值,以下是一些您可能希望试验的示例代码:
1 | $ComputerName = 'pc01' |
只需要做一些小改动,该代码就能返回一个 AD 使用的列表
这段示例代码需要:
RemoteRegistry
服务在对方机器上运行当您启用了 ScriptBlockLogging
后,PowerShell 将会记录所有在您机器上执行的所有 PowerShell 代码。如果没有启用它,所有安全相关的代码仍然会记录。这样很不错。然而,该任何用户都可以读取该日志,所以任何人都可以类似这样浏览记录下的代码:
1 | Get-WinEvent -FilterHashtable @{ ProviderName="Microsoft-Windows-PowerShell"; Id = 4104 } |
To harden security and limit the access to the log file, you have two choices:
要强化安全并限制日志文件的读取,您有两个选择:
1 | #requires -RunAsAdministrator |
当您运行该脚本时,读取 PowerShell 操作日志的权限被限制为只有本地管理员。
读写注册表的 HKEY_LOCAL_USER
十分容易,因为这个配置单元对于所有用户都一致。那么如何读写其他用户的 HKEY_CURRENT_USER
配置单元?
假设您是管理员并且希望为其他用户的 HKEY_CURRENT_USER
配置单元添加注册表值。
首先您需要挂载该用户的用户配置单元。该配置单元位于该用户的用户配置文件下的 NTUSER.DAT
文件中。作为一个管理员,您需要先运行以下 PowerShell 代码来挂载 UserTobias 用户的用户配置文件:
1 | PS C:\> REG LOAD HKEY_Users\UserTobias "C:\Users\Tobias\NTUSER.DAT" |
该用户配置单元将挂载在 HKEY_USERS
下名为 UserTobias
的注册表键中,而且 PowerShell 可以类似这样存取该路径:
1 | PS C:\> Get-ChildItem -Path Registry::HKEY_USERS\UserTobias |
现在要读取甚至写入该指定用户的配置单元十分容易。以下代码将创建一个新的注册表键:
1 | PS C:\> $null = New-Item -Path Registry::HKEY_USERS\UserTobias\Software\Microsoft\Windows\CurrentVersion\Test |
以下是如何读取/写入一个值:
1 | PS C:\> Get-ItemProperty -Path Registry::HKEY_USERS\UserTobias\Software\Microsoft\OneDrive |
当您操作完 HKEY_USERS
注册表配置单元之后,别忘了卸载它:
1 | PS C:\> $null = REG UNLOAD HKEY_Users\UserTobias |
请注意这条命令将会抛出一个 “Access Denied” 错误,如果您没有管理员特权,或者该注册表配置单元正在被其他人使用。例如,如果您启动了 regedit.exe,当该用户配置单元加载以后,regedit.exe 可以显示加载的用户配置单元,而当 regedit 处于打开状态时,该配置单元被锁定并且无法关闭。
在 Windows 10 中,不像 Windows Server,您无法使用 Get-WindowsFeature
和 Add-WindowsFeature
cmdlet 来管理 Windows 功能。
然而,对于客户端来说,有一个很类似的 cmdlet 可用:Enable-WindowsOptionalFeature
。以下代码将添加 PowerShell Hyper-V cmdlet 和 Hyper-V 功能:
1 | Enable-WindowsOptionalFeature -Online -All -FeatureName Microsoft-Hyper-V-Management-PowerShell -NoRestart |
执行的结果是一个对象,告知您是否需要重启。
请注意 -All
参数:如果您忽略了该参数,那么您需要自行确保所有先决条件和依赖项都已安装好,才能添加另一个新项。如果您懒,或者不了解依赖项,那么 -All
参数将自动为您安装所有必须的依赖项。
Windows 10 带来一系列功能,但默认只安装了一个子集。您可以手工打开控制面板查看 Windows 功能。有经验的管理员也会使用 dism.exe
命令行工具。
在 PowerShell 中,您可以通过 Get-WindowsOptionalFeature
查看 Windows 功能的状态。当您指定了 -Online
参数,该 cmdlet 将返回当前可用的功能和它们的状态。
使用 Where-Object
命令,您可以容易地过滤结果,并且例如只显示未安装的功能清单:
1 | # list all Windows features and their state |
PowerShell 默认情况下不支持原生的 cmd.exe 命令,例如 “dir
“。替代的是,它使用历史别名 “dir
“ 指向最接近的 PowerShell cmdlet:
1 | PS C:\> Get-Command -Name dir | ft -AutoSize |
这解释了为什么 PowerShell 中的 “dir
“ 不支持 cmd.exe 以及批处理文件中的开关和参数,例如 “cmd.exe/w
“。
如果您必须使用 cmd 形式的命令,请用 /c
参数(代表 “command”)启动一个原生的 cmd.exe,执行这条命令,并在 PowerShell 内处理执行结果。这个例子运行 cmd.exe /c
,然后以参数 /w
运行旧的 “dir
“ 命令:
1 | PS C:\> cmd.exe /c dir /w |
一个更安全的方法是使用 “--%
“ 操作符:
1 | PS C:\> cmd.exe --% /c dir /w |
当在参数之前添加了它之后,PowerShell 解释器将不会对参数进行处理,这样您甚至可以像在 cmd.exe 中一样使用环境变量注解。副作用是:您在参数中不再能使用 PowerShell 技术,比如变量:
1 | PS C:\> cmd.exe --% /c dir %WINDIR% /w |
Invoke-WebRequest
可以从网页获取 HTML 信息,并且可以用正则表达式来提取这些页面中的信息。
以下是一些可以获取英文的借口的代码:
1 | $ProgressPreference = 'SilentlyContinue' |
以下代码将获取英语和德语混合的借口:
1 | $page= Invoke-WebRequest "http://www.netzmafia.de/cgi-bin/bofhserver.cgi" |
当使用双引号字符串时,您可以扩展它们当中的变量,类似这样:
1 | PS C:\> "Windir: $env:windir" |
然而,没有明显的方法来标记变量的起止位置,所以以下操作将会失败:
1 | PS C:\> "$env:windir: this is my Windows folder" |
解决方案是使用大括号来标识字符串内变量的起止位置:
1 | PS C:\> "${env:windir}: this is my Windows folder" |
当运行 winver.exe
时,您可以方便地获取到完整的 Windows 生成号。通过 PowerShell 读取生成号并不是那么明显。并没有内置的 cmdlet。
不过,要创建这样功能的函数很简单:
1 | function Get-OSInfo |
结果看起来类似这样:
1 | PS C:\> Get-OSInfo |
如果想知道某个特定的设备是否连接到您的计算机上,您可以使用 WMI 来提取所有即插即用设备的名称:
1 | Get-WmiObject -Class Win32_PnpEntity | |