Chúng tôi đã gặp phải một số hành vi PowerShell lạ khi nói đến các giá trị trả về hàm.Hành vi không thể đoán trước của giá trị trả về hàm PowerShell
Một số bối cảnh:
Trong kịch bản và mô-đun của chúng tôi, chúng tôi luôn muốn thiết lập các $ErrorActionPreference
và $DebugPreference
để mặc định toàn cầu đó là có thể phục hồi với một hàm. Giả sử chúng tôi muốn đặt $DebugPreference
thành "Continue"
để có thêm thông báo trong nhật ký của chúng tôi.
Vì vậy, chúng tôi đang làm somthing như thế này:
$DebugPreference = Get-GlobalDebugPreference
Cho dù đây là một cách tiếp cận tốt được hay không không phải là một phần của câu hỏi này.
Vấn đề:
Trên một số máy móc với các phiên bản khác nhau của PowerShell này chỉ không làm việc như mong đợi. Khi chúng tôi gọi là chức năng của chúng tôi mà trả về "Continue
", $DebugPreference
có thực sự là giá trị chính xác được lưu trữ, nhưng chúng tôi không có bất kỳ thông điệp log thêm trong file log của chúng tôi
gì chúng tôi phát hiện ra:.
Dù Write-Debug
hoạt động hay không được liên kết bằng cách nào đó cách bạn trả lại giá trị "Continue
"từ hàm quản lý các giá trị mặc định chung của chúng tôi.
Ví dụ: khi chức năng trông giống như ví dụ sau, Write-Debug hoạt động như mong đợi và in các thông báo gỡ lỗi trong PowerShell 3. Trong PowerShell 2, giá trị được đặt thành "Continue
", nhưng Write-Debug không in thêm bất kỳ tin nhắn nào.
function Get-GlobalDebugPreference
{
return "Continue"
}
$DebugPreference = Get-GlobalDebugPreference
Tuy nhiên, nếu chúng ta chỉ cần thả giá trị vào vỏ và bỏ qua các tuyên bố return
, nó hoạt động cho tất cả các phiên bản của PowerShell v2 +.
function Get-GlobalDebugPreference
{
"Continue"
}
$DebugPreference = Get-GlobalDebugPreference
có nhiều cách để trả về một giá trị từ một hàm trong PowerShell Đối với một số cách nó hoạt động cho phiên bản PS 2, một số hoạt động với v3. ver sử dụng Write-Output để trả về giá trị "Continue
"không hoạt động tới v5.
Theo ý kiến của tôi, tất cả các phương pháp tiếp cận khác nhau sẽ hoạt động tốt và nên có thể hoán đổi cho nhau. Đó là hành vi khác với những điều cơ bản như vậy là có liên quan và làm cho PowerShell hơi khó đoán trước được.
Tôi đã soạn một tập lệnh nhỏ đặt $DebugPreference
với các phương thức trả về hàm khác nhau mà tất cả đều hoạt động như nhau. Nếu bạn chạy nó với các phiên bản PowerShell khác nhau, bạn sẽ nhận được một lượng Debug khác nhau. Lưu ý rằng biến số $DebugPreference
có giá trị đúng và loại chính xác sau mỗi bước, nhưng Write-Debug chỉ hoạt động sau một số trong số chúng.
Ai đó có thể giải thích những gì đang xảy ra ở đây?
Chạy nó với "powershell.exe -version 2 ...
"mang lại cho tôi kết quả này:
Starting to test return values. Current DebugPreference: SilentlyContinue
1 Obtained the value with return: Continue with Type string
2 Obtained the value from shell with return after: Continue with Type string
DEBUG: 2 After Get-GlobalDefaultWithReturnAfterwards
3 Obtained the value from shell with return after: Continue with Type System.Management.Automation.ActionPreference
DEBUG: 3 After Get-GlobalDefaultWithReturnAfterwardsActionPreference
4 Obtained the value without return: Continue with Type string
DEBUG: 4 After Get-GlobalDefaultWithOutReturn
5 Obtained the value with Write-Output: Continue with Type string
6 Obtained the value with Write-Output: Continue with Type System.Management.Automation.ActionPreference
7 Obtained piped value with Write-Output : Continue with Type string
8 Set the value directly: Continue with Type string
DEBUG: 8 After setting the value directly
Chạy nó với "powershell.exe -version 5 ...
" mang lại cho tôi kết quả này:
Starting to test return values. Current DebugPreference: SilentlyContinue
1 Obtained the value with return: Continue with Type string
DEBUG: 1 After Get-GlobalDefaultWithReturn
2 Obtained the value from shell with return after: Continue with Type string
DEBUG: 2 After Get-GlobalDefaultWithReturnAfterwards
3 Obtained the value from shell with return after: Continue with Type System.Management.Automation.ActionPreference
DEBUG: 3 After Get-GlobalDefaultWithReturnAfterwardsActionPreference
4 Obtained the value without return: Continue with Type string
DEBUG: 4 After Get-GlobalDefaultWithOutReturn
5 Obtained the value with Write-Output: Continue with Type string
6 Obtained the value with Write-Output: Continue with Type System.Management.Automation.ActionPreference
DEBUG: 6 After Get-GlobalDefaultWriteOutputActionPreference
7 Obtained piped value with Write-Output : Continue with Type string
8 Set the value directly: Continue with Type string
DEBUG: 8 After setting the value directly
Kịch bản:
function Get-GlobalDefaultWithReturn
{
return "Continue"
}
function Get-GlobalDefaultWithReturnAfterwards
{
"Continue"
return
}
function Get-GlobalDefaultWithReturnAfterwardsActionPreference
{
([System.Management.Automation.ActionPreference]::Continue)
return
}
function Get-GlobalDefaultWithOutReturn
{
"Continue"
}
function Get-GlobalDefaultWriteOutput
{
Write-Output "Continue"
}
function Get-GlobalDefaultWriteOutputActionPreference
{
Write-Output ([System.Management.Automation.ActionPreference]::Continue)
}
$DebugPreference = "SilentlyContinue"
Write-Host "Starting to test return values. Current DebugPreference: $DebugPreference"
$DebugPreference = Get-GlobalDefaultWithReturn
Write-Host "1 Obtained the value with return: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "1 After Get-GlobalDefaultWithReturn"
$DebugPreference = "SilentlyContinue"
$DebugPreference = Get-GlobalDefaultWithReturnAfterwards
Write-Host "2 Obtained the value from shell with return after: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "2 After Get-GlobalDefaultWithReturnAfterwards"
$DebugPreference = "SilentlyContinue"
$DebugPreference = Get-GlobalDefaultWithReturnAfterwardsActionPreference
Write-Host "3 Obtained the value from shell with return after: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "3 After Get-GlobalDefaultWithReturnAfterwardsActionPreference"
$DebugPreference = "SilentlyContinue"
$DebugPreference = Get-GlobalDefaultWithOutReturn
Write-Host "4 Obtained the value without return: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "4 After Get-GlobalDefaultWithOutReturn"
$DebugPreference = "SilentlyContinue"
$DebugPreference = Get-GlobalDefaultWriteOutput
Write-Host "5 Obtained the value with Write-Output: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "5 After Get-GlobalDefaultWriteOutput"
$DebugPreference = "SilentlyContinue"
$DebugPreference = Get-GlobalDefaultWriteOutputActionPreference
Write-Host "6 Obtained the value with Write-Output: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "6 After Get-GlobalDefaultWriteOutputActionPreference"
$DebugPreference = "SilentlyContinue"
Get-GlobalDefaultWriteOutput | % { $DebugPreference = $_ }
Write-Host "7 Obtained piped value with Write-Output : $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "7 After Get-GlobalDefaultWriteOutput with pipe"
$DebugPreference = "SilentlyContinue"
$DebugPreference = "Continue"
Write-Host "8 Set the value directly: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "8 After setting the value directly"
Điều này giống như một lỗi trong PowerShell trước phiên bản 5. Không nên có sự khác biệt giữa đầu ra mặc định và đầu ra 'Write-Output' /' echo' mà một hàm trả về. Bạn nhận được kết quả chính xác nếu bạn sửa đổi '$ global: DebugPreference' thay vì' $ DebugPreference'. –
Phụ lục: 'return" Tiếp tục "' không có kết quả mong muốn có vẻ là một lỗi đã được sửa trong PowerShell v3. –