PowerShell 入门






4.77/5 (21投票s)
PowerShell 是一个非常强大的工具,但它与经典的 DOS 命令提示符不同,如果你习惯了 CMD,它可能会让你感到困难。本文将引导你进入 PowerShell 的世界,并让你轻松上手。
引言
PowerShell 是更好的命令提示符。它允许你使用任何 .Net 功能,并访问 Windows 的许多不那么明显的、使用 CMD 难以访问的功能。PowerShell 基于 .Net 2.0,并将管道和过滤器(来自 Unix Shell)的理念与面向对象编程的范式结合起来。
PowerShell 的核心基于称为 Cmdlet(“命令-let”)的小功能单元。Cmdlet 列表可以在 Microsoft Technet 页面 上找到。
背景 - 语法
PowerShell 脚本所使用的脚本语言有自己的语法。本章将简要概述语法,并消除 PowerShell 脚本中隐藏的一些陷阱。
变量和常量
#Variables are defined with a leading '$':
$programFilesX86 = (${env:ProgramFiles(x86)}, ${env:ProgramFiles} -ne $null)[0]
上面的例子将变量“programFilesX86”设置为 x86 程序的程序文件文件夹的路径。因为 x86 平台没有该文件夹,所以在 x86 文件夹不可用的情况下,变量将被设置为普通的程序文件目录。
#Constants are also defined with a leading '$' -
#To distinguish them from variables, they shall be written in all-capital letters.
$CONSTVAL = "This value can't be changed"
Set-Variable CONSTVAL -option ReadOnly
虽然解释器规范不需要,但我建议你将常量写成全大写字母,以将它们与变量区分开来。
函数
PowerShell 脚本文件会被解释,如果在解释器调用之前没有读取到某个方法,PowerShell 就会出错。避免此错误陷阱的最佳方法是在顶部定义一个名为“Main”的方法,然后在文件末尾跳转到该方法。
function main{
#main function, as known from classic structured programs.
myFunction
}
function myFunction{
Write-Host "myFunction was called"
}
main #Jump to execute main
下面的示例本应执行相同的操作,但由于在调用“myFunction”时它尚未被解释,因此无法运行。
myFunction #Error - myFunction wasn't read yet, but is already called
function myFunction{
Write-Host "myFunction was called" #will never be reached
}
基本命令
文件系统
与命令提示符一样,PowerShell 提供了大量的 Cmdlet 来访问文件系统并修改文件和目录。
复制文件
可以使用 Copy-Item Cmdlet 复制文件,其中第一个参数指定源文件,第二个参数指定源文件的完整路径。
Copy-Item -Path "C:\Source\Powershell" -Destination "C:\Testumgebung"
通过在命令末尾添加 -Recurse 参数,可以递归复制。
Copy-Item -Path "C:\Source\Powershell" -Destination "C:\Testumgebung" -Recurse
获取文件或文件夹信息
可以使用 Get-Item Cmdlet 获取文件或文件夹信息。
Get-Item -Path "C:\"
要获取路径下子项的信息,可以使用带有通配符的 Get-Item 或 Get-ChildItem。
Get-Item -Path "C:\*"
Get-ChildItem -Path "C:\"
这两个 Cmdlet 都返回 C:\ 下子项的详细信息。
删除文件或目录
Remove-Item -Path "C:\Source\Test1\*.txt" -Recurse -Force
-Recurse 参数只能应用于文件,而 -Force 也可以删除锁定的文件。在上面所示的参数中,将从 C:\Source\Test1 及其子文件夹中删除所有 *.txt 文件。
复制文件或目录
Copy-Item -Path "C:\Source\*.txt" -Destination "C:\Source\Textfiles" -Recurse
此命令将 C:\Source 及其子文件夹中的所有 *.txt 文件复制到 C:\Source\Textfiles,并且子文件夹结构保持不变。
与进程交互
PowerShell 提供了大量的 Cmdlet 来帮助你分析和操作正在运行的进程。
你可以以几乎任何可能的选项启动新进程。
Start-Process powershell.exe
将启动一个新的 PowerShell 实例。Start-Process 是一个强大的 Cmdlet,并提供许多参数。所有参数的列表可以在 此 Microsoft Technet 主页上找到。
要获取系统中所有正在运行的进程列表,你可以使用
Get-Process
这将显示所有正在运行的进程列表,包括一些额外的信息。
当然,你可以按名称搜索特定进程。
Get-Process powershell
这可以通过搜索多个进程名称来扩展,例如 PowerShell 和 Windows 资源管理器。
Get-Process powershell,explorer
你应该明白了——你可以通过这种方式检查任意数量的进程名称。如果查找的进程未运行,PowerShell 将返回错误(例如,抛出异常)。你可能还不知道的是,允许在进程名称中使用通配符,这意味着
Get-Process power*
将返回所有以“power”开头的正在运行的进程。那些知道 WMI 类 Win32_Process 的人可能已经认识到,所有演示的内容都可以通过这个类轻松完成。但 PowerShell 可以做得更多:WMI 不公开公司或产品版本等属性,而 PowerShell 可以。在下面的示例中,Get-Process 通过 Select-Object Cmdlet 进行管道,只筛选出进程名称、产品版本和公司之外的所有信息。
Get-Process powershell | Select-Object name,productversion,company
现在你可能想知道如何才能知道 `get-process` 有哪些可用的属性,对吧?你可以自己找出。下面的行将 `get-process` 通过 `get-member` 进行管道,并显示所有可用的成员。
Get-Process | Get-Member
自己尝试一下——你会得到一个很长的成员列表,你可以自由使用所有这些成员。
当然,你迟早会遇到需要停止正在运行的进程的情况——使用 stop-process Cmdlet 来完成。它接受进程 ID 或进程名称作为参数。
Stop-Process 23498 Stop-Process -processname notepad
在你的 PowerShell 脚本中使用 .Net 类
以下函数使用 .Net System.Diagnostics 命名空间启动进程。当然,这也可以通过简单地使用 Start-Process Cmdlet 来实现,但这为你提供了一个在 PowerShell 脚本中正确使用 .Net 类的语法入门。
function StartProcess([string]$filePath, [array]$arguments, [bool] $waitForExit)
{
$pinfo = New-Object System.Diagnostics.ProcessStartInfo #Make a new Process start info object
$pinfo.FileName = $filePath #set the file name to the filePath argument
$pinfo.RedirectStandardError = $true #standard error and stdout shall be redirected
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = $arguments #set the arguments to the arguments specified $arguments
$p = New-Object System.Diagnostics.Process #create a process
$p.StartInfo = $pinfo # assign start info to the process
$p.Start() | Out-Null # start the process
IF($waitForExit){ #wait until the process has exited (if specified)
$p.WaitForExit()
}
}
实用程序
本章提供了一些我编写的 PowerShell 函数的示例。所有这些函数都提供现有 Cmdlet 不具备的功能,但在许多情况下仍然有用。
如果目录不存在则创建目录
仅仅创建目录会在目录已存在时报错。这个小程序助手函数通过仅在目录不存在时创建它来避免此问题。
function CreateDirectoryIfNotExisting([string]$dirPath){
IF(!(Test-Path -Path $dirPath)){#check if the directory exists
New-Item -ItemType directory -Path $dirPath #create it if it doesn't exist
}
}
如果文件/目录丢失则中止脚本执行
如果指定的文件在文件系统中丢失,此函数将中止脚本的执行。
function AbortIfFileMissing ([string]$filePath, [string]$name)
{
IF(!(Test-Path $filePath)){#Not being able to find file throws
Throw ("ERROR: The File $name was not found! Expected path: $filePath")
}
ELSE{
Write-Host ("File " + $name + " found. It's located at " + $filePath)
}
}
遵循相同的方案可以实现具有相同功能的目录函数。
function AbortIfDirectoryMissing ([string]$dirPath, [string]$name)
{
IF(!(Test-Path $dirPath)){#Not being able to find directory throws
Throw ("ERROR: The directory $name was not found! Expected path: $dirPath")
}
ELSE{
Write-Host ($name + " found. It's located at " + $dirPath)
}
}
深入阅读
本章提供了一系列链接,你可以使用这些链接阅读有关特定 PowerShell 主题的更深入、更详细的信息。