PowerShell 技能连载 - 查找 Windows 的产品密钥
当您需要从备份中还原电脑状态时,首先要知道您的 Windows 产品密钥。以下是一个简单的单行命令,可以获得产品密钥信息:
1 | (Get-WmiObject -Class SoftwareLicensingService).OA3xOriginalProductKey |
当您需要从备份中还原电脑状态时,首先要知道您的 Windows 产品密钥。以下是一个简单的单行命令,可以获得产品密钥信息:
1 | (Get-WmiObject -Class SoftwareLicensingService).OA3xOriginalProductKey |
在前一个技能中我们谈到一个名为“PSCredentialManager”的公共模块,可以用来管理缓存的凭据。有些时候,少即是多。当您阅读它的代码时,会发现它是通过一个名为 cmdkey.exe 的控制台命令在和 windows 系统打交道。
要获取您本机缓存的凭据,您只需要这样:
1 | PS> cmdkey /list |
它输出的是纯文本。然而,PowerShell 可以用 ForEach-Object
处理原始数据:
1 | cmdkey.exe /list | ForEach-Object {$found=$false} { |
结果类似这样:
Type User Info Target
---- ---- ---- ------
Domain Extended Credentials tabcabcabc@hicsawr.com Saved for this logon only Mi
Domain Extended Credentials 02jbqxcbqvsb Saved for this logon only Mi
Generic tabcabcabc@hicsawr.com Local machine persistence Le
Generic Local machine persistence Le
Generic Local machine persistence Le
Generic Local machine persistence Le
Generic tabcabcabc@hicsawr.com Local machine persistence Le
Generic Local machine persistence Le
Generic 02jdrxcbqvsb Local machine persistence Wi
Generic Martin Le
Domain Password Martin Do
Domain Password Martin Do
Domain Password User Do
公共的 PowerShell Gallery (www.powershellgallery.com) 是一个 PowerShell 脚本作者们可以自由地交换脚本和模块的地方。您所需要的只是包含 PowerShellGet 的 PowerShell 5,它带了操作 Gallery 需要的 cmdlet。
当然,您需要自己确认代码,确保它可以完美运行,并且没有安全问题。
有一个模块叫做“PSCredentialManager”。以下是如何查看这个模块信息的方法:
1 | PS> Find-Module -Name PSCredentialManager | Select-Object -Property * |
要安装这个模块,请运行以下代码:
1 | PS> Install-Module -Name PSCredentialManager -Scope CurrentUser -RequiredVersion 0.6 |
请注意我们显式地要求安装 0.6 版。在写这篇文章的时候,还有个 1.0.1 版,但存在一些问题。当您从一个公开的地方,例如 PowerShell Gallery 中获取内容,随时有可能得到非预期的结果,请留意。
如果您希望在安装一个模块前检查它的代码,可以使用 Save-Module
,将模块下载到一个隔离的地方。
1 | PS> Find-Module pscredentialmanager -AllVersions |
安装完成后,以下命令可以返回一个新 cmdlet 的列表:
1 | PS> Get-Command -Module pscredentialmanager |
您现在可以管理缓存的凭据。例如要返回一个缓存的凭据列表,请试试以下代码:
1 | PS> Get-CachedCredential |
如果您想看看新的 cmdlet(也叫函数)如何工作,您还可以阅读它的源码。这行代码将函数的源码复制到剪贴板:
1 | PS> ${function:Get-CachedCredential} | clip |
要弃用这个模块,只需要卸载它:
1 | PS> Uninstall-Module -Name pscredentialmanager -AllVersions |
Measure-Object
也可以计算属性值的总和。它可以用来计算文件夹大小。以下代码计算用户配置文件(可能需要一些时间,视找到的文件数量而定)。它只是将所有文件的“Length”属性相加:
1 | $size = (Get-ChildItem -Path $home -Force -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum |
输出的结果类似如下:
Folder Size: 172945767402 Bytes
Folder Size: 164.933,94 MB
您可为 Get-ChildItem
添加更多的参数,显式地控制哪些文件参加统计。例如这段代码添加了 -Filter
参数,并指定文件的扩展名,来只统计用户配置文件目录中找到的 PowerShell 脚本文件的大小。
1 | $size = (Get-ChildItem -Path $home -Filter *.ps1 -Force -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum |
在前一个技能中我们学习了如何有效地统计一个文件夹中项目的数量。以下是更多的例子。
用 PowerShell 统计指定文件夹中文件的数量易如反掌:
1 | $count = Get-ChildItem -Path "$home\Desktop" -Force | |
只需要调整 Get-ChildItem
的参数就可以找到更多。例如添加 -Recurse
开关,就可以包括子文件夹中的文件:
1 | $count = Get-ChildItem -Path "$home\Desktop" -Force -Recurse -ErrorAction SilentlyContinue | |
或者,只关注某些文件。这个例子只统计两层目录深度以内的 log 和 txt 文件:
1 | $count = Get-ChildItem -Path $env:windir -Force -Recurse -Include *.log, *.txt -ErrorAction SilentlyContinue -Depth 2 | |
(请注意:-Depth
参数是 PowerShell 5 引入的)
一个快速但浪费的统计文件数量的方法如下:
1 | (Get-ChildItem -Path c:\windows).Count |
但是,这将产生一些内存负担,因为在 Count
属性能够获取对象数量之前,所有文件将会堆在内存里。当进行递归搜索时,这种情况更严重。
一个节约非常多资源的方法是类似这样使用 Measure-Object
:
1 | (Get-ChildItem -Path c:\windows | Measure-Object).Count |
这里使用流来获取项目的数量,所以 PowerShell 不需要在内存中存储所有文件。
URL 缩短功能对于 Twitter 消息十分有用,但是隐藏了真实地址。您是否真的信任 http://bit.ly/e0Mw9w 呢?
以下是一个简单的方法,帮您还原缩短后的 URL 指向的真实地址:
1 | $shortUrl = "http://bit.ly/e0Mw9w" |
如您所见,这个例子中缩短的 URL 指向的是 Lee Holmes 的博客:http://www.leeholmes.com/projects/ps_html5/Invoke-PSHtml5.ps1 。Lee Holmes 是一个 PowerShell 团队成员,如果您信任他,那么可以好奇地运行他著名的代码片段:
1 | iex (New-Object Net.WebClient).DownloadString("http://bit.ly/e0Mw9w") |
这是一个能说明 Invoke-Expression
别名为“iex”有危险的很好例子。
在前一个技能中我们介绍了如何用 Invoke-WebRequest
来获取天气预报数据。获取到的数据是纯黑白的文本。
要获取彩色的报告,Windows 10 可以利用 powershell.exe 的控制序列特性。只需要在 PowerShell 控制台中运行以下代码:
1 | $City = 'Hannover' |
只需要将 user agent 设为“curl”,Windows 10 powershell.exe 就能收到包含色彩控制序列的输出。
Invoke-WebRequest
可以轻松地获得网页内容。如果不指定 –UseBasicParsing
参数,HTML 内容会被解析成 Internet Explorer DOM。通过这种方法,PowerShell 只需要几行代码就可以获取世界上大多数城市当前的天气预报:
1 | $City = 'New York' |
要注意一些事情:
Out-GridView
只能显示有限行的文本。要查看完整的报告,请将 $text
输出到控制台。Invoke-WebRequest
需要内置的 Windows 浏览器运行和初始化至少一次您是否使用 Read-Host
来接受用户的输入?如果您是这么做的,请重新考虑一下。Read-Host
总是提示用户,并且用了 Read-Host
就无法自动化运行脚本:
1 | $City = Read-Host -Prompt 'Enter City' |
一个更好的简单方法是这样:
1 | param |
它创建了一个必选参数。如果用户没有提供传输这个实参,那么会创建一个提示,效果类似 Read-Host。但是,用户始终可以传入这个脚本的参数并使脚本自动化运行。只需要确保只有一个 param()
语句,并且必须放在脚本的开始处。逗号来分隔多个参数。
如果您不喜欢 param()
创建的提示,那么可以用这种方法:
1 | param |
这样,您可以完全控制提示的内容,并且用户又可以通过实参传入参数,并且无人值守运行脚本。