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 或更早的环境中使用这个技术。在那些环境中,您还是需要手工确认脚本是否拥有管理员权限。
适用于 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
适用于 Windows 8.1 或 Server 2012 R2
Windows 8.1 和 Server 2012 R2 引入了一个名为“PrintManagement”的模块。它包含了管理本地和远程打印机所需的所有 cmdlet。
要列出指定计算机的所有打印任务,首先确定可用的打印机,然后用循环取出每个打印机的打印任务。这实际做起来十分简单:
$ComputerName = $env:COMPUTERNAME
Get-Printer -ComputerName $ComputerName | ForEach-Object {
Get-PrintJob -PrinterName $_.Name -ComputerName $ComputerName
}
如果该代码返回空,那么说明没有打印任务(或者您没有读取它们的权限)。
适用于 Windows 8.1 或 Server 2012 R2
要更新远程计算机上的组策略设置,请使用 Invoke-GPUpdate
,并且传入希望更新设置的计算机名。
Invoke-GPUpdate
在远程计算机上创建“gpupdate
”计划任务。您可以使用 –RandomDelayInMinutes
指定一个 0 至 44640 分钟(31 天)之间的值。该 cmdlet 将使用一个随机的时间因子来避免网络阻塞。
适用于 Windows 8.1 和 Server 2012 R2
Windows 8.1 和 Server 2012 R2 带来了一个叫做“PrintManagement”的模块。它包含了管理本地和远程打印机所需的所有 Cmdlet。
以下是一个示例脚本,演示了安装打印机驱动、设置打印机端口、安装打印机、共享该打印机,以及设置某些打印机属性的过程。
$ComputerName = $env:COMPUTERNAME
$DriverName = 'Samsung SCX-483x 5x3x Series XPS'
$IPAddress = '192.168.2.107'
$PortName = 'NetworkPrint_192.168.2.107'
$PrinterName = 'BWPrint'
$ShareName = 'Office 12'
Add-PrinterDriver -ComputerName $ComputerName -Name $DriverName
Add-PrinterPort -Name $PortName -ComputerName $ComputerName
Add-Printer -ComputerName $ComputerName -Name $PrinterName -DriverName $DriverName -Shared -ShareName $ShareName -PortName $PortName
Set-PrintConfiguration -ComputerName $ComputerName -PrinterName $PrinterName -PaperSize A4
要使用它,请确保您修改了 $IPAddress
并指向一个存在的打印机。请将 $ComputerName
修改指向一个远程计算机而不是您的本地计算机。
要列出 PrintManagement
模块所带的所有 Cmdlet,请试试以下代码:
PS> Get-Command -Module PrintManagement
CommandType Name ModuleName
----------- ---- ----------
Function Add-Printer PrintManagement
Function Add-PrinterDriver PrintManagement
Function Add-PrinterPort PrintManagement
Function Get-PrintConfiguration PrintManagement
Function Get-Printer PrintManagement
Function Get-PrinterDriver PrintManagement
Function Get-PrinterPort PrintManagement
Function Get-PrinterProperty PrintManagement
Function Get-PrintJob PrintManagement
Function Read-PrinterNfcTag PrintManagement
Function Remove-Printer PrintManagement
Function Remove-PrinterDriver PrintManagement
Function Remove-PrinterPort PrintManagement
Function Remove-PrintJob PrintManagement
Function Rename-Printer PrintManagement
Function Restart-PrintJob PrintManagement
Function Resume-PrintJob PrintManagement
Function Set-PrintConfiguration PrintManagement
Function Set-Printer PrintManagement
Function Set-PrinterProperty PrintManagement
Function Suspend-PrintJob PrintManagement
Function Write-PrinterNfcTag PrintManagement
如您所见,它们实际上是 PowerShell 函数而不是二进制 Cmdlet。