PnP
PnP

Reputation: 3185

Handling return values with PowerShell

For example, I have the below function:

Function enable-RemoteDesktopConnections
{
    Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name "fDenyTSConnections" -Value 00000000
    Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name "fSingleSessionPerUser" -Value 00000000
    Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name "UserAuthentication" -Value 00000000
}

This simply enables Remote Desktop. Now, I want to have some error handling within the function, but equally return a success or failure to the call itself so I can update values further in the script.

Can you wrap functions in a IF Statement and then use boolean to determine whether it was successful or not?

For example, take this function, where $a = "3"

Function foo {
 If($a -eq "1"){
    $true
 }else{
    $false
 }}

We then wrap the Function in an IF i.e. if the function returned true, success, or false, Fail.

If(foo){
  Write-Host "Success"
}else{
  Write-Host "Fail"
}

Is there a better way, a more effective method, a more robust approach.

Upvotes: 0

Views: 765

Answers (2)

Χpẘ
Χpẘ

Reputation: 3451

Since this is a programming style question, here are some PS style elements to consider. In general, built-in PS cmdlets don't use return codes. They use exceptions, return errors in the error stream, or they return $null.

Briefly, exceptions allow a lot of flexibility in how errors are handled:

  • In a function you write, error handling can be ignored and left for the caller to deal with
  • Or error handling can be performed against a whole block of code
  • Or error handling can be performed against a specific line of code
  • You can use finally to perform resource cleanup regardless of whether error happened
  • You can use Trap to handle all errors at a given scope (along with sub scopes) in the same place
  • Using $ErrorActionPreference or the -ErrorAction common parameter you can turn exceptions into errors or errors into exceptions

Transactions, discussed in the previous answer, are a way to turn multiple actions into a single atomic action. In a transaction either all the individual actions succeed or none of them do. In the case of the 3 registry settings for RDP that may or may not be important. I kind of doubt it is though. Otherwise whoever designed those registry settings wouldn't have designed them that way - to easy for users to get into trouble.

Transactions don't help with signalling errors. So if your concern is that the caller of enable-RemoteDesktopConnections know whether it succeeded or not transactions don't directly enable that. They do make sure that all 3 registry operations succeeded/failed, so your error signalling can be binary (yes or no, exception or no exception). As opposed to your error signalling being something like: 1) all registry updates performed, 2) some performed and some failed, and 3) they all failed.

Also the transaction makes sure the registry is never in a state where some of the 3 changes were made and some weren't - due to the actions of your script. However there's nothing to prevent another program from changing a subset of those 3 values.

Upvotes: 2

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174445

If each Set-ItemProperty call is dependant on the previous call, you might want to leverage the power of transactions:

Function Enable-RemoteDesktopConnections
{
    param()

    # Set ErrorAction preference, only applies to function scope
    $ErrorActionPreference = "SilentlyContinue"

    # Initiate a transaction that automatically rolls back on error
    Start-Transaction -RollbackPreference Error

    # Do your thing with the -UseTransaction parameter switch
    Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name "fDenyTSConnections" -Value 00000000 -UseTransaction
    Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name "fSingleSessionPerUser" -Value 00000000 -UseTransaction
    Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name "UserAuthentication" -Value 00000000 -UseTransaction

    # Attempt to complete transaction
    Complete-Transaction

    # return the status of whether the last call succeeded or not
    return $?
}

Upvotes: 4

Related Questions