PowerShell 技能连载 - 复制命令行历史
适用于 PowerShell 所有版本
要将 PowerShell 会话中键入过的所有 PowerShell 命令保存下来,请试试这行代码:
(Get-History).CommandLine | clip.exe
它将所有的命令拷贝至剪贴板。然后您就可以将它们粘贴到 PowerShell ISE 并保存为文件。
适用于 PowerShell 所有版本
要将 PowerShell 会话中键入过的所有 PowerShell 命令保存下来,请试试这行代码:
(Get-History).CommandLine | clip.exe
它将所有的命令拷贝至剪贴板。然后您就可以将它们粘贴到 PowerShell ISE 并保存为文件。
适用于 PowerShell 所有版本
在前一个技巧里我们演示了如何通过 DELL 的序列号在线检查保修状态。其它厂家也会提供类似的服务。
这段代码可以读取序列号:
$ComputerName = $env:COMPUTERNAME
$serial = (Get-WmiObject -ComputerName $ComputerName -Class Win32_BIOS).SerialNumber
"Your computer serial is $serial"
适用于 PowerShell 2.0 及以上版本
如果您拥有一台 DELL 电脑,您可以通过 Web Service 提交电脑的序列号得到授权信息:
$serial = '36GPL41'
$service = New-WebServiceProxy -Uri http://143.166.84.118/services/assetservice.asmx?WSDL
$guid = [Guid]::NewGuid()
$info = $service.GetAssetInformation($guid,'warrantycheck',$serial)
$info.Entitlements
结果可能看起来如下:
$info.Entitlements
ServiceLevelCode : TS
ServiceLevelDescription : P, ProSupport
Provider : DELL
StartDate : 23.03.2004 00:00:00
EndDate : 23.03.2007 00:00:00
DaysLeft : 0
EntitlementType : Expired
ServiceLevelCode : ND
ServiceLevelDescription : C, NBD ONSITE
Provider : UNY
StartDate : 23.03.2005 00:00:00
EndDate : 23.03.2007 00:00:00
DaysLeft : 0
EntitlementType : Expired
ServiceLevelCode : ND
ServiceLevelDescription : C, NBD ONSITE
Provider : UNY
StartDate : 23.03.2004 00:00:00
EndDate : 24.03.2005 00:00:00
DaysLeft : 0
EntitlementType : Expired
这些从 Web Service 返回的信息还包括了其它有用的信息,例如计算机的系统类型:
PS> $info.AssetHeaderData
ServiceTag : 36GPL41
SystemID : PLX_PNT_CEL_GX270
Buid : 11
Region : Americas
SystemType : OptiPlex
SystemModel : GX270
SystemShipDate : 23.03.2004 07:00:00
适用于 PowerShell 2.0 及以上版本
需要管理 MSI 安装包的朋友可以从这个开源项目中受益:http://psmsi.codeplex.com/。
只需要下载 PowerShell 模块——它自己包含了一个安装包。请确保在安装它之前对 MSI 文件进行解锁。否则,Windows 可能会拒绝安装它。
不幸的是,这个模块将它自己安装到一个很特殊的地方(AppData\Local\Apps...),并且扩展了 $env:PSModulePath
环境变量,所以 PowerShell 可以找到这个模块。这是为什么您在安装完模块之后需要重启 PowerShell 的原因,因为 PowerShell 不能自动感知到 $env:PSModulePath
发生了改变。
这是获取新的 MSI 相关 cmdlet 的方法:
PS> Get-Command -Module MSI
CommandType Name ModuleName
----------- ---- ----------
Function Get-MSIComponentState MSI
Function Get-MSISharedComponentInfo MSI
Function Install-MSIAdvertisedFeature MSI
Cmdlet Add-MSISource MSI
Cmdlet Clear-MSISource MSI
Cmdlet Edit-MSIPackage MSI
Cmdlet Export-MSIPatchXml MSI
Cmdlet Get-MSIComponentInfo MSI
Cmdlet Get-MSIFeatureInfo MSI
Cmdlet Get-MSIFileHash MSI
Cmdlet Get-MSIFileType MSI
Cmdlet Get-MSILoggingPolicy MSI
Cmdlet Get-MSIPatchInfo MSI
Cmdlet Get-MSIPatchSequence MSI
Cmdlet Get-MSIProductInfo MSI
Cmdlet Get-MSIProperty MSI
Cmdlet Get-MSIRelatedProductInfo MSI
Cmdlet Get-MSISource MSI
Cmdlet Get-MSISummaryInfo MSI
Cmdlet Get-MSITable MSI
Cmdlet Install-MSIPatch MSI
Cmdlet Install-MSIProduct MSI
Cmdlet Measure-MSIProduct MSI
Cmdlet Remove-MSILoggingPolicy MSI
Cmdlet Remove-MSISource MSI
Cmdlet Repair-MSIProduct MSI
Cmdlet Set-MSILoggingPolicy MSI
Cmdlet Test-MSIProduct MSI
Cmdlet Uninstall-MSIPatch MSI
Cmdlet Uninstall-MSIProduct MSI
适用于 PowerShell 3.0 及以上版本
有些时候您偶然会见到类似这样的技巧:
$FilePath = "$env:SystemRoot\WindowsUpdate.log"
$ContentsWithLinebreaks = (Get-Content $FilePath) -join "`r`n"
您能否出猜出它的用意?Get-Content
缺省情况下返回由一行一行组成的字符串数组,然后 -join
操作符将该数组转化为一个字符串。
从 PowerShell 3.0 开始,Get-Content
多了一个参数:-Raw
。它比起刚才的方法高效的多,并且可以得到相同的结果:
$FilePath = "$env:SystemRoot\WindowsUpdate.log"
$ContentsWithLinebreaks = (Get-Content $FilePath) -join "`r`n"
$ContentsWithLinebreaks2 = Get-Content $FilePath -Raw
$ContentsWithLinebreaks -eq $ContentsWithLinebreaks2
当您使用这段代码时,会发现 $ontentWithLinebreaks
和 $ContentWithLinebreaks2
是不同的。唯一的区别是在 $ContentsWithLinebreaks2
尾部有一个换行符:
PS> $ContentsWithLinebreaks -eq $ContentsWithLinebreaks2.TrimEnd("`r`n")
True
PS>
适用于 PowerShell 4.0 及以上版本
如果您知道某个脚本需要管理员权限,只需要一个简单的 #requres
语句就可以确保符合该需求的才可以运行:
#requires -version 4.0
#requires –runasadministrator
'I am Admin!'
如果这个脚本没有使用管理员身份运行,它将显示一个有意义错误提示信息,说明它为何无法运行。
实际上,在这个例子中您可以看到两条 #requires
语句。第一条确保该脚本至少运行在 PowerShell 4.0 以上的环境中,这是第二条 #requires
的先决条件。它是由 PowerShell 4.0 引入的,不支持 PowerShell 更低的版本。
所以最好不要在 PowerShell 3.0 或更早的环境中使用这个技术。在那些环境中,您还是需要手工确认脚本是否拥有管理员权限。
1 | function foo() { |
这种写法和 C 语言中定义一个函数的写法差不多。
1 | var bar = function() { |
例子中变量 bar
指向一个匿名函数。由于这是一个赋值语句,所以应该以 ;
结尾。虽然分号可以省略。
1 | var bar = function foo() { |
此处的 foo
可以省略,不会影响代码逻辑。但是加上 foo
在调试工具中查看调用堆栈时,可以更清晰地看到函数的名称。所以这是一个推荐的实践。
1 | (function() { |
还有一种变体:
1 | (function() { |
请注意上述两种写法的圆括号的位置区别。前一种写法是 JSLint 推荐的写法,所以推荐采用第一种写法。
这种模式本质上只是一个函数表达式(无论是命名或匿名的),该函数会在创建后立刻执行。以下是用命名函数来实现 IIFE 的例子:
1 | (function foo() { |
代码中用 foo
作为 IIFE 的名字。
这种模式是非常有用的,因为它为初始化代码提供了一个作用于沙箱(sandbox)。代码中的 bar
变量此时会成为一个局部变量,不会污染全局的 window
(global
) 对象。
适用于 Windows 8.1 或 Server 2012 R2
Windows 8.1 和 Server 2012 R2 引入了一个名为“PrintManagement”的模块。它包含了管理本地和远程打印机所需的所有 cmdlet。
在前一个技能中我们演示了如何读取打印任务。每个打印任务都有一个 JobStatus
属性告诉您该 PrintJob
是否成功完成。
可以通过这种方式获取所有的状态码:
PS> Import-Module PrintManagement
PS> [Microsoft.PowerShell.Cmdletization.GeneratedTypes.PrintJob.JobStatus]::GetNames([Microsoft.PowerShell.Cmdletization.GeneratedTypes.PrintJob.JobStatus])
Normal
Paused
Error
Deleting
Spooling
Printing
Offline
PaperOut
Printed
Deleted
Blocked
UserIntervention
Restarted
Complete
Retained
RenderingLocally
接下来,您可以过滤已有的打印任务。并且,比如打印出所有已完成或有错误的打印任务。这段代码将列出所有有错误或已完成的打印任务:
$ComputerName = $env:COMPUTERNAME
Get-Printer -ComputerName $ComputerName | ForEach-Object {
Get-PrintJob -PrinterName $_.Name -ComputerName $ComputerName |
Where-Object { $_.JobStatus -eq 'Complete' -or $_.JobStatus -eq 'Error' -or $_.JobStatus -eq 'Printed'}
}
要移除这些打印任务,只需要加上 Remove-PrintJob
命令:
$ComputerName = $env:COMPUTERNAME
Get-Printer -ComputerName $ComputerName | ForEach-Object {
Get-PrintJob -PrinterName $_.Name -ComputerName $ComputerName |
Where-Object { $_.JobStatus -eq 'Complete' -or $_.JobStatus -eq 'Error' -or $_.JobStatus -eq 'Printed'}
} |
Remove-PrintJob -CimSession $ComputerName
中文版:
README-zh-cn.md
本repo由支付宝前端开发工程师 @莫登(新浪微博@郭宇)维护,部分案例包括Angular在 支付宝某些系统上的使用经验