适合初学者阅读的Windows PowerShell 指令工具教学文件,介绍基本概念与操作方法。

PowerShell 是由微软所发展的任务自动化与组态管理框架,它的角色类似于UNIX/Linux 系统上的壳层(shell),透过脚本语言以及各种辅助工具,让系统管理者可以将各种工作自动化。

起初PowerShell 仅支援Windows 系统,后来于2016 年以开放原始码(MIT 授权)的方式释出后,发展成为跨平台的管理工具,目前它已经支援各种主流的Linux 发行版以及Mac OS 系统,其安装档案与原始码都可以从

互动式壳层(Shell)

若要开启Windows 的PowerShell,可从开始选单中寻找「Windows PowerShell」,点选后就可以打开PowerShell 的执行环境。

Windows 开始选单

PowerShell 的操作介面跟传统的命令提示字元(cmd.exe

Windows PowerShell 视窗

Cmdlets 与别名

在 PowerShell 指令視窗中,除了可以執行傳統的 Windows 指令、執行檔之外,PowerShell 本身也提供了一種特殊的 cmdlet(發音為 command-let)結構式指令,所有的 cmdlet 指令名稱都是以 動詞-名詞 的方式來命名,例如 Get-ProcessGet-ContentStop-Process 等。

以下這個例子是使用 Get-Process 這個 cmdlet 指令,查詢 Greenshot 這個應用程式的行程資訊:

Get-Process -Name Greenshot
Get-Process 查詢行程資訊

大部分的 cmdlet 指令名稱都很長,打字麻煩、也容易不小心打錯字,遇到這種情況時,可以先打指令的前幾個字母,接著按下 Tab 鍵,這樣 PowerShell 就會自動想辦法補其後續的字母。

以輸入 Get-Process 這行指令來說,我們就可以在輸入 Get-Pr 這幾個字之後,按下 Tab 來補齊後續的指令名稱,如果以這幾個字母開頭的指令有很多個的話,則會依序顯示每一個可能的組合,我們可以多按幾下 Tab 鍵來尋找自己想要輸入的指令。

雖然 Tab 鍵可以讓我們少打一些字,但是管理者在平常互動式的操作中,使用太長的指令還是不方便,為了讓互動式操作更順手,PowerShell 為所有的 cmdlet 都定義了簡短的別名(aliases),並且允許使用者再輸入參數名稱時,只要輸入足夠辨識的字母即可,另外 PowerShell 的指令是不分大小寫的,所以可以全部都以小寫輸入。

Get-Process 這行指令預設的別名是 gps,所以我們也可以這樣執行上面的指令:

gps -n Greenshot
使用 cmdlet 別名

cmdlet 指令的參數除了以參數名稱來指定之外,也可以透過參數的位置順序來判斷(這樣就不需要打參數名稱)。以 Get-Process 來說,若不加參數名稱,其第一個參數就是行程名稱(也就是 -Name),而這個行程名稱參數也允許使用萬用字元,所以我們可以使用這樣的指令找出名稱是 G 開頭、t 結尾的行程:

gps G*t
依據位置判斷參數

物件

PowerShell 將許多的資料都當成物件來處理,這樣可以讓許多的工作指令搞撰寫起來更方便。

舉例來說,以下這行指令會產生一個簡單的字串:

"Hello, World."
Hello, World.

事實上這行字串就是一個 .NET 框架的物件,我們可以透過它的 Length 屬性,得知此字串的長度:

"Hello, World.".Length
13

所有會產生輸出的 cmdlet 指令,也可以傳回資料物件,例如 Get-Process 就會傳回 System.Diagnostics.Process 這種物件,我們可以把指令傳回的物件儲存在變數中,方便後續的指令稿使用。

在 PowerShell 中,變數名稱都是以錢字號($)開頭,若要把 Get-Process 指令的查詢結果儲存下來,可以這樣寫:

$process = Get-Process -Name Greenshot

由於這個儲存下來的 $process 是一個完整的 Process 物件,所以我們可以使用其中的各種屬性或函數來控制該行程。例如取得行程的 CPU 使用率:

$green.CPU

或強制關閉這個應用程式:

$green.Kill()

這裡的範例只是讓大家了解我們可以透過物件進行各種操作,在 PowerShell 若要讓特定的程式終止執行,最直接的做法是使用 Stop-Process 這個 cmdlet 指令。

管理者需求導向

PowerShell 本身在設計時就考慮了許多系統管理者的需求,除了可使用 .NET 框架的物件之外,還有其他很多方便的小功能,像在電腦上常用的 KB、MB、GB 等單位,也可以在 PowerShell 中直接使用,例如計算 2TB 的資料以每秒 3.5 MB 的速度備份,需要幾個小時:

2TB / 3.5MB / 3600
166.440634920635

另一項常用的功能就是日期與時間的處理,以下這一行指令是計算從現在的時間到晚上 21:45 還有多久:

[DateTime] "21:45" - [DateTime]::Now
Days              : 0
Hours             : 11
Minutes           : 22
Seconds           : 44
Milliseconds      : 956
Ticks             : 409649565189
TotalDays         : 0.474131441190972
TotalHours        : 11.3791545885833
TotalMinutes      : 682.749275315
TotalSeconds      : 40964.9565189
TotalMilliseconds : 40964956.5189

這裡用中括號包起來的 [DateTime] 代表 System.DateTime 這個類別,[DateTime] "21:45" 的作用是將 "21:45" 這個字串轉換為 System.DateTime 的物件。

後面的 [DateTime]::Now 代表呼叫 System.DateTime 類別內的 Now 靜態函數,傳回現在的時間,與前面的時間相減之後,就得到間隔的時間了。

如果只想取出結果中的 Hours 欄位,可以這樣寫:

$result = [DateTime] "21:45" - [DateTime]::Now
$result.Hours
11

若要計算兩個日期之間的天數,可以這樣寫:

$result = [DateTime] "2018/10/23" - [DateTime]::Now
$result.TotalDays
160.565214351617

組合多項指令

有時候我們在處理資料時,會經過好幾道程序,前一個指令的輸出會作為下一個指令的輸入,在這種狀況下就可以使用 PowerShell 的管線(pipe)功能,串接多個指令。

PowerShell 的管線符號為 |,只要上一個指令所產生的物件類型可以被下一個指令接受,就可以用管線符號直接串接起來使用。例如我們可以使用 Get-Process 指令找出 Edge 瀏覽器的行程,然後將結果直接導給 Stop-Process,關閉 Edge 瀏覽器:

Get-Process -Name MicrosoftEdge | Stop-Process

另一個例子是使用 Get-ItemFolderA 目錄下的的所有檔案列出來,導給 Move-Item 指令,將這些檔案搬移至 FolderB 目錄中:

Get-Item FolderA* | Move-Item -Destination FolderB

我們也可以使用 PowerShell 的管線串接多個指令,以下是將 Get-Process 的輸出用 Where-Object 篩選出 Handles 大於或等於 1000 的項目,經過 Sort-Object 排序後,再由 Format-Table 輸出指定的欄位:

Get-Process |
  Where-Object { $_.Handles -ge 1000 } |
  Sort-Object Handles |
  Format-Table Handles,Name,Description -Auto
複雜的管線

保护机制

PowerShell 提供系统管理者非常强大又方便的功能,不过有了快速方便的管理工具,在使用上也必须谨慎小心,避免下错指令搞坏系统。

为了让管理者可以方便确认要执行的实际动作,PowerShell 在许多的指令中都提供了 -WhatIf-Confirm

例如我们如果想要把所有系统上 EdgeEdgeStop-ProcessStop-Process-WhatIfStop-Process

Get-Process
使用 -WhatIf

在我们确认所有的动作都没问题之后,再将 -WhatIf

另外一种方式是使用 -Confirm

Get-Process
使用 -Confirm

查询指令与物件用法

PowerShell 中可用的cmdlet 指令数量相当多,我们不太可能记得所有的指令名称与用法,实务上的做法通常都是遇到问题时,再去查询有哪些相关的指令可以使用。

若想要以关键字来寻找相关的cmdlet 指令,可以使用 Get-Command*process

Get-Command
Get-Command 搜寻指令

Get-Command会列出所有符合搜寻条件的指令,若想要查询某个指令的详细用法,可以使用 Get-HelpStop-Process

Get-Help
查询 Stop-Process

在PowerShell 中除了cmdlet 指令很多让人记不起来之外,.NET 框架的物件种类也不少,再加上每一种物件的用法都不同,所以在使用物件时,我们也时常会需要查询各种物件可用的属性与方法。

若要查询一个物件有哪些属性与方法,可以将物件透过管线的方式导给Get-Member"Hello"

"Hello"
查询字串物件的属性与方法

我们也可以将其他cmdlet 指令输出的物件直接导给Get-Member

Get-Process

或是将储存在变数中的物件导给 Get-Member

$result

指令稿

PowerShell 跟一般的指令稿语言(script language)一样,可以直接在互动式的视窗中执行,若程式码比较长的话,也可以把指令写在指令稿档案(script file)当中,一次执行档案内所有的指令。

假设我们有以下的几行下载网页的PowerShell 指令稿:

$webClient

若要以指令稿档案的方式执行这段程式码,首先要把它们储存成PowerShell 的指令搞档案(副档名为.ps1C:OfficeGuidescript.ps1

C:OfficeGuidescript.ps1

若执行时出现了「系统上已停用指令码执行」的错误讯息,请参考

历史指令

若要查询过去执行过的指令,可以使用 Get-History

Get-History

在执行一系列的指令之后,若想要将执行过的动作储存成整份的指令稿,可以使用 Get-HistoryForeach-Object

Get-History

接着可以启动记事本编辑一下这些执行过的指令:

notepad C:OfficeGuidescript2.ps1

编辑好之后,就可以直接执行这份指令稿了:

C:OfficeGuidescript2.ps1

注解

在撰写指令稿的时候,为了让程式码更容易阅读,建议可以加上适当的注解,在PowerShell 中单行的注解可用井字号(#

# 列出chrome 的行程

在程式码中,所有 #

Get-Process

如果要放置多行的注解,可以将注解使用 <##>

<# #>


这种多行的注解适合用于详细的叙述,或是把整段暂时没用的程式码注解起来。

浏览种类型资料

PowerShell 的provider 架构允许程式开发者以类似档案系统的操作方式,浏览与操作各类型的资料库。

以最普通的档案系统来说,我们可以使用以下指令列出 C:

Set-Location
浏览档案

而在熟悉这套操作模式之后,就可以用相同的方法浏览Windows 的登录机码:

Set-Location
浏览Windows 登录机码

相同的操作方法也可以套用在凭证的浏览上:

Set-Location
浏览凭证

参考资料:

Oh 游读者 👋
It’s nice to meet you.

每周三,您都将收到一封内容详实的Newsletter.

Oh 游读者 👋
It’s nice to meet you.

每周三,您都将收到一封内容详实的Newsletter.