Import-Module之「Missing argument in parameter list」鬼打牆筆記
故事是這樣的,我在PowerShell Core環境下開發了一個PowerShell Module。但不是每一台Windows Server都有PowerShell Core的執行環境,當部屬至Windows Server的PowerShell時才發現某些主機怪怪的。
此Module在我Windows 11開發機裡的PowerShell或PowerShell Core都有先測試過都,都能正常執行。
兩台不同的Windows Server 2019主機上,PowerShell的Import-Module
一台正常,一台不正常。而且在特定同事的開發機上也有類似的情況,也會出現匯入錯誤的情況。
我改寫一個可重現此錯誤的測試程式碼:
function Send-UdspMail {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]
$Subject,
[Parameter(Mandatory = $true)]
[string]
$Content,
[Parameter(Mandatory = $true)]
[string]
$TO,
[string]
$CC = "",
[string]
$BCC = ""
)
begin {
Write-Debug "Running time: $(Get-Date)"
Write-Debug "FunctionName: Send-UdspMail"
}
process {
if (("" -eq $CC) -and ("" -eq $BCC)) {
Write-Debug "無CC.無BCC."
$jsonParam =
@"
`"{`\`"From`\`":`\`"i@test.com`\`",`\`"Subject`\`":`\`"$Subject`\`",`\`"Content`\`":`\`"$Content`\`",`\`"CreatedBy`\`":`\`"PowerShell`\`",`\`"ReceiverList`\`":[{`\`"Type`\`":`\`"To`\`",`\`"MailAddress`\`":`\`"$TO`\`"}],`\`"Tags`\`":[`\`"PowerShell`\`"]}`"
"@
}
if (("" -ne $CC) -and ("" -eq $BCC)) {
Write-Debug "有CC: $CC ;無BCC."
$jsonParam =
@"
`"{`\`"From`\`":`\`"i@test.com`\`",`\`"Subject`\`":`\`"$Subject`\`",`\`"Content`\`":`\`"$Content`\`",`\`"CreatedBy`\`":`\`"PowerShell`\`",`\`"ReceiverList`\`":[{`\`"Type`\`":`\`"To`\`",`\`"MailAddress`\`":`\`"$TO`\`"},{`\`"Type`\`":`\`"CC`\`",`\`"MailAddress`\`":`\`"$CC`\`"}],`\`"Tags`\`":[`\`"PowerShell`\`"]}`"
"@
}
if (("" -eq $CC) -and ("" -ne $BCC)) {
Write-Debug "無CC;有BCC: $BCC ."
$jsonParam =
@"
`"{`\`"From`\`":`\`"i@test.com`\`",`\`"Subject`\`":`\`"$Subject`\`",`\`"Content`\`":`\`"$Content`\`",`\`"CreatedBy`\`":`\`"PowerShell`\`",`\`"ReceiverList`\`":[{`\`"Type`\`":`\`"To`\`",`\`"MailAddress`\`":`\`"$TO`\`"},{`\`"Type`\`":`\`"BCC`\`",`\`"MailAddress`\`":`\`"$BCC`\`"}],`\`"Tags`\`":[`\`"PowerShell`\`"]}`"
"@
}
if (("" -ne $CC) -and ("" -ne $BCC)) {
Write-Debug "有CC: $CC ;有BCC: $BCC ."
$jsonParam =
@"
`"{`\`"From`\`":`\`"i@test.com`\`",`\`"Subject`\`":`\`"$Subject`\`",`\`"Content`\`":`\`"$Content`\`",`\`"CreatedBy`\`":`\`"PowerShell`\`",`\`"ReceiverList`\`":[{`\`"Type`\`":`\`"To`\`",`\`"MailAddress`\`":`\`"$TO`\`"},{`\`"Type`\`":`\`"CC`\`",`\`"MailAddress`\`":`\`"$CC`\`"},{`\`"Type`\`":`\`"BCC`\`",`\`"MailAddress`\`":`\`"$BCC`\`"}],`\`"Tags`\`":[`\`"PowerShell`\`"]}`"
"@
}
$body = ...
$response = Invoke-RestMethod YourAPIURI -Method 'POST' -Headers $headers -Body $body
}
end {
return $response
}
}
它是一段發送Email的服務,因為要判斷是否有$CC
、$BCC
這幾個選項,擁有不同選項所需要的JSON格式不同。雖然是在PowerShell Core開發,但都有特別小心不要用到PowerShell未提供的語法,且在正常主機中,不論PowerShell或PowerShell Core都能正常執行。
但錯誤訊息「Missing argument in parameter list
」讓我測試了好久好久,可以說完全沒有頭緒。
PS C:> Import-Module UdspService
At C:\PsScript\Modules\UdspService\UdspService.ps1:40 char:35
+ `"{`\`"From`\`":`\`"i@test.com`\`",`\`"Subject`\`":`\`"$Subject`\`",` ...
+ ~
Missing argument in parameter list.
At C:\PsScript\Modules\UdspService\UdspService.ps1:40 char:185
+ ... owerShell`\`",`\`"ReceiverList`\`":[{`\`"Type`\`":`\`"To`\`",`\`"Mail ...
+ ~
Missing argument in parameter list.
At C:\PsScript\Modules\UdspService\UdspService.ps1:40 char:243
+ ... `",`\`"MailAddress`\`":`\`"$TO`\`"},{`\`"Type`\`":`\`"CC`\`",`\`"Mail ...
+ ~
Missing argument in parameter list.
At C:\PsScript\Modules\UdspService\UdspService.ps1:45 char:26
+ Write-Debug "無CC;有BCC: $BCC ."
+ ~~~~~~~~~~~~~~~~~~~~~
Unexpected token '無CC;有BCC: $BCC ."' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingArgument
不可能是在組合JSON格式的段落有問題,如果有問題,應該是全部都有問題,為何是部分Windows Server,又或者部分同事開發機有問題。
就在快追不下去時,同事傳來一個消息,它如果是以這樣的指令來執行,那麼可以執行成功。
powershell.exe -ExcutionPolicy Bypass -File .\Test.ps1
我嘗試了許多次,都已經把所有-ExcutionPolicy
都開到**無限制(Unrestricted)**了,但還是解決不了Import-Module
的錯誤。而且相互比對之後,成功與失敗主機本身的-ExcutionPolicy
並無不同。這下又進入死胡同了。
在沒日沒夜的測試之後,終於找問題點,我們先來看看修改之後不會失敗的程式碼:
function Send-UdspMail {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]
$Subject,
[Parameter(Mandatory = $true)]
[string]
$Content,
[Parameter(Mandatory = $true)]
[string]
$TO,
[string]
$CC = "",
[string]
$BCC = ""
)
begin {
Write-Debug "Running time: $(Get-Date)"
Write-Debug "FunctionName: Send-UdspMail"
}
process {
if (("" -eq $CC) -and ("" -eq $BCC)) {
Write-Debug "No CC.No BCC."
$jsonParam =
@"
`"{`\`"From`\`":`\`"i@test.com`\`",`\`"Subject`\`":`\`"$Subject`\`",`\`"Content`\`":`\`"$Content`\`",`\`"CreatedBy`\`":`\`"PowerShell`\`",`\`"ReceiverList`\`":[{`\`"Type`\`":`\`"To`\`",`\`"MailAddress`\`":`\`"$TO`\`"}],`\`"Tags`\`":[`\`"PowerShell`\`"]}`"
"@
}
if (("" -ne $CC) -and ("" -eq $BCC)) {
Write-Debug "Have CC: $CC ;No BCC."
$jsonParam =
@"
`"{`\`"From`\`":`\`"i@test.com`\`",`\`"Subject`\`":`\`"$Subject`\`",`\`"Content`\`":`\`"$Content`\`",`\`"CreatedBy`\`":`\`"PowerShell`\`",`\`"ReceiverList`\`":[{`\`"Type`\`":`\`"To`\`",`\`"MailAddress`\`":`\`"$TO`\`"},{`\`"Type`\`":`\`"CC`\`",`\`"MailAddress`\`":`\`"$CC`\`"}],`\`"Tags`\`":[`\`"PowerShell`\`"]}`"
"@
}
if (("" -eq $CC) -and ("" -ne $BCC)) {
Write-Debug "No CC;Have BCC: $BCC ."
$jsonParam =
@"
`"{`\`"From`\`":`\`"i@test.com`\`",`\`"Subject`\`":`\`"$Subject`\`",`\`"Content`\`":`\`"$Content`\`",`\`"CreatedBy`\`":`\`"PowerShell`\`",`\`"ReceiverList`\`":[{`\`"Type`\`":`\`"To`\`",`\`"MailAddress`\`":`\`"$TO`\`"},{`\`"Type`\`":`\`"BCC`\`",`\`"MailAddress`\`":`\`"$BCC`\`"}],`\`"Tags`\`":[`\`"PowerShell`\`"]}`"
"@
}
if (("" -ne $CC) -and ("" -ne $BCC)) {
Write-Debug "Have CC: $CC ;Have BCC: $BCC ."
$jsonParam =
@"
`"{`\`"From`\`":`\`"i@test.com`\`",`\`"Subject`\`":`\`"$Subject`\`",`\`"Content`\`":`\`"$Content`\`",`\`"CreatedBy`\`":`\`"PowerShell`\`",`\`"ReceiverList`\`":[{`\`"Type`\`":`\`"To`\`",`\`"MailAddress`\`":`\`"$TO`\`"},{`\`"Type`\`":`\`"CC`\`",`\`"MailAddress`\`":`\`"$CC`\`"},{`\`"Type`\`":`\`"BCC`\`",`\`"MailAddress`\`":`\`"$BCC`\`"}],`\`"Tags`\`":[`\`"PowerShell`\`"]}`"
"@
}
$body = ...
$response = Invoke-RestMethod YourAPIURI -Method 'POST' -Headers $headers -Body $body
}
end {
return $response
}
}
原因不在JSON格式上面,是因為我在Write-Debug "無CC.無BCC."
裡面寫了中文。但部屬到英文版的Windows Server的PowerShell執行時會有問題。PowerShell Core對於UniCode的相容性很好,因此就算在英文版Windows Server上也能正常執行。請有問題的同事修改本機指令碼測試,它的開發機是英文版,因此也中了一樣的頭獎,修改訊息為英文之後,一切正常。
回頭看看錯誤訊息,其實訊息有反應出看不懂中文的問題:Unexpected token 'ç„¡CC;有BCC: $BCC ."' in expression or statement.
,只是一直被前面那一句「Missing argument in parameter list
」搞得不知所措。
最後一個迷團,為何一開始的Windows Server 2019,有一台能正常,有一台不正常?以下是我所能找到的合理解釋:
正常這台有升級過一次,我猜是之前是中文版然後升為英文版,但核心保留中文資源,以致於Module裡Write-Debug
的中文沒有造成錯誤。但如果是純英文版環境,則程式碼包含中文就有一定的風險了。
完全沒想到「中文訊息輸出訊息」+「英文版PowerShell」+「錯誤的錯誤訊息」一連串連鎖反應,造成這難以偵錯的過程。
沒有留言:
張貼留言
感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。