65.9K
CodeProject 正在变化。 阅读更多。
Home

PowerShell 入门

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.77/5 (21投票s)

2014年10月4日

CPOL

5分钟阅读

viewsIcon

35351

downloadIcon

395

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 主题的更深入、更详细的信息。

© . All rights reserved.