位元詩人 [Windows] 程式設計教學:使用 PowerShell

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

前言

傳統上,Windows 的腳本語言分為批次檔 (batch script) 和 Windows Script Host (註) 兩種。前者是命令提示字元 (Command Prompt) 內建的語法,但功能有限。後者則可利用 COM (Component Object Model) 取得較多的功能,但不是終端機環境所用的語法。

(註) Windows Script Host 的內建語言有 VBScript 和 JScript 兩種,可再安裝其他腳本語言。

PowerShell 則結合兩者的特性,既是命令列環境,又是命令列腳本語言。此外,可以用 PowerShell 或 .NET 平台語言來擴充其功能。雖然不一定要直接用 PowerShell 取代命令提示字元,可以把 PowerShell 當成新工具來學。

PowerShell 的版本

PowerShell 在這幾年中隨著 .NET 技術持續演進,出現兩種版本。我們在本節介紹不同的 PowerShell。

基於 .NET Core 的 PowerShell Core

微軟近幾年把 .NET 平台的重心移到 .NET Core 上,也在 .NET Core 上實作新的 PowerShell Core。這個版本的 PowerShell 隨著 .NET Core 跨越多個平台,在 Windows、macOS、GNU/Linux 都可使用。

由於 Unix 原本的 shell 環境和命令列工具已經相當成熟,PowerShell 不太會取代掉這些工具,純 Unix 使用者也不會轉用這個新環境。 PowerShell 是給同時有在用 Windows 和 Unix 的程式設計者一個 (相對) 一致的系統管理工具。

這個版本的 PowerShell 不是 Windows 系統預設軟體,需另行安裝。

基於 .NET Framework 的 PowerShell

原本的 PowerShell 基於 .NET Framework。這個版本的 PowerShell 則是 Windows 限定的工具。為了相容於現有的命令列腳本,Windows 上仍會保留此命令列環境,但不太會新增功能了。除了要相容舊系統外,不用刻意守在這個版本的 PowerShell。

啟動 PowerShell 終端機

按下 Win鍵 + r 啟動「執行」對話框。輸入 powershell 後按 Enter 鍵即可啟動 .NET Framework 版本的 PowerShell。而輸入 pwsh 即可啟動 .NET Core 版本的 PowerShell。

第一次使用 PowerShell

剛進入 PowerShell 的命令列環境,會出現以下的提示 (prompt),等待使用者輸入:

PS C:\Users\user>

命令列環境和 GUI 環境不同,沒有視覺提示,要由使用者自行輸入指令來操作該環境。

每台 Windows 主機的工作目錄是相異的,為了簡化,我們省去工作目錄的部分:

PS >

我們實際輸入 Get-ChildItem 指令來檢視工作目錄下的檔案和子目錄:

PS > Get-ChildItem

輸入的方式是用鍵盤逐一輸入 Get-ChildItem 後按下 ENTER 鍵。

其實 PowerShell 的指令是不分大小寫的 (case-insensitive),在這裡刻意區分大小寫僅是易於閱讀,也符合 PowerShell 社群的慣例。讀者習慣 PowerShell 的使用方式後可自行轉為全小寫輸入指令,可以少按幾個鍵。

有用過其他命令列環境的讀者可能會覺得 PowerShell 的指令很怪。因為 PowerShell 的指令是用 Verb-Noun 的概念來組合,而不像傳統的命令列環境,每個命令列工具各自命名。

輸入指令後,系統會顯示出該工作目錄的檔案和子目錄,然後將命令列環境的使用權返還給使用者:

PS > Get-ChildItem

    目錄: C:\Users\user

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d-r--      2014/12/24  下午 12:33            Contacts
d-r--       2020/4/29  上午 11:24            Desktop
d-r--       2020/4/20  下午 08:46            Documents
d-r--        2020/5/6  下午 07:19            Downloads
d-r--      2014/12/24  下午 12:33            Favorites
d----      2014/12/24  下午 01:00            Intel
d-r--       2019/11/2  上午 08:48            Links
d-r--      2014/12/24  下午 12:33            Music
d-r--       2019/11/2  上午 08:48            OneDrive
d-r--      2014/12/24  下午 12:33            Pictures
d-r--      2014/12/24  下午 12:33            Saved Games
d-r--       2020/4/20  下午 08:47            Searches
d-r--      2014/12/24  下午 12:33            Videos

PS >

當命令列環境的使用者返還給使用者後,使用者可繼續輸入下一個指令。

互動性使用 (interactive mode) 是命令列環境基本的使用方式。而非互動模式 (non-interactive mode) 或批次模式 (batch mode) 則是較進階的使用方式。在批次模式中,使用者要預先寫好命令列腳本 (command-line script),執行該腳本時逐一執行腳本內預寫好的指令。

原本的 Get-ChildItem 指令較長。PowerShell 允許使用別名 (alias) 來輸入指令:

PS > dir

這時候指令就短多了。但還是要熟記指令的全名,對查閱 API 文件比較方便。

取得 PowerShell 的版本

由於 PowerShell 是持續演進的系統,了解自己目前使用的 PowerShell 版本對撰寫 PowerShell 腳本有所幫助。輸入以下指令來檢視 PowerShell 的版本:

PS > Get-Host | Select-Object Version

Version
-------
2.0

PS >

讀者可能會懷疑這個指令怎麼這麼長?實際上,這是兩個指令 Get-HostSelect-Object,兩者間用 | (pipe) 串連起來。

PowerShell 的管線 (pipe) 和 Unix 的管線略有不同,前者所傳遞的是 PowerShell 物件 (object) 而非字串 (string)。PowerShell 用物件來傳遞的理由是不需要重新解析字串,當物件傳到下一個指令時可直接使用。

關閉 PowerShell

輸入 exit 指令即可離開 PowerShell 終端機。

PowerShell 指令的組成

命令列環境的指令其實也是電腦程式。這些程式本身沒有 GUI,需搭配命令列環境來使用。PowerShell 的指令的主要來源如下:

  • cmdlet
  • cmdlet 的別名 (alias)
  • 命令提示字元指令
  • 批次檔
  • 外部程式

前兩種是 PowerShell 內建的功能。PowerShell 內建的指令稱為 cmdlet (command-let)。而別名並不是真正的 cmdlet,只是給 cmdlet 起個短名。

在 PowerShell 環境中使用命令提示字元指令和批次檔僅是為了相容舊程式。如果要把 PowerShell 當成主力環境的話,就不需要再刻意寫批次檔。

外部程式則是第三方命令列工具。因命令列工具已經發展多年,不可能全部用 PowerShell 改寫。做為一種命令列環境,PowerShell 仍需相容於現有的命令列工具。

取得特定指令的來源

使用 Get-Command 指令可顯示指令的來源。例如,用 Get-Command 來檢視 dir 指令的來源:

PS > Get-Command dir

CommandType     Name                            Definition
-----------     ----                            ----------
Alias           dir                             Get-ChildItem

由此可知,dir 不是 cmdlet,而是 cmdlet 的別名。

除了用來檢視指令的來源外,Get-Command 可以模擬 Unix 的 which(1) 指令。例如,檢查系統上是否能用 GCC:

PS > Get-Command gcc 2>$null

這時候,我們不需要 Get-Command 的錯誤訊息,只要知道該指令是否有成功。所以把標準錯誤重導到 $null (空物件)。

當輸出為空時,代表該指令不存在。我們可以進一步檢查自動變數 $?

PS > $?
False

這時候確認系統上沒有 GCC 可用。

獲得 cmdlet 的說明文件

由於命令列環境沒有視覺提示,得熟悉指令才能順利使用。本節介紹如何使用 PowerShell 終端機內建的工具來學習 PowerShell 指令。

剛安裝好 PowerShell 時,PowerShell 的本地端文件不是很完善。如果想要在本地端觀看 PowerShell 的幫助文件,可以使用 Update-Help 指令:

PS > Update-Help

這個指令可以下載或更新本地端的幫助文件。

取得說明文件的 cmdlet 是 Get-Help。假定要用 Get-Help 查詢 Get-ChildItem 的用法,輸入以下指令:

PS > Get-Help Get-ChildItem

以下指令和前一個指令等效:

PS > Get-ChildItem -?

-? 是 cmdlet 的共通參數,用來查詢該 cmdlet 的說明文件。

如果想要取得詳細一點的說明,在 Get-Help 指令中加上 -Detailed 參數:

PS > Get-Help Get-ChildItem -Detailed | more

由於說明文字較長,用 | (pipe) 重導給 more 指令,就可以逐頁捲動。

more 並不是 cmdlet,而是命令提示字元的指令。由此可知,PowerShell 在必要時仍可呼叫命令提示字元的指令。

如果想取得完整的說明,在 Get-Help 指令中加上 -Full 參數:

PS > Get-Help Get-ChildItem -Full | more

也可以使用命令提示字元的 help 指令:

PS > help Get-ChildItem

如果想看線上版說明,可在 Get-Help 指令中加上 -Online 參數:

PS > Get-Help Get-ChildItem -Online

這時候會連到官方的 API 文件,這應該算是最完整且最具權威性的文件了。但要注意說明文件的版本和自己系統的版本是否相符。

取得別名 (Alias) 的原始 cmdlet

雖然用別名打指令很方便,最好還是學一下每個 cmdlet 的實際名際,查相關文件會比較方便。用 Get-Alias 指令可取得特定別名的原 cmdlet。以下指令用來取得 dir 的原 cmdlet:

PS > Get-Alias dir

取得 cmdlet 的屬性

由於 cmdlet 回傳的值是物件,用 Get-Member 指令可以觀看物件的屬性:

PS > Get-Location | Get-Member

   TypeName: System.Management.Automation.PathInfo

Name         MemberType Definition
----         ---------- ----------
Equals       Method     bool Equals(System.Object obj)
GetHashCode  Method     int GetHashCode()
GetType      Method     type GetType()
ToString     Method     string ToString()
Drive        Property   System.Management.Automation.PSDriveInfo Drive {get;}
Path         Property   string Path {get;}
Provider     Property   System.Management.Automation.ProviderInfo Provider {get;}
ProviderPath Property   string ProviderPath {get;}

在 PowerShell 中撰寫多行程式

以下範例展示如何在 PowerShell 中撰寫多行程式:

PS > if ($true) {
>> Write-Host "Hello World"
>> }
>>
Hello World
PS >

實際輸入的方式是每撰寫一行就按一次 Enter 鍵。PowerShell 環境會自動換行。尾端輸入空行後會結束該程式碼片段並執行。

如果碰到較長或需重覆使用的 PowerShell 程式,還是會寫在命令稿後再執行。

使用 PowerShell 的議題

PowerShell 是持續發展的命令列環境,但系統上的 PowerShell 版本不一定是最新版。使用 PowerShell 時應儘量避免過新或實驗性質的特性,以免寫出不相容的 PowerShell 命令稿。

雖然 PowerShell 在非 Windows 系統也可以使用,但在非 Windows 系統上 PowerShell 不是主流的系統管理工具,大部分的系統不會預裝 PowerShell。如果需要使用 GNU/Linux 或 Unix 主機,最好還是花點時間學習正統的 Unix 命令列環境和命令列工具。

關於作者

身為資訊領域碩士,位元詩人 (ByteBard) 認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

位元詩人喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,位元詩人將所學寫成文章,放在這個網站上和大家分享。