2017-07-24 14 views
5

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$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:.

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" 
+1

Đ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'. –

+0

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. –

Trả lời

1

Đầu i nói rằng tôi không có vấn đề nhưng có vẻ như cách bạn chạy vấn đề mã, trừ ISE, Console và cao hơn Powershell phiên bản chạy như v2 đây là những gì tôi phát hiện ra:

Nếu không có vấn đề:

  • powershell.exe -file c: \ debugtest.ps1
  • Powershell. exe -Command "c: \ debugtest.ps1".

Với vấn đề:

  • powershell.exe -Command c : \ Debugtest.ps1

Cách giải quyết đề nghị tôi đã làm việc trong trường hợp này:

Bạn có thể muốn thử (Get-GlobalDefaultWithReturn) ToString() để buộc nó vào một chuỗi nếu đó là vấn đề.

Powershell Version:

Major Minor Build Revision 
----- ----- ----- -------- 
2  0  -1  -1  

Nó trông giống như một lỗi, nhưng tôi không biết bất cứ điều gì thêm về nó được nêu ra. Đúng là một chút Không thể đoán trước nhưng bạn có thể muốn xem xét cách bạn chạy mã của mình, ví dụ: với TẬP_TIN nếu đó là TẬP_TIN.

+0

Tôi có thể tạo lại hành vi được mô tả bằng 'powershell -version 2' trên hệ thống đã cài đặt PowerShell v4. Tôi không có hệ thống PowerShell v2 thuần túy ở đây. Sẽ xác minh sau tối nay. –

+1

PowerShell v2 trên một hộp kiểm tra XP cho thấy hành vi tương tự như chạy một phiên bản mới hơn với '-version 2'. –

Các vấn đề liên quan