Windows PowerShell 5.1 與 PowerShell 7 的差異 ── 公司內部腳本遷移實務指南

· · PowerShell, Windows, 遷移, 自動化, 維運改善, 腳本, 既有資產活用

「在伺服器上安裝 PowerShell 7 之後,現有的腳本會不會壞掉?」「一直維持 5.1 是不是不太妥當?」── 最近愈來愈常從擁有公司內部維運腳本的客戶那裡聽到這類問題。Windows 內建的 PowerShell(5.1),與需要另行安裝的 PowerShell 7。由於名稱相同,常被誤以為「升級版本就會取代舊版」,但實際上兩者是並行共存的不同產品

若沒有正確理解這層關係就直接導入 7,通常會踩到兩種狀況之一:「明明裝了卻什麼都沒變(工作仍在 5.1 上執行)」,或是反過來「一遷移,日文檔案交換就出現亂碼」。後者尤其是日文環境特有的事故,原因就出在預設字元編碼的差異上。

本文以擁有公司內部腳本的資訊系統・維運人員為對象,從機制層面整理 5.1 與 7 的關係與差異,並附上判斷表,彙整實際推進遷移的步驟。

1. 先講結論

  • Windows PowerShell 5.1 與 PowerShell 7 是不同的產品,以並行(side-by-side)的方式共存。5.1 隨 Windows 內建,建構於 .NET Framework 之上;7 則需另行安裝,建構於 .NET 之上。即使安裝了 7,5.1 也不會消失。12
  • Microsoft 不再為 5.1 新增功能。5.1 的支援期限與 Windows 本身的生命週期綁定,開發的主軸則是 7。新撰寫的腳本應以 7 為基準。13
  • 執行檔不同。5.1 是 powershell.exe,7 是 pwsh.exe。只要不改寫工作排程器等處的啟動指令,既有機制就會持續在 5.1 上運作。45
  • 預設的字元編碼不同。5.1 依 Cmdlet 而異(例如 Out-File 為 UTF-16LE、Get-Content 為 ANSI 等),7 則一律為不含 BOM 的 UTF-8。這是日文環境遷移時最先踩到的地雷。6
  • 7 上無法運作的模組,可以使用 Windows 相容功能。透過 Import-Module -UseWindowsPowerShell 可以載入到背景的 5.1 處理序中,經由遠端功能使用,但回傳的是序列化後的物件,無法呼叫方法。7
  • #Requires -Version$PSVersionTable 在程式碼中明確標示「這個腳本該在哪個版本上執行」。如此可以在執行前,就阻止「在非預期版本上運作而悄悄出錯」的事故。89
  • 遷移採取「盤點 → 在 7 上執行測試 → 更新啟動指令」的分階段方式進行。7 本身以 MSI 或 winget 導入,並在一開始就決定更新的發佈方式(是否透過 Microsoft Update)。524

2. 5.1 與 7 是什麼關係 ── 不是取代,而是共存

首先用表格掌握整體樣貌。

項目 Windows PowerShell 5.1 PowerShell 7
取得方式 Windows 內建1 需另行安裝(MSI/winget 等)2
基礎架構 .NET Framework 4.x5 .NET(7.4 為 .NET 8.0 等)54
執行檔 powershell.exe pwsh.exe4
安裝位置 $Env:windir\System32\WindowsPowerShell\v1.05 $Env:ProgramFiles\PowerShell\75
未來的開發 不再新增功能1 開發的主軸,有 LTS/Stable 版本發行3
支援期限 依循 Windows 本身的生命週期3 依循底層 .NET 的支援政策3

7 並不會取代 5.1,而是安裝在不同的目錄中,以並行方式運作。模組存放位置(PSModulePath)、設定檔、事件日誌都各自獨立管理,不過由於 7 端的 PSModulePath 也包含了 5.1 的模組路徑,因此從 7 可以載入大部分的既有模組。52

「自己目前身處哪一邊」隨時可以用以下兩行程式碼確認。$PSVersionTable 是保存 PowerShell 版本資訊的自動變數。9

# 確認自己目前身處哪一個 PowerShell
$PSVersionTable.PSVersion   # 若為 5.1.x 則是 Windows PowerShell,7.x 則是 PowerShell 7
$PSVersionTable.PSEdition   # Desktop = Windows PowerShell / Core = PowerShell 7

官方的定位也很明確。Windows PowerShell 是隨 Windows 內建的版本,Microsoft 不會透過新功能對其進行更新,支援期限與所使用的 Windows 版本綁定。另一方面,PowerShell(7 系列)建構於新版 .NET 之上,每個版本的支援期限都依循底層 .NET 的支援政策設定。13 5.1 並不會在明天就消失,但實務上的結論是:「未來要撰寫的」「未來要長期使用的」腳本,基準都應該放在 7 上。

3. 最先踩到的地雷 ── 預設編碼的差異與亂碼

在日文環境的遷移問題中,最常見的就是亂碼。原因很明確:兩者的預設字元編碼不同。6

操作 5.1 的預設值 7 的預設值
Out-File・重新導向(>) UTF-16LE(含 BOM)6 不含 BOM 的 UTF-86
Set-Content / Add-Content ANSI(日文環境為 Shift_JIS)6 不含 BOM 的 UTF-8
Get-Content(無 BOM 檔案) ANSI6 不含 BOM 的 UTF-8
Export-Csv ASCII(會遺失日文字元)6 不含 BOM 的 UTF-8
腳本本身的解讀方式(無 BOM) ANSI 字碼頁6 UTF-8
# 即使是同一行程式碼,5.1 與 7 產生的檔案位元組序列也不同
'こんにちは' | Out-File -FilePath C:\temp\hello.txt
# 在 5.1 中執行 → 產生 UTF-16LE(含 BOM)的檔案
# 在 7 中執行   → 產生不含 BOM 的 UTF-8 檔案

這在實務上意味著兩件事。

第一,以 Shift_JIS 為前提的檔案交換作業,一旦換到 7 上,讀寫都有可能出現亂碼。因為 5.1 的 Get-Content 會把無 BOM 的檔案當作 ANSI(日文環境即 Shift_JIS)來讀取,而 7 則是以 UTF-8 讀取。對策是在所有檔案輸入輸出中明確指定 -Encoding。7 可以用字碼頁編號(-Encoding 932)或註冊名稱來指定,7.4 以後也可以使用 ansi 這個值。6 CSV 處理的具體寫法,已整理於同時發佈的「用 PowerShell 自動化 Excel・CSV 業務處理」中。

第二,是腳本檔案本身的儲存格式。若把以不含 BOM 的 UTF-8 儲存、內含日文註解的腳本讓 5.1 讀取,會被誤判為 ANSI,導致亂碼或語法錯誤。依照官方文件的建議,含有非 ASCII 字元的腳本應以帶 BOM 的 UTF-8 儲存,如此一來無論在 5.1 還是 7 上都能正確解讀。6

4. 相容性 ── 在 7 上無法運作的內容,以及 Windows 相容功能的實際能耐

4.1. 哪些東西會無法運作

7 可以直接載入大部分既有模組5,但也有無法載入的情況。以下是官方列舉的代表性範例。

  • 不再內建的模組:PSWorkflow/PSWorkflowUtility(工作流程)、PSScheduledJob、ISE 專用模組、Microsoft.PowerShell.LocalAccounts 等都不包含在 7 之中。4
  • Snap-in:早於模組的舊式擴充形式 Snap-in,在 7 中不受支援。4
  • 高度依賴 .NET Framework 的程式碼:由於 7 的底層 .NET 不同,直接呼叫 .NET 方法的腳本可能出現行為變化。54
  • 細部行為變更:例如 Export-Csv 預設不再輸出 #TYPE 這一行,Group-Object 回傳的群組會經過排序等,這些變更會影響依賴輸出內容的腳本。4

反方向的不相容也存在。使用三元運算子、ForEach-Object -Parallel 等 7 新增的語法與功能撰寫的腳本,無法在 5.1 上運作5 也就是說,每個腳本都必須決定要「寫成兩邊都能動」,還是「明確指定該用哪一邊執行」。

Microsoft 製模組的相容狀況,可以在官方的模組相容性頁面確認。10

編輯環境(ISE)的遷移方向也要一併決定。Windows PowerShell ISE 目前並沒有從 Windows 中移除的計畫,安全性與高優先度的修補也會持續提供,但新功能的開發已經結束,支援的對象僅限 PowerShell 5.1 以前的版本11 也就是說,用 ISE 撰寫並執行要在 7 上運作的腳本這種做法並不成立。官方指引的遷移方向是 Visual Studio Code 加上 PowerShell 擴充功能,只要安裝擴充功能,就能切換整合式主控台所使用的 PowerShell 版本(也可以在設定中新增額外的路徑)。針對習慣 ISE 的使用者,官方也準備了「在 VS Code 中重現 ISE 操作體驗」的指南,從那裡開始說明轉換方式會比較快。11 由於資訊系統現場有不少 ISE 使用者,腳本的遷移計畫與編輯環境的轉換,請在同一時機一併說明。

4.2. Windows 相容功能(-UseWindowsPowerShell)的機制與限制

7 提供了 Windows 相容功能,專門用於處理只能在 5.1 上運作的模組。

# 透過相容功能載入尚未支援 7 的模組(官方文件中的範例)
Import-Module -Name ScheduledTasks -UseWindowsPowerShell

其機制是遠端功能的應用。背景會啟動一個 Windows PowerShell 5.1 處理序,模組會被載入到名為 WinPSCompatSession 的工作階段中,而 7 端則會匯入由隱含遠端功能所產生的代理模組。位於 System32 之下的 5.1 專用模組,即使是透過名稱指定或命令自動偵測,也會隱含地透過這套機制載入。7

畫成圖之後,兩個處理序之間的關係就一目了然。

powershell.exe ── 背景啟動的 5.1 處理序pwsh.exe ── PowerShell 7 的處理序轉送命令呼叫結果僅回傳序列化後的值副本,無法呼叫方法WinPSCompatSession透過相容功能載入的所有模組共用同一個 Runspace只能在 5.1 上運作的模組本體腳本本體代理模組由隱含遠端功能產生的入口,並非本體

如圖所示,7 端擁有的並非模組本體,而只是一個入口。實際情況並非「裝了 7,一切就都能在 7 上運作」,而是「從 7 端拜託 5.1 端執行,再收下結果的副本」—— 後面提到的所有限制,都是從這個結構衍生出來的。

這個功能雖然方便,但若不了解限制就貿然使用,可能會悄悄出錯。官方明確記載的限制如下。7

  • 往來的是序列化後的值,而非原始物件。回傳的物件無法呼叫方法,手邊拿到的只是屬性的快照。
  • 只能在本機的 Windows 上運作,且需要 Windows PowerShell 5.1。
  • 透過相容功能載入的所有模組,共用同一個 Runspace(同一個 5.1 處理序)。
  • 部分模組(如 PSScheduledJob)在預設情況下會被拒絕載入。

諸如「呼叫取得結果的方法」「在管線中途需要原始物件」之類的處理,用相容功能是無法成立的。這種情況下,雖然也可以把整條管線都放在 5.1 端執行、只接收最終結果7,但實務上的感覺是:與其把處理寫得複雜,不如只讓該處理留在 5.1 上執行,這樣更容易維護。

5. 寫得具防禦性 ── #Requires 與版本分支

在遷移期間,必然會出現「不確定會在哪個版本上執行」的狀態。在非預期版本上執行到一半才出錯是最糟的情況,因此要在腳本端加入防禦機制。

只要寫上 #Requires 陳述式,不符合條件的 PowerShell 就會在腳本執行之前就被拒絕執行。8

#Requires -Version 7.0
# 本腳本僅供 7 使用(使用了 ForEach-Object -Parallel 等功能)。
# 若以 powershell.exe(5.1)啟動,後續內容將完全不會執行

反過來,5.1 專用的腳本則寫上 #Requires -PSEdition DesktopDesktop 是 5.1 系列、Core 是 7 系列的版本名稱。89

若是兩邊都能執行的腳本,只想針對部分行為做調整,可以用 $PSVersionTable 在執行時進行分支判斷。9

# 在同時支援 5.1 與 7 的腳本中,只針對版本差異的處理進行分支
if ($PSVersionTable.PSVersion.Major -ge 6) {
    $enc = 932            # 7:可以用字碼頁編號指定 Shift_JIS
} else {
    $enc = 'Default'      # 5.1:Default = 系統的 ANSI 字碼頁
}
Get-Content -LiteralPath $path -Encoding $enc

重點在於,這種明確標示要在「盤點階段」就加入,而不是等到「遷移結束之後」。只要有一行 #Requires,任何人都能一眼看出這個腳本屬於哪個版本的世界。

6. 遷移的推進方式 ── 從盤點到更新工作排程器

實際的遷移按以下順序進行。一次性全部切換是事故的根源,因此原則上採取分階段遷移。

步驟 1:盤點。從腳本存放位置與工作排程器中,清查出正在運作的 .ps1 檔案與啟動指令。

# 從工作排程器中,清查出所有啟動 PowerShell 的工作
Get-ScheduledTask | ForEach-Object {
    foreach ($action in $_.Actions) {
        # 為了也能抓到 cmd.exe /c powershell ... 這類間接啟動,同時檢查執行檔與引數
        if ("$($action.Execute) $($action.Arguments)" -match 'powershell|pwsh') {
            [pscustomobject]@{
                TaskPath  = $_.TaskPath        # 工作名稱只在資料夾內具有唯一性,因此也一併記錄路徑
                TaskName  = $_.TaskName
                Execute   = $action.Execute    # powershell.exe 或 pwsh.exe
                Arguments = $action.Arguments
            }
        }
    }
} | Export-Csv -Path .\ps-tasks.csv -NoTypeInformation -Encoding UTF8

產生出來的 ps-tasks.csv 共有 4 欄。以下列出各欄的意義與格式範例(範例值僅為格式示意,實際內容依環境而異)。

欄位 內容 值的範例
TaskPath 工作所在的資料夾。工作名稱只在資料夾內具有唯一性 \\Contoso\Batch\
TaskName 工作名稱 DailyReport
Execute 啟動的執行檔 powershell.exe / C:\Program Files\PowerShell\7\pwsh.exe / cmd.exe
Arguments 引數字串 -NoProfile -ExecutionPolicy RemoteSigned -File C:\scripts\daily-report.ps1

製作這份 CSV 是為了檢視以下三點。Execute 為 powershell.exe 的列,是仍在 5.1 上運作的工作,也就是遷移對象。Execute 為 cmd.exe 的列,由於 PowerShell 的啟動指令埋在 Arguments 之中,需要打開內容確認。而Arguments 中既沒有出現 -File 也沒有出現 -Command 的列,代表是以位置參數方式傳遞呼叫,在步驟 5 換成 pwsh 時解讀方式會改變(理由詳見步驟 5)。只要把這三種情況分類清楚,遷移計畫的基數(分母)就確定了。

步驟 2:導入 7。使用 MSI 套件(適合透過部署管理工具展開)或 winget 進行安裝。52

要採用哪個版本、如何安裝,依照下列基準決定。32

論點 選項 判斷基準
選哪個版本 LTS / Stable 業務伺服器選 LTS。LTS 是對應 .NET LTS 的版本,更新僅限於重大安全性修補與維護,設計上讓對既有工作負載的影響降到最低。Stable 雖然包含新功能,但在下一個 LTS 推出後約 6 個月支援就會結束3
客戶端裝置 winget 官方將其列為 Windows 客戶端上建議採用的方法2
伺服器・大量展開 MSI 套件 官方明確標示最適合 Windows Server 與企業展開。可以在命令列的屬性中指定更新途徑2
MSIX(市集)版本 注意 屬於使用者層級的安裝,無法設為供全體使用者使用,且因應用程式沙箱機制,無法使用透過 WSMan 的 PowerShell Remoting 等限制。不適合用於伺服器2
# 使用 winget 安裝。更新也可以透過 winget upgrade 走同一條途徑
winget install --id Microsoft.PowerShell --source winget

# 若想安裝 MSI 套件(適合伺服器・部署管理工具)
winget install --id Microsoft.PowerShell --source winget --installer-type wix

winget 本身也有前提條件。自 7.6.0 版的 winget 套件開始,winget install --id Microsoft.PowerShell 的行為改為預設安裝 MSIX 套件,因此若想要 MSI,就要像上面一樣加上 --installer-type wix。此外,winget 在 Windows Server 2022 以前的版本中無法使用(Windows Server 2025 的桌面體驗版則有內建)。對伺服器群組的展開計畫,以 MSI 為前提來規劃會比較穩妥。2

更新的維運方式也要一開始就決定。7.2 以後的 MSI 提供透過 Microsoft Update 接收更新的選項(預設啟用),可以納入 WSUS 或組態管理工具的一般更新流程。4 最糟糕的情況,就是放任未受管理的安裝方式不管,導致舊版的 7 一直殘留下來。

步驟 3:在 7 上執行測試。pwsh 執行每個盤點到的腳本,確認是否能運作、輸出檔案是否出現亂碼。由於 7 與 5.1 共存,不必停止正式環境的工作就能進行測試,這正是並行設計的優點。2 若出現錯誤,就依第 4 章的相容性問題(模組、.NET API、行為變更)逐一排查。

若不先決定「算是能動」的基準,測試就永遠做不完,因此先把合格條件整理成檢查清單。

  • pwsh -NoProfile -File <腳本> 能執行到最後,且 $LASTEXITCODE 為 0
  • 錯誤串流沒有任何輸出(對於預期內的警告,確認內容後可以接受)
  • 所有相依模組都能在 7 上載入(Import-Module 能通過。也要確認是否落入了相容功能)
  • 輸出檔案的內容與 5.1 版一致(見下方的 Compare-Object)
  • 輸出檔案的編碼符合接收端的預期(第 3 章。若有以 Shift_JIS 為前提的交換對象則為必要項目)
  • 對於變更類的處理,已用 -WhatIf 確認對象與 5.1 時相同
  • 執行時間沒有明顯拉長(若落入相容功能,有時會變慢)

要核對輸出結果,最可靠的方式是讓同一個腳本分別在 5.1 與 7 上執行,再比對差異。

# 分別在 5.1 與 7 上執行同一個腳本,並比較輸出檔案
& "$Env:windir\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -File .\daily-report.ps1
Move-Item .\report.csv .\report-51.csv -Force
& "$Env:ProgramFiles\PowerShell\7\pwsh.exe" -NoProfile -File .\daily-report.ps1
Move-Item .\report.csv .\report-7.csv -Force

# 逐行比對差異。若有執行日期時間等每次都會變動的欄位,比對前先排除該欄位
Compare-Object (Get-Content .\report-51.csv) (Get-Content .\report-7.csv)

# 進一步確認位元組是否一致(BOM 或換行符號的差異會在此顯現)
(Get-FileHash .\report-51.csv).Hash -eq (Get-FileHash .\report-7.csv).Hash

出現差異時,首先要分辨是「值本身不同」,還是「外觀相同、只是位元組序列不同」。若 Compare-Object 沒有差異,只有 Get-FileHash 不一致,那麼原因就是編碼或換行符號的差異(第 3 章)。請將「遷移完成」定義為「產出的成果物與 5.1 時相同」,而不是「在 7 上不出例外地跑完」。

步驟 4:明確標示該用哪個版本執行。為通過測試的腳本補上 #Requires -Version 7.0,為要留在 5.1 上的腳本補上 #Requires -PSEdition Desktop(第 5 章)。

步驟 5:更新啟動指令。改寫工作排程器的動作(Action)。若忘記這一步,就會發生「自以為已經遷移到 7,實際上卻仍在 5.1 上運作」的情況。

# 變更前(在 5.1 上執行):
#   powershell.exe -NoProfile -ExecutionPolicy RemoteSigned -File C:\scripts\daily-report.ps1
# 變更後(在 7 上執行):
#   "C:\Program Files\PowerShell\7\pwsh.exe" -NoProfile -File C:\scripts\daily-report.ps1

另外,pwsh.exe 的第一個位置參數已經從 -Command 改為 -File。若機械式地替換相當於 powershell.exe -Command "..." 的呼叫方式,解讀會跟著改變,因此請務必明確指定 -File / -Command4

執行原則與腳本簽署的處理方式,請參閱同時發佈的「PowerShell 的執行原則與指令碼簽署」;從批次檔(.bat)遷移的判斷,請參閱「那個批次檔,該遷移到 PowerShell 嗎?」。

7. 實務上的定石(判斷表)

論點 選項 判斷基準
新腳本的基準 5.1 / 7 原則上選 7。5.1 維持現狀、不再新增功能,開發主軸是 713
既有腳本的遷移 一次性切換 / 分階段遷移 盤點 → 在 7 上測試 → 通過的先更新啟動指令。因為並行共存,才能分階段遷移5
有 5.1 專用模組 放棄遷移 / -UseWindowsPowerShell / 只讓該處理留在 5.1 先理解相容功能的序列化限制(無法呼叫方法)。若會變複雜,留在 5.1 更容易維護7
明確標示版本 什麼都不做 / #Requires 為所有腳本加上 #Requires 或執行時檢查。在執行前就阻止非預期版本的執行8
檔案輸入輸出 交給預設值 / 明確指定 -Encoding 一律明確指定。從結構上防止 5.1 與 7 預設值差異造成的亂碼6
7 的更新維運 手動重新安裝 / MSI 的 Microsoft Update 連動或 winget 先決定更新途徑再發佈。放任不管的舊版 7 最危險42

總結

  • 5.1 與 7 是不同的產品,以並行方式共存。即使安裝了 7,既有機制也不會損壞,但反過來說,只要不改變啟動指令,就什麼都不會被遷移。
  • 5.1 處於不再新增功能、支援期限與 Windows 本身綁定的現狀維持模式,7 才是開發的主軸。新腳本應以 7 為基準撰寫。
  • 日文環境中最大的地雷是預設編碼的差異(5.1 各不相同,7 則一律為不含 BOM 的 UTF-8)。透過明確指定輸入輸出的 -Encoding,以及以帶 BOM 的 UTF-8 儲存腳本,可以加以防範。
  • 在 7 上無法運作的模組,可以靠 Windows 相容功能來補救,但有只能回傳序列化後的值這項限制。若行不通,就只讓該處理留在 5.1 上。
  • 用 #Requires 與 $PSVersionTable 在程式碼中明確標示「這是該在哪個版本上執行的腳本」,阻止在非預期版本上執行。
  • 遷移採取「盤點 → 導入 7(MSI/winget) → 執行測試 → 加上 #Requires → 更新工作排程器的啟動指令」的分階段方式進行。

相關文章

相關諮詢領域

合同會社小村軟體承接公司內部腳本資產的盤點,以及分階段遷移至 PowerShell 7 的規劃與執行、依賴 5.1 專用模組之處理的切割拆分,以及「遷移後出現亂碼・無法運作」等問題的調查。

參考連結

  1. Microsoft Learn, What is Windows PowerShell?。關於 Windows PowerShell 與 PowerShell 是不同產品、Windows PowerShell 隨 Windows 內建並建構於 .NET Framework 之上且最新版本為 5.1、Microsoft 未再透過新功能進行更新,支援期限與所使用的 Windows 版本綁定的說明。  2 3 4 5 6

  2. Microsoft Learn, Install PowerShell 7 on Windows。關於 PowerShell 7 不會取代 Windows PowerShell 5.1,而是安裝在新目錄中並行執行、預設安裝位置為 $Env:ProgramFiles\PowerShell\7,以及 winget・MSI 等安裝方式的說明。  2 3 4 5 6 7 8 9 10 11 12

  3. Microsoft Learn, PowerShell Support Lifecycle。關於 PowerShell 7 有 LTS 與 Stable 的版本區分且支援結束日期依循底層 .NET 的支援政策、Windows PowerShell 作為 Windows 的元件依循 Windows 支援生命週期的說明。  2 3 4 5 6 7 8

  4. Microsoft Learn, Differences between Windows PowerShell 5.1 and PowerShell 7.x。關於執行檔名稱從 powershell.exe 改為 pwsh.exe 以支援並行運作、第一個位置參數從 -Command 改為 -File、PSWorkflow・PSScheduledJob・LocalAccounts 等模組與 Snap-in 不包含於 7、Export-Csv 預設省略 #TYPE 及 Group-Object 輸出已排序結果等行為變更、各版本所依據的底層 .NET,以及 7.2 以後 MSI 的 Microsoft Update 連動選項的說明。  2 3 4 5 6 7 8 9 10 11

  5. Microsoft Learn, Migrating from Windows PowerShell 5.1 to PowerShell 7。關於 PowerShell 7 的設計以與 5.1 並行共存為前提(不同的安裝路徑・PSModulePath・設定檔・事件日誌)、5.1 與 7 各自的安裝位置、多數既有模組能在 7 上運作並可用 UseWindowsPowerShell 補足相容性、三元運算子與 ForEach-Object -Parallel 等新功能,以及透過 MSI/ZIP 展開的說明。  2 3 4 5 6 7 8 9 10 11 12

  6. Microsoft Learn, about_Character_Encoding。關於 Windows PowerShell 5.1 的預設編碼依 Cmdlet 而不一致(Out-File 與重新導向為 UTF-16LE、Set-Content/Get-Content 為 ANSI、Export-Csv 為 ASCII 等)、PowerShell 6 以後一律以不含 BOM 的 UTF-8 為預設值、5.1 會把無 BOM 的腳本誤判為 ANSI 因此含非 ASCII 字元的腳本應以帶 BOM 的 UTF-8 儲存,以及字碼頁編號指定與 7.4 的 ansi 值的說明。  2 3 4 5 6 7 8 9 10 11

  7. Microsoft Learn, about_Windows_PowerShell_Compatibility。關於相容功能會將模組載入背景的 Windows PowerShell 5.1 處理序(WinPSCompatSession)、並透過隱含遠端功能產生代理模組的機制、既有透過 UseWindowsPowerShell 的明確載入也有自動載入、以序列化後的值而非原始物件運作・僅限本機 Windows・共用單一 Runspace・預設拒絕載入清單等限制的說明。  2 3 4 5

  8. Microsoft Learn, about_Requires。關於 #Requires 陳述式在未滿足指定的 PowerShell 版本(-Version)、版本類型(-PSEdition Core 或 Desktop)、模組等前提條件時會直接拒絕腳本執行的說明。  2 3 4

  9. Microsoft Learn, about_Automatic_Variables。關於 $PSVersionTable 是保存目前工作階段 PowerShell 版本詳細資訊的唯讀雜湊表、PSEdition 屬性在 5.1(完整功能版 Windows)為 Desktop、在 6 以後為 Core 的說明。  2 3 4

  10. Microsoft Learn, PowerShell 7 module compatibility。關於彙整 Microsoft 製各模組(包括 Windows 管理相關模組)對 PowerShell 7 支援狀況的說明。 

  11. Microsoft Learn, Using Visual Studio Code for PowerShell Development。關於 Windows PowerShell ISE 雖會保留在 Windows 中但新功能開發已結束、僅能在 PowerShell 5.1 以前的版本運作、目前沒有從 Windows 移除的計畫且安全性與高優先度修補仍會持續、PowerShell 開發應使用 Visual Studio Code 與 PowerShell 擴充功能、可在工作階段選單切換所用的 PowerShell 或另外設定路徑,以及備有在 VS Code 中重現 ISE 操作體驗的指南的說明。  2

共用相同標籤的最新文章。能以相近的主題延伸理解。

與本文相近的主題頁面。以本文為起點,可進一步連到相關服務與其他文章。

本文連結到以下服務頁面,歡迎從最接近的入口查看。

常見問題

整理諮詢這個主題時常見的問題。

Windows PowerShell 5.1 與 PowerShell 7 有什麼不同?
兩者是不同的產品。5.1 隨 Windows 內建,執行於 .NET Framework 之上,Microsoft 已停止為其新增功能,支援期限則依循 Windows 本身的生命週期。7 是建構於 .NET(舊稱 .NET Core)之上、需另行安裝的產品,是目前開發的主軸。7 並非取代 5.1,而是安裝於不同的目錄中並行共存,執行檔名稱也以 powershell.exe 與 pwsh.exe 區分。
安裝 PowerShell 7 之後,既有的 5.1 腳本會損壞嗎?
不會損壞。7 安裝於不同的目錄中(預設為 Program Files\PowerShell\7),模組存放位置與設定檔也與 5.1 分開管理。透過工作排程器等方式啟動 powershell.exe 的既有機制,仍會照舊在 5.1 上運作。正因如此,反而要注意「只是安裝了 7,並不代表已經完成任何遷移」這一點 —— 想讓某個腳本改在 7 上執行,就必須明確把啟動指令切換為 pwsh.exe。
為什麼在 PowerShell 7 中執行以往的腳本會出現亂碼?
原因是預設的字元編碼改變了。5.1 依 Cmdlet 而異(例如 Out-File 為 UTF-16LE、Get-Content 為 ANSI 等),7 則一律為不含 BOM 的 UTF-8。由於日文環境中有許多以 Shift_JIS 為前提的檔案交換作業,若在維持預設值的狀態下遷移,讀寫雙方都可能出現亂碼。只要做到以下兩點,幾乎就能防範:對檔案輸入輸出明確指定 -Encoding,以及將含有非 ASCII 字元的腳本本身以帶 BOM 的 UTF-8 格式儲存。
在 PowerShell 7 中無法運作的模組該怎麼處理?
首先直接在 7 中執行 Import-Module,確認是否能正常運作。若無法運作,可使用 Windows 相容功能(Import-Module -UseWindowsPowerShell),它會在背景的 5.1 處理序中載入模組,再透過遠端功能從 7 端呼叫使用。不過這種方式有其限制:回傳的是序列化後的物件,無法呼叫方法,且只能在本機 Windows 上運作。若處理內容碰到這些限制,務實的做法是不要勉強,只讓該部分繼續留在 5.1 上執行。
公司內部腳本從 5.1 遷移到 7 該怎麼進行?
不要一次性切換,而是採取分階段遷移。首先從工作排程器與腳本存放位置盤點所有 .ps1 檔案,逐一在 7(pwsh)上執行測試,確認是否能正常運作。針對測試通過的腳本,補上 #Requires -Version 7,並將工作排程器的啟動指令從 powershell.exe 更新為 pwsh.exe。只能在 5.1 上運作的腳本,不要勉強遷移,而是明確標示該用哪個版本執行後予以保留。7 本身則以 MSI 或 winget 導入,同時也要一併決定更新的發佈方式。

作者檔案

本文作者的個人檔案頁面。

Go Komura

小村軟體有限公司 代表

以 Windows 軟體開發、技術諮詢與故障調查為中心,在難以重現的故障調查與既有資產仍在運作的專案上具有優勢。

回到部落格一覽