使用 PowerShell 批次設定 Excel 保護密碼
0 |
專案遇到為 Excel (.xlsx) 設定讀取密碼的需求。OpenXML SDK 提供的工作表保護功能,只僅限於防止內容被修改,無法做到輸入密碼才能開啟。有不少 Excel 商業元件可以彌補這個缺口,授權費用約三五百塊美金,並不算貴。但由於其他的需求我用 ClosedXML 或 OpenXML SDK 都可滿足,不值得單為這個功能採購元件,加上預計作業會在使用者的個人電腦執行,肯定有安裝 Excel,而且桌面環境,不像在網站或跑排程呼叫 Excel 有遇到一堆妖怪。 (延伸閱讀:呼叫Excel的程式無法以排程方式執行、「以排程方式呼叫Word/Excel注意事項」補充包) 評估後決定這次就用 PowerShell 實做批次加密 Excel 檔。
PowerShell 可以建立 COM+ 物件,加上是弱型別語言,操作起來比 C# 還容易,程式碼比預期簡單很多,用到一則之前介紹過的技巧 - Read-Host -AsSecureString 輸入密碼字串(參考:淺談 PowerShell 中的密碼字串加密處理)。這類與權限管控有關的密碼,我偏好請使用者現場輸入,不使用設定檔或批次參數,如此可做到只有當事人一個人知道,全程沒在畫面出現也不會留下軌跡。
還有個小眉角是我設定 $excel.Visible = $true,讓使用者看到 Excel 逐一開檔處理的過程,讓進度更透明一些,這還有另一項好處,若 .xlsx 原本有設讀取密碼,Excel 會彈出對話框等使用者輸入密碼再繼續。
完整程式範例如下:
Param(
[parameter(Mandatory=$true)][string]
$excelPath
)
$ErrorActionPreference = "STOP"
$excelPaths = @()
if ($excelPath.EndsWith(".xlsx")) {
if (Test-Path $excelPath) {
$excelPaths += $excelPath
}
}
else {
$excelPaths += @((Get-ChildItem -Path $excelPath -Filter "*.xlsx").FullName)
}
if ($excelPaths.Length -eq 0) {
Write-Error "未找到 Excel 檔案 - $excelPath"
Exit
}
function decodeSecureString($secString) {
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secString)
return [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
}
$pwdSecStr = Read-Host "請輸入 Excel 加密密碼" -AsSecureString
$pwdConfirmSecStr = Read-Host "請再輸一次密碼" -AsSecureString
$passwd = decodeSecureString($pwdSecStr)
if ($passwd -ne (decodeSecureString($pwdConfirmSecStr))) {
Write-Error "密碼不符"
Exit
}
try
{
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $true # 顯示 UI,若原本就有密碼會提示使用者輸入
$excelPaths | ForEach-Object {
Write-Host "加密 $_..."
$excel.WorkBooks.Open($_) | Out-Null
$excel.ActiveWorkbook.Password = $passwd
$excel.ActiveWorkbook.Save()
$excel.ActiveWorkBook.Close()
}
}
finally
{
$excel.Quit()
}
執行畫面:
產生的 Excel 檔開啟時會彈出密碼輸入視窗,成功!
Example of how to use PowerShell to add password protection to Excels batchly.
Comments
Be the first to post a comment