PowerShell 技能连载 - 键盘技巧
在 PowerShell ISE 4.0 控制台窗格中,按住 CTRL
键,然后按 向上
键,可以将光标从命令行中移到结果区域中。
在 PowerShell ISE 4.0 控制台窗格中,按住 CTRL
键,然后按 向上
键,可以将光标从命令行中移到结果区域中。
LDAP 查询的功能非常强大,可以帮助查找缺少信息的账户。
这段代码将返回所有带邮箱地址的 Active Directory 用户:
$searcher = [ADSISearcher]"(&(sAMAccountType=$(0x30000000))(mail=*))"
$searcher.FindAll() |
ForEach-Object { $_.GetDirectoryEntry() } |
Select-Object -Property sAMAccountName, name, mail
如果您想查询相反的内容,请通过“!
”号进行相反的查询。以下代码可以返回所有缺少邮箱地址的 Active Directory 用户:
$searcher = [ADSISearcher]"(&(sAMAccountType=$(0x30000000))(!(mail=*)))"
$searcher.FindAll() |
ForEach-Object { $_.GetDirectoryEntry() } |
Select-Object -Property sAMAccountName, name, mail
只要两行命令,就可以“轻松”地获取实时天气预报:
(curl http://61.4.185.48:81/g/ -UseBasicParsing).Content -cmatch 'var id=(\d+);' | Out-Null
irm "http://www.weather.com.cn/data/sk/$($matches[1]).html" | select -exp weatherinfo
使用效果:
PS >(curl http://61.4.185.48:81/g/ -UseBasicParsing).Content -cmatch 'var id=(\d+);' | Out-Null
PS >irm "http://www.weather.com.cn/data/sk/$($matches[1]).html" | select -exp weatherinfo
city : 福州
cityid : 101230101
temp : 15
WD : 北风
WS : 2级
SD : 79%
WSE : 2
time : 10:20
isRadar : 1
Radar : JC_RADAR_AZ9591_JB
您还可以把第二行改为以下形式,获取更猛的数据:
irm "http://m.weather.com.cn/data/$($matches[1]).html" | select -exp weatherinfo
或:
irm "http://www.weather.com.cn/data/cityinfo/$($matches[1]).html" | select -exp weatherinfo
顺便透露一下,高富帅一般不这么看天气预报哦!
编号 | 发布时间 | 标题 | |
---|---|---|---|
Vol.01 | 2013年06月 | 文件系统任务 | 下载 |
Vol.02 | 2013年07月 | 数组和哈希表 | 下载 |
Vol.03 | 2013年08月 | 日期、时间和文化 | 下载 |
Vol.04 | 2013年09月 | 对象和类型 | 下载 |
Vol.05 | 2013年10月 | WMI | 下载 |
Vol.06 | 2013年11月 | 正则表达式 | 下载 |
Vol.07 | 2013年12月 | 函数 | 下载 |
Vol.08 | 2013年12月 | 静态 .NET 方法 | 下载 |
Vol.09 | 2014年01月 | 注册表 | 下载 |
Vol.10 | 2014年02月 | Internet 相关任务 | 下载 |
Vol.11 | 2014年03月 | XML 相关任务 | 下载 |
Vol.12 | 2014年08月 | 安全相关任务 | 下载 |
如果您(和我一样)足够懒,也可以用这样一行 PowerShell 代码来下载:
1..12 | ForEach-Object { Invoke-WebRequest "http://powershell.com/cs/PowerTips_Monthly_Volume_$_.pdf" -OutFile "PowerTips_Monthly_Volume_$_.pdf" }
译者注:您没有看错!这是近期最邪恶的一个技巧,文末有译者机器上的实验效果。
厌倦了每次自己想蹩脚的借口?以下脚本能让您每调用一次 Get-Excuse
就得到一个新的接口!您所需的一切只是 Internet 连接:
function Get-Excuse
{
$url = 'http://pages.cs.wisc.edu/~ballard/bofh/bofhserver.pl'
$ProgressPreference = 'SilentlyContinue'
$page = Invoke-WebRequest -Uri $url -UseBasicParsing
$pattern = '<br><font size = "\+2">(.+)'
if ($page.Content -match $pattern)
{
$matches[1]
}
}
如果您需要通过代理服务器或者身份认证来访问 Internet,那么请查看函数中 Invoke-WebRequest
的参数。您可以通过它提交代理服务器信息,例如身份验证信息。
译者注:以下是
Get-Excuse
为笔者找的“借口”,很有创意吧 ;-)
PS >Get-Excuse
your process is not ISO 9000 compliant
PS >Get-Excuse
evil hackers from Serbia.
PS >Get-Excuse
piezo-electric interference
PS >Get-Excuse
Bogon emissions
PS >Get-Excuse
because Bill Gates is a Jehovah's witness and so nothing can work on St. Swithin's day.
PS >Get-Excuse
Your cat tried to eat the mouse.
PS >Get-Excuse
It works the way the Wang did, what's the problem
PS >Get-Excuse
Telecommunications is upgrading.
PS >Get-Excuse
Your computer's union contract is set to expire at midnight.
PS >Get-Excuse
Daemon escaped from pentagram
PS >Get-Excuse
nesting roaches shorted out the ether cable
PS >Get-Excuse
We ran out of dial tone and we're and waiting for the phone company to deliver another bottle.
PS >Get-Excuse
Root nameservers are out of sync
PowerShell 保存了您键入的所有命令列表,但是当您关闭 PowerShell 时,这个列表就丢失了。
以下是一个保存当前命令历史到文件的单行代码:
Get-History | Export-Clixml $env:temp\myHistory.xml
当您启动一个新的 PowerShell 控制台或 ISE 编辑器实例时,您可以将保存的历史读入 PowerShell:
Import-Clixml $env:\temp\myHistory.xml | Add-History
不过,加载历史并不会影响键盘缓冲区,所以按下上下键并不会显示新导入的历史条目。然而,您可以用 TAB 自动完成功能来查找您之前输入的命令:
#(KEYWORD) <-现在按下(TAB)键!
PowerShell 使我们拥有了一门非常强大的脚本语言。许多产品,例如 SharePoint 以 Cmdlet 的形式提供了它们自己的管理扩展。
客户们喜欢脚本语言,是因为它使他们能够编写自己的代码而不需要运行某个编译器,也不需要将可执行程序拷贝到它们的目标计算机中。相对于部署一个脚本,在那些目标计算机中运行一个可执行程序或者在命令行 Shell 中执行一些命令通常需要更复杂的审批过程。
但是从另一方面来说,编写 PowerShell 脚本需要学习一门新的脚本语言并且需要使用他们所熟悉范围之外的工具。作为一个开发者,我喜欢 C# 和 Visual Studio 的智能提示等强大功能。并且,在过去几年内,我用 C# 开发了许多工具——并且我不希望在移植到 PowerShell 的过程中丢弃这些设计好的轮子。
所以如果能在 PowerShell 中复用现有的 C# 代码,而不需要将它以 Cmdlet的形式实现的话,那就十分理想了。
实际上 PowerShell 2.0 提供了一种方式来实现它:使用 Add-Type
Cmdlet,它能够通过您提供的 C# 源代码在内存中生成一个新的 .NET 程序集,并且可以将该程序集直接用于同一个会话中的 PowerShell 脚本中。
出于演示的目的,我们假设已有以下简单的 C# 代码,作用是获取和设置 SharePoint 中的 Content Deployment 的 RemoteTimeout
值:
using Microsoft.SharePoint.Publishing.Administration;
using System;
namespace StefanG.Tools
{
public static class CDRemoteTimeout
{
public static void Get()
{
ContentDeploymentConfiguration cdconfig = ContentDeploymentConfiguration.GetInstance();
Console.WriteLine("Remote Timeout: "+cdconfig.RemoteTimeout);
}
public static void Set(int seconds)
{
ContentDeploymentConfiguration cdconfig = ContentDeploymentConfiguration.GetInstance();
cdconfig.RemoteTimeout = seconds;
cdconfig.Update();
}
}
}
除了引用 .NET 框架之外,这个工具还引用了两个 SharePoint DLL(Microsoft.SharePoint.dll 和 Microsoft.SharePoint.Publishing.dll),它们用来存取 SharePoint 的对象模型。为了确保 PowerShell 能正确地生成程序集,我们需要为 Add-Type
Cmdlet 用 -ReferencedAssemblies
参数提供引用信息。
为了指定源代码的语言(可以使用 CSharp
、CSharpVersion3
、Visual Basic
和 JScript
),您需要使用 -Language
参数。缺省值是 CSharp
。
在我的系统中我有一个 csharptemplate.ps1[csharptemplate.ps1] 文件,我可以快速地复制和修改成我需要的样子来运行我的 C# 代码:
$Assem = (
...add referenced assemblies here...
)
$Source = @"
...add C# source code here...
"@
Add-Type -ReferencedAssemblies $Assem -TypeDefinition $Source -Language CSharp
对于上述的 C# 例子,对应的最终 PowerShell 脚本如下:
$Assem = (
"Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" ,
"Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
)
$Source = @"
using Microsoft.SharePoint.Publishing.Administration;
using System;
namespace StefanG.Tools
{
public static class CDRemoteTimeout
{
public static void Get()
{
ContentDeploymentConfiguration cdconfig = ContentDeploymentConfiguration.GetInstance();
Console.WriteLine("Remote Timeout: "+cdconfig.RemoteTimeout);
}
public static void Set(int seconds)
{
ContentDeploymentConfiguration cdconfig = ContentDeploymentConfiguration.GetInstance();
cdconfig.RemoteTimeout = seconds;
cdconfig.Update();
}
}
}
"@
Add-Type -ReferencedAssemblies $Assem -TypeDefinition $Source -Language CSharp
[StefanG.Tools.CDRemoteTimeout]::Get()
[StefanG.Tools.CDRemoteTimeout]::Set(600)
上述例子的最后几行演示了如何在 PowerShell 中调用 C# 方法。
注:文中涉及到的 csharptemplate.ps1 可以在这里[下载][csharptemplate.ps1]。
[csharptemplate.ps1]: /assets/download/csharptemplate.ps1
要正确地将单词首字母转换为大写,您可以用正则表达式或者一点系统函数:
用正则表达式的话,您可以这样做:
$sentence = 'here is some text where i would like the first letter to be capitalized.'
$pattern = '\b(\w)'
[RegEx]::Replace($sentence, $pattern, { param($x) $x.Value.ToUpper() })
用系统函数的话,这样做可以达到相同的效果:
$sentence = 'here is some text where i would like the first letter to be capitalized.'
(Get-Culture).TextInfo.ToTitleCase($sentence)
正则表达式稍微复杂一点,但是功能更多。例如如果出于某种古怪的原因,您需要将每个单词的首字母替换为它的 ASCII 码,那么正则表达式可以轻松地实现:
$sentence = 'here is some text where i would like the first letter to be capitalized.'
$pattern = '\b(\w)'
[RegEx]::Replace($sentence, $pattern, { param($x) [Byte][Char]$x.Value })
PowerShell 可以操作 COM 对象,例如 Outlook 应用程序。以下简单的两行代码能返回当前的 Outlook 配置文件名:
$outlookApplication = New-Object -ComObject Outlook.Application
$outlookApplication.Application.DefaultProfileName
从 PowerShell 4.0 开始,方法名可以是一个变量。以下是一个简单的例子:
$method = 'ToUpper'
'Hello'.$method()
当您需要调用的方法须通过一段脚本计算得到的时候,这个特性十分有用。
function Convert-Text
{
param
(
[Parameter(Mandatory)]
$Text,
[Switch]$ToUpper
)
if ($ToUpper)
{
$method = 'ToUpper'
}
else
{
$method = 'ToLower'
}
$text.$method()
}
以下是用户调用该函数的方法:
PS> Convert-Text 'Hello'
hello
PS> Convert-Text 'Hello' -ToUpper
HELLO
缺省情况下,该函数将文本转换为小写。当指定了开关参数 -ToUpper
时,函数将文本转换为大写。由于动态方法特性的支持,该函数不需要为此写两遍代码。
译者注:在旧版本的 PowerShell 中,您可以通过 .NET 方法(而不是脚本方法)中的反射来实现相同的目的。虽然它不那么整洁,但它能运行在 PowerShell 4.0 以下的环境:
function Convert-Text
{
param
(
[Parameter(Mandatory)]
$Text,
[Switch]$ToUpper
)
if ($ToUpper)
{
$method = 'ToUpper'
}
else
{
$method = 'ToLower'
}
$methodInfo = $Text.GetType().GetMethod($method, [type[]]@())
$methodInfo.Invoke($Text, $null)
}