PowerShell 技能连载 - 在 PowerShell ISE 中创建干净的测试环境
当您在 PowerShell ISE 编辑器中开发 PowerShell 脚本时,您需要在一个干净的环境中运行最终的测试,确保不会被之前运行时残留的变量或者函数干扰。
创建一个干净的测试环境的最简单方法是:选择文件菜单,然后选择“新建 PowerShell 选项卡”。这将为您带来一个新的标签页,并且该页代表一个全新的 PowerShell 宿主。完美的测试环境!
PowerShell 技能连载 - 在 PowerShell ISE 中创建干净的测试环境
当您在 PowerShell ISE 编辑器中开发 PowerShell 脚本时,您需要在一个干净的环境中运行最终的测试,确保不会被之前运行时残留的变量或者函数干扰。
创建一个干净的测试环境的最简单方法是:选择文件菜单,然后选择“新建 PowerShell 选项卡”。这将为您带来一个新的标签页,并且该页代表一个全新的 PowerShell 宿主。完美的测试环境!
我们在 用 PowerShell 屏蔽腾讯 QQ 的广告 这篇文章中介绍过了如何屏蔽 QQ 聊天窗口的横幅广告,那么如何屏蔽 QQ 秀的广告呢?请参见 QQ2013 删除QQ秀广告。
但是其中的步骤有点繁琐。我们把整个流程用 PowerShell 写一遍,对于用户只要执行一下即可:
$folder = "${env:ProgramFiles}\Tencent\QQ\Plugin\Com.Tencent.QQShow\"
$folder
$rdbFile = Join-Path $folder 'Bundle.rdb'
$rdbDir = Join-Path $folder 'Bundle'
$xmlPath = Join-Path $folder 'Bundle\I18N\2052\UrlBundle.xml'
if (Test-Path "$rdbFile.bak") {
Write-Warning "$rdbFile.bak 文件已存在,请确认是否已经替换?"
Write-Warning "程序退出。"
return
}
$rdbFile
.\RDB.exe """$rdbFile"""
move $rdbFile "$rdbFile.bak"
.\D4QQenc.exe (Join-Path $folder 'Bundle\I18N\2052\UrlBundle.xml.enc')
del (Join-Path $folder 'Bundle\I18N\2052\UrlBundle.xml.enc')
[xml]$urlBundle = Get-Content $xmlPath -Encoding UTF8 | where { $_ -ne '' }
@('IDS_QQSHOW_MARKET', 'IDS_3DSHOW_MARKET', 'IDS_FLASHSHOW_MARKET') | foreach {
$id = $_
($urlBundle.StringBundle.String | where { $_.id -eq $id })."#text" = ''
}
$urlBundle.OuterXml | Set-Content $xmlPath -Encoding UTF8
.\RDB.exe """$rdbDir"""
您也可以从这里 下载 写好的脚本,祝您使用愉快。
本方法在 QQ2013(SP6) 上验证通过。
快速入门 PowerShell 3.0 - 入门篇。密码 sja7
快速入门 : PowerShell 3.0 高级工具和脚本 - 提高篇。密码 djqe
PowerShell 技能连载 - 从 PFX 文件中导入多个证书
Get-PfxCertificate 可以从 PFX 文件中导入数字证书。然而,他只能获取一个证书。所以如果您的 PFX 文件中包含多个证书,您无法使用这个 cmdlet 获取其它的证书。
若要从一个 PFX 文件中导入多个证书,只要使用以下代码:
$pfxpath = 'C:\PathToPfxFile\testcert.pfx'
$password = 'topsecret'
Add-Type -AssemblyName System.Security
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection
$cert.Import($pfxpath, $password, 'Exportable')
$cert
PowerShell 技能连载 - 在 Remoting 中使用完整限定名
当您尝试使用 PowerShell Remoting 时,您也许会因为您使用的机器名不是完整限定名而导致连接错误。Kerberos 验证可能需要也可能不需要使用完整限定名,这取决于您的 DNS 配置。
所以也许您使用如下方式连接的时候会发生错误:
Enter-PSSession -ComputerName storage1
当发生错误的时候,请向 DNS 查询完整限定名:
[System.Net.Dns]::GetHostByName('storage1').HostName
然后,用查出的名字来代替主机名。如果主机启用了 Remoting 并且正确地配置了,您现在应该可以连上了。
假设您创建了这个函数:
function Test-Function
{
param
(
[Parameter(Mandatory=$true)]
$ServerPath
)
"You selected $ServerPath"
}
它现在可以正常工作,但是在半年之后的代码审查中,您的老板希望您使用标准的参数名称,将“ServerPath”改名为“ComputerName”。那么您对您的代码做出适当的修改:
function Test-Function
{
param
(
[Parameter(Mandatory=$true)]
$ComputerName
)
"You selected $ComputerName"
}
然而,您不能很容易地控制哪些人调用了您的函数,而且他们使用了旧的参数。所以要确保向后兼容,请确保您的函数使用旧的参数名也可以工作:
function Test-Function
{
param
(
[Parameter(Mandatory=$true)]
[Alias("ServerPath")]
$ComputerName
)
"You selected $ComputerName"
}
旧的代码任然可以运行,并且新的代码(以及代码自动完成)将会使用新的名称:

PowerShell 技能连载 - 从 PFX 文件中导入证书
您可以使用 Get-PfxCertificate 来从 PFX 文件中读取数字证书,然后用数字证书来为脚本文件签名,例如:
$pfxpath = 'C:\PathToPfxFile\testcert.pfx'
$cert = Get-PfxCertificate -FilePath $pfxpath
$cert
Get-ChildItem -Path c:\myscripts -Filter *.ps1 | Set-AuthenticodeSignature -Certificate $cert
然而,Get-PfxCertificate 将会交互式地询问您导出证书至 PFX 文件时所用的密码:
要静默地导入证书,请使用这段代码:
$pfxpath = 'C:\PathToPfxFile\testcert.pfx'
$password = 'topsecret'
Add-Type -AssemblyName System.Security
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import($pfxpath, $password, 'Exportable')
$cert
PowerShell 技能连载 - 读取注册表的可扩充字符串值
当您读取一个“可扩充字符串”类型的注册表值时,它将自动展开文本中的所有环境变量值。
这个例子将从注册表中读取系统设备路径:
$path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion'
$key = Get-ItemProperty -Path $path
$key.DevicePath
该结果将是实际的路径。这问题不大,除非您希望获取原始(未展开的)注册表值。以下是读取原始值的例子:
$path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion'
$key = Get-Item -Path $path
$key.GetValue('DevicePath', '', 'DoNotExpandEnvironmentNames')
通过这种方式存取注册表值可以提供额外的信息:您还可以获取该值的数据类型:
$path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion'
$key = Get-Item -Path $path
$key.GetValueKind('DevicePath')
PowerShell 可以很容易地读取环境变量。以下代码返回当前的 Windows 文件夹:
$env:windir
然而,如果您想永久地改变用户或机器的环境变量,您需要使用 .NET 的功能。以下是一个可以快速设置或删除环境变量的简单函数:
function Set-EnvironmentVariable
{
param
(
[Parameter(Mandatory=$true, HelpMessage='Help note')]
$Name,
[System.EnvironmentVariableTarget]
$Target,
$Value = $null
)
[System.Environment]::SetEnvironmentVariable($Name, $Value, $Target )
}
要创建一个永久的环境变量,试试以下代码:
PS> Set-EnvironmentVariable -Name TestVar -Value 123 -Target User
请注意新的用户变量只对新运行的应用程序可见。已运行的应用程序将会保持它们的运行环境副本,除非它们显式地请求改变后的变量。
以下是删除该环境变量的代码:
PS> Set-EnvironmentVariable -Name TestVar -Value '' -Target User
花生壳是 oray 公司提供的 DDNS 客户端。官方的客户端庞大臃肿:

不过好在花生壳开放了基于 http 的 API。这样我们可以很容易地用 PowerShell 实现更新动态 IP 的功能:
param (
$UserName = 'xxx',
$Password = 'yyy',
$HostName,
$IP
)
function Get-ExternalIP {
#(Invoke-WebRequest 'http://myip.dnsomatic.com' -UseBasicParsing).Content
((Invoke-WebRequest 'http://ddns.oray.com/checkip').ParsedHtml.body.innerText -split ':')[1].Trim()
}
function Update-OrayDdns {
param (
[parameter(Mandatory = $true)]
[string]$UserName,
[parameter(Mandatory = $true)]
[string]$Password,
[parameter(HelpMessage = '需要更新的域名,此域名必须是开通花生壳服务。多个域名使用,分隔,默认为空,则更新护照下所有激活的域名。')]
[string]$HostName,
[parameter(HelpMessage = '需要更新的IP地址,可以不填。如果不指定,则由服务器获取到的IP地址为准。')]
[string]$IP
)
$request = 'http://ddns.oray.com/ph/update?hostname={0}' -f ($HostName -join ',')
if ($IP) {
$request = $request + '&myip=' + $IP
}
$encoded = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($UserName+":"+$Password ))
$headers = @{Authorization = "Basic "+$encoded}
$response = Invoke-WebRequest $request -Headers $headers -UseBasicParsing
$codes = @{
good = '更新成功,域名的IP地址已经更新。'
nochg = '更新成功,但没有改变IP。一般这种情况为本次提交的IP跟上一次的一样。'
notfqdn = '未有激活花生壳的域名。'
nohost = '域名不存在或未激活花生壳。'
abuse = '请求失败,频繁请求或验证失败时会出现。'
'!donator' = '表示此功能需要付费用户才能使用,如https。'
911 = '系统错误'
}
$code = ($response.Content -split ' ')[0]
$message = $codes[$code]
if ($code -eq 'good' -or $code -eq 'nochg') {
Write-Output $message
} elseif ($code -eq 'notfqdn' -or $code -eq 'nohost') {
Write-Warning $message
} else {
Write-Error $message
}
}
Update-OrayDdns $UserName $Password $HostName
您也可以从这里 下载 写好的脚本。