PowerShell 技能连载 - 使用 IPv4 来 Ping
适用于 PowerShell 所有版本
您可以像其它命令一样在 PowerShell 脚本中使用 ping.exe。向 ping 命令加入“-4
”参数之后,您可以强制 ping 命令使用 IPv4 协议(也可以用“-6
”参数强制使用 IPv6)。
PS> ping localhost -4
适用于 PowerShell 所有版本
您可以像其它命令一样在 PowerShell 脚本中使用 ping.exe。向 ping 命令加入“-4
”参数之后,您可以强制 ping 命令使用 IPv4 协议(也可以用“-6
”参数强制使用 IPv6)。
PS> ping localhost -4
适用于 PowerShell ISE 3 及以上版本
当您下载了 PowerShell 帮助文件之后(在提升权限的 shell 中,用 Update-Help
),您就可以用 Get-Help
命令来查找许多有用主题背后的信息。例如,以下代码将列出所有包含关键字“Parameter”的主题:
PS> Get-Help parameter
Name Category Module Synopsis
---- -------- ------ --------
Get-ClusterParameter Cmdlet FailoverClusters Get-Cl...
Set-ClusterParameter Cmdlet FailoverClusters Set-Cl...
about_CommonParameters HelpFile Descri...
about_Functions_Advanced_Param... HelpFile Explai...
about_Parameters HelpFile Descri...
about_Parameters_Default_Values HelpFile Descri...
about_ActivityCommonParameters HelpFile Descri...
about_WorkflowCommonParameters HelpFile
一般性的帮助主题都是以“about_”开头的。
在 PowerShell ISE 中,只需要单击任何一个列出的名称,然后按下 F1
键,就可以在独立的帮主窗口中打开关联的主题。
适用于 PowerShell 所有版本
函数的优先级永远比 cmdlet 高,所以如果两者名字相同,函数将会被执行。
这个函数将切实有效地改变 Get-Process
的行为:
function Get-Process
{
'go away'
}
以下是意料之中的执行结果:
PS> Get-Process
go away
甚至如果您指定了 cmdlet 的完整限定名,函数也可以优先执行:
function Microsoft.PowerShell.Management\Get-Process
{
'go away'
}
执行结果:
PS> Microsoft.PowerShell.Management\Get-Process -Id $pid
go away
这也适用于别名。它们的优先级甚至比函数更高。
唯一能确保确实执行的是 cmdlet 的方法是直接存取模块,选择希望执行的 cmdlet,然后直接调用它:
$module = Get-Module Microsoft.PowerShell.Management
$cmdlet = $module.ExportedCmdlets['Get-Process']
& $cmdlet
或者,只需要用 -noprofile
参数启动一个新的 PowerShell,确保没有人能混进您的 PowerShell 环境即可。
适用于 PowerShell 所有版本
假设您的系统启用了 EFS (Encrypting File System),并且您想将文件保存到一个 NTFS 盘中,那么以下是加密以及确保只有您可以读取该文件的方法:
(Get-Item -Path 'C:\path..to..some..file.txt').Encrypt()
如果加密成功,那么在 explorer.exe 中将会显示为绿色而不是平常的黑色。用 Decrypt()
代替 Encrypt()
来撤销加密。
请注意需要事先设置了 EFS,并且您的公司可能需要一个集中存放的备份加密秘钥。
适用于 PowerShell 控制台
请注意本文所述的内容仅限于“真实的”控制台使用。它不适用于 PowerShell ISE 编辑器。
在 PowerShell 控制台中,许多用户在要分页输出数据时仍然采用管道输出到 more.com
的老办法:
PS> dir c:\windows | more
这看起来能用。不过当您输出大量数据到管道的时候,PowerShell 看起来卡住了:
PS> dir c:\windows -Recurse -ErrorAction SilentlyContinue | more
这是因为 more.com
无法实时工作。它会首先收集所有的输入数据,然后开始分页输出。
更好的办法是使用 Out-Host
cmdlet,结合 -Paging
参数:
PS> dir c:\windows -Recurse -ErrorAction SilentlyContinue | Out-Host -Paging
它能即时输出结果,因为它一旦从管道接收到数据,就可以开始处理。
适用于 PowerShell 所有版本
请在您的脚本中避免使用 Invoke-Expression
。这个 cmdlet 接受一个字符串,并且像一个命令一样执行它。在大多数情况下,这是没必要的,它只能带来风险。
以下是一个故意构造的例子:
function Test-BadBehavior($Path)
{
Invoke-Expression "Get-ChildItem -Path $Path"
}
这个函数用 Invoke-Expression
来运行一个命令并且加上一个参数值,用来返回输入参数代表的路径下的文件列表。
由于 Invoke-Expression
接受任意的字符串参数,所以您将自己带入了类似“SQL 注入攻击”的环境中。请试着以这种方式运行脚本:
PS> Test-BadBehavior 'c:\;Get-Process'
这样写第二个命令也会被执行,并会列出所有运行中的进程。Invoke-Expression
常常被攻击者用于从外部 URL 下载恶意的程序并轻松地执行。
当然,Invoke-Expression
本来就没必要用。平时在生产系统的脚本中基本没什么用。请注意确保以硬编码的方式编写您想执行的命令:
function Test-BadBehavior($Path)
{
Get-ChildItem -Path $Path
}
适用于 PowerShell 所有版本
在 PowerShell 控制台(非 PowerShell ISE)中,您只要按下 F7
键就可以列出刚才键入的命令列表。当然,如果还没有执行过任何命令,就不会显示任何内容。
按 ALT+F7
键将会清空命令行历史列表。
适用于 PowerShell 所有版本
若要以编程的方式从文件中加载证书并将它安装到证书管理其的指定位置,请看以下脚本:
$pfxpath = 'C:\temp\test.pfx'
$password = 'test'
[System.Security.Cryptography.X509Certificates.StoreLocation]$Store = 'CurrentUser'
$StoreName = 'root'
Add-Type -AssemblyName System.Security
$certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$certificate.Import($pfxpath, $password, 'Exportable')
$Store = New-Object system.security.cryptography.X509Certificates.x509Store($StoreName, $StoreLocation)
$Store.Open('ReadWrite')
$Store.Add($certificate)
$Store.Close()
您可以配置这个脚本并指定待导入的证书文件的路径和密码。您还可以指定其存储的位置(当前用户或本地计算机),以及将其放入的容器(例如“root”代表受信任的根证书颁发机构,“my”代表个人)。
适用于 PowerShell 所有版本
若要调用记事本打印纯文本文件,请使用这行代码(请将路径替换成需要的值,否则将打印出长长的系统日志文件):
Start-Process -FilePath notepad -ArgumentList '/P C:\windows\WindowsUpdate.log'
适用于 PowerShell 所有版本
WMI 可以方便地创建新的共享文件夹。以下是一段创建本地共享文件夹的代码:
$ShareName = 'NewShare'
$Path = 'c:\123'
If (!(Get-WmiObject -Class Win32_Share -Filter "name='$ShareName'"))
{
$Shares=[WMICLASS]"WIN32_Share"
$Shares.Create($Path,$ShareName,0).ReturnValue
}
else
{
Write-Warning "Share $ShareName exists already."
}
如果您有远程机器的管理员权限的话,也可以在远程的机器上创建共享文件夹。只需要像这样使用完整 WMI 即可:
$ShareName = 'NewShare'
$Path = 'c:\123'
$Server = 'MyServer'
If (!(Get-WmiObject -Class Win32_Share -Filter "name='$ShareName'"))
{
$Shares=[WMICLASS]"\\$Server\root\cimv2:WIN32_Share"
$Shares.Create($Path,$ShareName,0).ReturnValue
}
else
{
Write-Warning "Share $ShareName exists already."
}