「在伺服器上安裝 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
畫成圖之後,兩個處理序之間的關係就一目了然。
flowchart LR
subgraph PS7["pwsh.exe ── PowerShell 7 的處理序"]
SCRIPT["腳本本體"]
PROXY["代理模組<br/>由隱含遠端功能產生的入口,<br/>並非本體"]
end
subgraph PS51["powershell.exe ── 背景啟動的 5.1 處理序"]
SESSION["WinPSCompatSession<br/>透過相容功能載入的所有模組<br/>共用同一個 Runspace"]
MOD["只能在 5.1 上運作的模組本體"]
end
SCRIPT --> PROXY
PROXY -->|"轉送命令呼叫"| SESSION
SESSION --> MOD
MOD -->|"結果"| SESSION
SESSION -.->|"僅回傳序列化後的值副本,<br/>無法呼叫方法"| SCRIPT
如圖所示,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 Desktop。Desktop 是 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
| 論點 | 選項 | 判斷基準 |
|---|---|---|
| 選哪個版本 | 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 / -Command。4
執行原則與腳本簽署的處理方式,請參閱同時發佈的「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 指令基礎 ── 該先學會的操作與安全使用方式
- PowerShell 腳本應用 ── 安全地自動化日誌調查、封存與報表化
- 用 PowerShell 自動化 Excel・CSV 業務處理 ── 彙總・比對・報表輸出的實務食譜
- 為 VBScript 停用做準備:VBA・企業內部工具盤點指南
- 將 .NET Framework 遷移到 .NET 之前該確認的事 - 在著手前就決定勝負的實戰檢核表
- 那個批次檔,該遷移到 PowerShell 嗎? ── cmd/bat 資產盤點與遷移判斷
相關諮詢領域
合同會社小村軟體承接公司內部腳本資產的盤點,以及分階段遷移至 PowerShell 7 的規劃與執行、依賴 5.1 專用模組之處理的切割拆分,以及「遷移後出現亂碼・無法運作」等問題的調查。
參考連結
-
Microsoft Learn, What is Windows PowerShell?。關於 Windows PowerShell 與 PowerShell 是不同產品、Windows PowerShell 隨 Windows 內建並建構於 .NET Framework 之上且最新版本為 5.1、Microsoft 未再透過新功能進行更新,支援期限與所使用的 Windows 版本綁定的說明。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
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
-
Microsoft Learn, PowerShell Support Lifecycle。關於 PowerShell 7 有 LTS 與 Stable 的版本區分且支援結束日期依循底層 .NET 的支援政策、Windows PowerShell 作為 Windows 的元件依循 Windows 支援生命週期的說明。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8
-
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
-
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
-
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
-
Microsoft Learn, about_Windows_PowerShell_Compatibility。關於相容功能會將模組載入背景的 Windows PowerShell 5.1 處理序(WinPSCompatSession)、並透過隱含遠端功能產生代理模組的機制、既有透過 UseWindowsPowerShell 的明確載入也有自動載入、以序列化後的值而非原始物件運作・僅限本機 Windows・共用單一 Runspace・預設拒絕載入清單等限制的說明。 ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, about_Requires。關於 #Requires 陳述式在未滿足指定的 PowerShell 版本(-Version)、版本類型(-PSEdition Core 或 Desktop)、模組等前提條件時會直接拒絕腳本執行的說明。 ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, about_Automatic_Variables。關於 $PSVersionTable 是保存目前工作階段 PowerShell 版本詳細資訊的唯讀雜湊表、PSEdition 屬性在 5.1(完整功能版 Windows)為 Desktop、在 6 以後為 Core 的說明。 ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, PowerShell 7 module compatibility。關於彙整 Microsoft 製各模組(包括 Windows 管理相關模組)對 PowerShell 7 支援狀況的說明。 ↩
-
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
相關文章
共用相同標籤的最新文章。能以相近的主題延伸理解。
PowerShell 腳本的引數設計與模組化 ── 從「能動的腳本」到「能交給別人用的腳本」
本文整理將 PowerShell 腳本提升到可以交給別人使用之品質的步驟,說明 param 區塊與 [CmdletBinding()]、輸入驗證、管線輸入、-WhatIf 對應、.psm1 模組化,一直到公司內部共用與 Git 管理的要點。
PowerShell 腳本太慢時該檢查的地方 ── 陣列・管線・比對的訣竅
整理 PowerShell 腳本變慢的常見原因。從實務角度解說陣列 += 造成 O(n^2) 的原因、管線與 foreach 的差異、比對的雜湊表化、檔案 I/O 的改善,以及正確的測量方式。
告別 Write-Host ── PowerShell 的輸出資料流與日誌設計
本文整理 PowerShell 六個輸出資料流的使用區分、Write-Host 所存在的問題與正確用途、函式傳回值被污染的原因、透過 -Verbose 與 -InformationVariable 由呼叫端進行控制的方法,以及結構化日誌的留存方式。
PowerShell 的並行處理 ── ForEach-Object -Parallel 與工作(Job)的選用之道
從實務角度整理 ForEach-Object -Parallel、Start-ThreadJob、Start-Job 的差異與選用方式,$using: 與執行緒安全性,ThrottleLimit 的決定方法,以及反而變慢的情況。
從 PowerShell 正確呼叫外部 exe ── 引數的引號、結束代碼、亂碼陷阱
從 PowerShell 呼叫 robocopy 或公司內部 EXE 時,引數會被破壞、拿不到結束代碼、輸出出現亂碼。本文從實務角度整理 PowerShell 7.3 的引數傳遞變更、停止剖析權杖 --%、以及 Start-Process 的使用時機。
相關主題
與本文相近的主題頁面。以本文為起點,可進一步連到相關服務與其他文章。
Windows 技術主題
彙整 KomuraSoft LLC 關於 Windows 開發、故障調查與既有資產活用文章的主題中心。
與本主題相關的服務
本文連結到以下服務頁面,歡迎從最接近的入口查看。
Windows 應用程式開發
支援包含常駐處理、設備連動、運作日誌與可維護結構的 Windows 桌面應用程式。
Windows 軟體維護 & 現代化
支援既有 Windows 軟體的階段性升級、功能追加、64 位元就緒以及可維護性的重構。
常見問題
整理諮詢這個主題時常見的問題。
- 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 導入,同時也要一併決定更新的發佈方式。