none
PowerShell nested Try/Catch

    Question

  • Sorry if this is not posted in the right location.

    I have a feeling there is a better way to do this. If so, I'm all ears. Anyway, I want to search for an AD user with and without a space in their name because sAMAccount names can be either format.



    This code:

    1)search for name with space

    2) if 1 errors: search for name without space

    3) if 2 errors: do things when the user is not found by either search method like add the user.

    even when the user is found, the code always executes the 2nd catch block, giving me an "ADUserAlreadyExists" exception. I wouldn't expect this because the 2nd catch should only execute if the 2nd try encounters an error. I think it has to do with both catches being for the same error name. 

    Thursday, July 11, 2013 5:48 PM

Answers

  • Simple logic is best here:

    if($user=Get-AdUserr -identity $useerid -ea 0){
        Write-Host 'User found' -fore green
    }else{
         Write-Host 'User not found' -fore red
    }

    No need for exceptions.

    If you use ANR resolution display name can be resolved but ay resolve to multiple users so you need to check.  All of this can be done with Get-AdUser only.


    ¯\_(ツ)_/¯

    • Marked as answer by _Derek_ Friday, July 12, 2013 1:22 PM
    Friday, July 12, 2013 12:49 PM

All replies

  • You should not embed a try/catch inside a catch.  It will corrupt the stack.  You must exit the exception before trying a new bit of code.

    It is bad design to use exceptions as code.  Exceptions are expensive and can telescope if not handled exactly right.

    Redesign your logic to be direct.  That means as k a direct question by accessing a method or property that returns a result that is what you need. A null result will indicate that the value or object does not exist or is not valid.

    When posting code do not post images as they cannot be copied and tested.  Use the code posting wizard on the toolbar.

    DisplayName is not a valid identity but can be used in an ANR query.


    ¯\_(ツ)_/¯

    Thursday, July 11, 2013 5:55 PM
  • Thanks for the response. The only way I know how to query for a user is with the get-aduser cmdlet. It's a powerful tool because it searches all OU's. Whenever it isn't able to "get" a user however, it hits an exception. So I feel like exceptions are inevitable in this case. Yes - I could write a function that returns a Boolean of whether the user was found. But there will still have to be error mgmt inside the function. You might have noticed that I was modifying but never using the variable $found. I'll just put the actions for when a use is not found inside an

    if not $found{ 

    statement. 

     
    Friday, July 12, 2013 12:45 PM
  • Simple logic is best here:

    if($user=Get-AdUserr -identity $useerid -ea 0){
        Write-Host 'User found' -fore green
    }else{
         Write-Host 'User not found' -fore red
    }

    No need for exceptions.

    If you use ANR resolution display name can be resolved but ay resolve to multiple users so you need to check.  All of this can be done with Get-AdUser only.


    ¯\_(ツ)_/¯

    • Marked as answer by _Derek_ Friday, July 12, 2013 1:22 PM
    Friday, July 12, 2013 12:49 PM
  • Thanks for the response. The only way I know how to query for a user is with the get-aduser cmdlet. It's a powerful tool because it searches all OU's. Whenever it isn't able to "get" a user however, it hits an exception. So I feel like exceptions are inevitable in this case. Yes - I could write a function that returns a Boolean of whether the user was found. But there will still have to be error mgmt inside the function. You might have noticed that I was modifying but never using the variable $found. I'll just put the actions for when a use is not found inside an

    if not $found{ 

    statement. 

     

    You're on the right track here.  The code structure would look something like this.  Note that in this case, you don't even need a $found variable;  your if statements can just check whether $user is $null.  Using a success / found flag can be useful for more complicated blocks, though, so I left it in as an illustration.

    $found = $false try { $user = Get-ADUser ... $found = $true } catch { # Handle the error, if you want } if (!$found) { try { $user = Get-ADUser ... $found = $true } catch { # Handle the error, if you want. } }

    if ($found) {
    # Do something with $user
    } else {
    # Log an error
    }



    • Edited by David Wyatt Friday, July 12, 2013 12:58 PM edit
    Friday, July 12, 2013 12:57 PM
  • Forcing try/cat is unnecessary.  Just check the result and take appropriate action as I posted above.  A Null result is the same as a $false in an 'if' statement.  This is by design in all languages since 'C'.  It is a common and useful programing construct.  Learn to use it.

    Exception handling is a techniques that is more suited to blocks of code.  It also works best with raw .Net calls.  PowerShell has been designed to allow CmdLets to suppress error handling and allow us to direct test the result.  This is the simples solution for many design patterns.


    ¯\_(ツ)_/¯

    Friday, July 12, 2013 1:03 PM
  • Forcing try/cat is unnecessary.  Just check the result and take appropriate action as I posted above.  A Null result is the same as a $false in an 'if' statement.  This is by design in all languages since 'C'.  It is a common and useful programing construct.  Learn to use it.

    Exception handling is a techniques that is more suited to blocks of code.  It also works best with raw .Net calls.  PowerShell has been designed to allow CmdLets to suppress error handling and allow us to direct test the result.  This is the simples solution for many design patterns.


    ¯\_(ツ)_/¯

    So you're suggesting I use " -ErrorAction ContinueSilently"
    Friday, July 12, 2013 1:13 PM
  • It may not be "necessary", but it's certainly an option.

    The nice thing about using -EA Stop and try/catch is that you don't have to play any guessing games about whether a cmdlet will produce terminating or non-terminating errors (which is undocumented right now, requiring a fair amount of trial and error to get right), or use multiple methods of testing for errors.  I only use this technique when a cmdlet is operating on (or searching for) a single object, since -EA Stop causes it to dump the entire pipeline, but in that situation (a single-object command), it makes the code simpler.

    Friday, July 12, 2013 1:15 PM
  • Forcing try/cat is unnecessary.  Just check the result and take appropriate action as I posted above.  A Null result is the same as a $false in an 'if' statement.  This is by design in all languages since 'C'.  It is a common and useful programing construct.  Learn to use it.

    Exception handling is a techniques that is more suited to blocks of code.  It also works best with raw .Net calls.  PowerShell has been designed to allow CmdLets to suppress error handling and allow us to direct test the result.  This is the simples solution for many design patterns.


    ¯\_(ツ)_/¯

    So you're suggesting I use " -ErrorAction ContinueSilently"

    That is what the 'if' statement does.  It gets the results and test for a null return while hiding the error. (-ea 0 is SilentlyContinue )

    ¯\_(ツ)_/¯

    Friday, July 12, 2013 1:15 PM
  • It may not be "necessary", but it's certainly an option.

    The nice thing about using -EA Stop and try/catch is that you don't have to play any guessing games about whether a cmdlet will produce terminating or non-terminating errors (which is undocumented right now, requiring a fair amount of trial and error to get right), or use multiple methods of testing for errors.  I only use this technique when a cmdlet is operating on (or searching for) a single object, since -EA Stop causes it to dump the entire pipeline, but in that situation (a single-object command), it makes the code simpler.

    -EA Stop does not work correctly with all CmdLets.  It is always more expansive to use an exception. -EA stop throws an exception which is re-thrown to the try/catch wrapper.  Now you are causing two delays.  In many instances this is trivial but it is still a bad design habit.  Learn to avoid it until you are sure you know when you can get away with it.

    OCCAM says... use the simpler construct.


    ¯\_(ツ)_/¯

    Friday, July 12, 2013 1:21 PM
  • -EA Stop does not work correctly with all CmdLets.

    I suppose you have specific examples to back this up?

    It is always more expansive to use an exception. -EA stop throws an exception which is re-thrown to the try/catch wrapper.  Now you are causing two delays.  In many instances this is trivial but it is still a bad design habit.  Learn to avoid it until you are sure you know when you can get away with it.

    OCCAM says... use the simpler construct.


    ¯\_(ツ)_/¯

    Wrapping an exception is a constant time, small delay;  it can be ignored, when the benefits are producing code that can be more easily read and maintained.  Using the .NET Framework at all is much more "expensive" than writing your own C or Assembly code.  We use it anyway, though, because it hides all the complexity of memory management / etc, resulting in code that is easier to manage, and will usually have fewer bugs.  (When's the last time you heard of a buffer overrun in managed code?)
    Friday, July 12, 2013 1:27 PM
  • -EA Stop does not work correctly with all CmdLets.

    I suppose you have specific examples to back this up?

    It is always more expansive to use an exception. -EA stop throws an exception which is re-thrown to the try/catch wrapper.  Now you are causing two delays.  In many instances this is trivial but it is still a bad design habit.  Learn to avoid it until you are sure you know when you can get away with it.

    OCCAM says... use the simpler construct.


    ¯\_(ツ)_/¯

    Wrapping an exception is a constant time, small delay;  it can be ignored, when the benefits are producing code that can be more easily read and maintained.  Using the .NET Framework at all is much more "expensive" than writing your own C or Assembly code.  We use it anyway, though, because it hides all the complexity of memory management / etc, resulting in code that is easier to manage, and will usually have fewer bugs.  (When's the last time you heard of a buffer overrun in managed code?)

    This thread makes it painfully obvious that Try/catch is not the easier and more understandable approach.  If you prefer it then you are free to use it.  It is overkill and not at all necessary in this case.  It can also cause inexperienced scripters to get horribly lost.

    Never forget old OCCAM!  Why drive across the street when you can just walk?


    ¯\_(ツ)_/¯

    Friday, July 12, 2013 1:36 PM
  • Do you even know what Occam's Razor means?  Paraphrasing:  All other things being equal, the simplest solution tends to be the correct one.

    That first phrase is kind of important to the principle.  As I've already pointed out, there are benefits to using try/catch (in combination with ErrorAction Stop) in certain situations.  At that point it becomes a cost/benefit question, not something where you can just rattle off the word "Occam" to try to sound smart.

    I've already pointed out that the cost of using Exceptions is small, and more importantly, constant.  On modern computers, you can completely ignore that type of performance hit in favor of producing more manageable code.  So it really comes down to the personal preference of the developer (or team of developers);  in PowerShell, do they want to have to deal with both terminating and non-terminating errors at the same time (trapping for both), or, in some situations, force the try/catch construct to be all that is required?

    Friday, July 12, 2013 1:50 PM
  • Do you even know what Occam's Razor means?  Paraphrasing:  All other things being equal, the simplest solution tends to be the correct one.

    That first phrase is kind of important to the principle.  As I've already pointed out, there are benefits to using try/catch (in combination with ErrorAction Stop) in certain situations.  At that point it becomes a cost/benefit question, not something where you can just rattle off the word "Occam" to try to sound smart.

    I've already pointed out that the cost of using Exceptions is small, and more importantly, constant.  On modern computers, you can completely ignore that type of performance hit in favor of producing more manageable code.  So it really comes down to the personal preference of the developer (or team of developers);  in PowerShell, do they want to have to deal with both terminating and non-terminating errors at the same time (trapping for both), or, in some situations, force the try/catch construct to be all that is required?

    I am a personal friend of Occam.  We dine regularly.

    Stop your nonsense ol David.  Try/Catch is way more expensive.  Use it is you like.  It is not the easiest solution.  "All other things being equal".

    And stop trying to twist my pal Occam's meaning.  The actual statement  is not what is normally posted in Inet blogs.  It is much more general and subtle.

    Actually, I should also try and use the correct spelling for William of Ockham.  Bill was quite definite about his statements: "Plurality must never be posited without necessity"  In other words don't over-complicate things without a good reason.  In programming "visiual clarity" is important but not necessarily a good reason to impact code.  Code impact is always more important.

    You are still free to do as you like. Just don't try to blame your excesses on my buddy Bill Ockham.  He will become very agitated.


    ¯\_(ツ)_/¯


    • Edited by jrv Friday, July 12, 2013 2:32 PM xxxx
    Friday, July 12, 2013 2:32 PM
  • Yes, you're very good at copying and pasting something from Wikipedia.  Well done.  The "without necessity" portion of that description is exactly what I was pointing out to you earlier.  Also, of the two of us, I'm not the one who brought up Occam's Razor as justification for writing code a certain way.

    In programming "visiual clarity" is important but not necessarily a good reason to impact code. Code impact is always more important.

    You're welcome to your opinion here, but quite frankly, you're wrong.  Writing clear, manageable, secure, and bug-free code is nearly always better than writing unreadable crap that might execute a few CPU cycles faster.  When performance is a concern, profile the code and see which routines should be optimized.  When you write those optimizations, do it with as much documentation as is needed to make sure the code can still be easily understood when a new developer reads it.

    The cost of maintaining code and fixing bugs is massive, both in terms of development / testing man hours and in potential lost revenue due to negative customer perception.  Microsoft estimates that they lose about $100,000 every time they have to publish a security bulletin and an associated patch.

    Friday, July 12, 2013 4:03 PM
  • David - do you ever get tired of arguments that have no resolution?

    I am going to declare that "I win!" and call it quits.  You can still write code as you like.  Don't let my lack of a rebuttal stop you.

    Have a nice day and don't let them get you down.


    ¯\_(ツ)_/¯

    Friday, July 12, 2013 4:08 PM
  • I mostly just get sick of the attitude behind your posts.  You frequently come across as saying "That's wrong.  Don't do that.  You don't know what you're doing.  Go learn something.", which is not productive at all (and more than a little insulting).  For one thing, you're not always right, and for another, most of the time, there are multiple options available.  Showing someone how to weigh the pros and cons of different options is helpful; telling them to only do it "your way" is not.

    When I see that kind of thing, I'm more than happy to call you on it.  I'm sure this won't be the last time.

    Friday, July 12, 2013 4:21 PM
  • I mostly just get sick of the attitude behind your posts.  You frequently come across as saying "That's wrong.  Don't do that.  You don't know what you're doing.  Go learn something.", which is not productive at all (and more than a little insulting).  For one thing, you're not always right, and for another, most of the time, there are multiple options available.  Showing someone how to weigh the pros and cons of different options is helpful; telling them to only do it "your way" is not.

    When I see that kind of thing, I'm more than happy to call you on it.  I'm sure this won't be the last time.

    YOu have quite an imagination.  You should not to personally criticize other posters.  It is not up to you to manage whether I disagree with something on technical grounds.  If I think something is terchnically wrong I will say so.  You are free to ignore me but you cannot tell me I can not do this.

    You have repeatedly accused me of things that are not true based on what is posted.  I have not insulted you here. I made a statement and you started an argument about something I posted in jest.  I continued the jest but you seem to have now sense of what is funny or amusing. You just want to argue.  We will start a forum for arguments.  I recommend studying Monte Python before you join the forum.

    Here is your first lesson: http://www.youtube.com/watch?v=RDjCqjzbvJY


    ¯\_(ツ)_/¯

    Friday, July 12, 2013 4:30 PM
  • Mom! Dad! stop fighting :'(

    Both of you have some vary valid points on coding in my amateur opinion. In the war between performance and usability, the best road is the middle one generally. Consumer cars would get better gas mileage if their bodies were more aerodynamic (lower profile, protruding and pointy fender) but there comes a time where people need to be comfortable while driving, and not have to worry about crazy protrusions when parallel parking. It's a balance. 

    Anyway, I changed my error action to "SilentlyContinue" and for some odd reason, it does not seem to be working. I'll attach my code, and a screenshot. I did try the " -ea 0 " but reverted to the full statements when that did not work.

        # Try to find user by LDAP display name, search for with and without space
          if($user=Get-AdUser -identity $name -ea 0)
          {
            modUser
          }
          elseif($user=Get-AdUser -identity $displayname -ea 0)
          {
             moduser
          }
          else
          {
            if ($adduser)
            {
            new-aduser -Name "$displayname" -mobilephone $mobilephone -path "$path" -emailaddress "$emailaddress" `
                       -officePhone "$officePhone" -displayname "$displayname" -givenname "$givenname" `
                       -surname "$surname" -Manager $manager -Title $title -fax $fax -Department $department `
                       -State $state -PostalCode $PostalCode -POBox $POBox -Office $office `
                       -OtherName $othername -city $city -Organization $organization
       
              $addedUserList += $name
            }
          }
        $notFoundlist += $name
    }
    Here I try it at the command line to no avail:
     
    Friday, July 12, 2013 5:24 PM
  • You can trap "not found" as follows:


    try {
      get-aduser NonExistentUser
    }
    catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {
      "Not Found"
    }

    However, this is not very efficient as noted previously. It's more efficient to say:


    get-aduser -filter { SamAccountName -eq <whatever> }

    If output of above is $NULL, then the user was not found.

    Bill

    Friday, July 12, 2013 5:36 PM
    Moderator
  • thanks Bill, doing that initially could have saved me a lot of trouble. In regard to my previous ErrorAction Post, do you have any idea what was wrong with my syntax?
    Friday, July 12, 2013 5:50 PM
  • ErrorAction only affects non-terminating errors.  Terminating errors always have to be handled by either try/catch or trap statements.  Unfortunately, there's little to no cmdlet documentation regarding what types of errors they are expected to produce.

    In this case, Get-ADUser appears to be throwing a terminating error when you use the -Identity parameter, but if you use -Filter and nothing is found, it just returns no results.

    Friday, July 12, 2013 6:19 PM
  • I was under the impression that Error Action changes the type of error. For instance when I was using try/catch statements (prior to unsuccessfully nesting them), I had to change the error action to stop because the error is naturally non-terminating and like you said, try/catch would not influence it. Now I try and change the error to non-terminating and no message. ADIdentityNotFoundException is still non-terminating but it is not silent. I know it is non-terminating because I am iteratingthrough 100+ csv objects and getting an error for every single one. 
    Friday, July 12, 2013 7:01 PM
  • As you have noticed, not all cmdlets play by the usual rules, unfortunately.

    Bill

    Friday, July 12, 2013 7:05 PM
    Moderator
  • If you set ErrorAction to stop, it wraps the non-terminating error and turns it into a terminating error instead.  Other values of ErrorAction do different things, but only if the error was non-terminating to begin with.

    A terminating error doesn't mean it'll cause your entire script to fail (the way an unhandled exception would in a .NET application), but it will abort the pipeline in which it occurs.  Your script can still continue on to execute the next command after that pipeline.  In this case:

    $user = Get-ADUser -Identity $displayName

    That command is an entire pipeline, and nothing else will abort when it throws a terminating error.

    Friday, July 12, 2013 7:11 PM
  • If you set ErrorAction to stop, it wraps the non-terminating error and turns it into a terminating error instead.

    Usually, yes. But this does not work with get-aduser. Try this script:


    $user = get-aduser NonExistentUser -erroraction Stop
    "Next line"
    

    The script will output an error and "Next line" regardless of what you use for the -erroraction parameter.

    Bill


    Friday, July 12, 2013 7:24 PM
    Moderator
  • If you set ErrorAction to stop, it wraps the non-terminating error and turns it into a terminating error instead.

    Usually, yes. But this does not work with get-aduser. Try this script:


    $user = get-aduser NonExistentUser -erroraction Stop
    "Next line"
    

    The script will output an error and "Next line" regardless of what you use for the -erroraction parameter.

    Bill


    The error thrown by Get-ADUser in this case is already a terminating error.  Adding -ErrorAction Stop doesn't affect its behavior at all.

    I think I see the source of confusion here, though.  When you turn a non-terminating error into a terminating error with -EA Stop, it causes your calling function to throw a terminating error (which may mean your whole script exits). When a cmdlet throws an unhandled terminating error, your script just outputs the error to the screen and moves on with the next command. This may also be why jrv said earlier that -EA stop doesn't always work (though that's not entirely correct.  -EA stop is doing exactly what it's supposed to do to errors that are non-terminating).

    # Cmdlet thrown terminating error. Using ErrorAction SilentlyContinue
    # to demonstrate that this is a terminating error (otherwise it wouldn't
    # be output to the screen). Get-ADUser -Identity FakePerson -ErrorAction SilentlyContinue "After Get-ADUser" # -EA stop terminating error Get-Item C:\Does\Not\Exist -ErrorAction Stop "After Get-Item"


    Friday, July 12, 2013 7:54 PM
  • I understand why the PowerShell team added a concept of non-terminating errors, but the current implementation (and lack of cmdlet documentation) makes it confusing.
    Friday, July 12, 2013 7:56 PM
  • The point is that the behavior seems to be inconsistent, because you can modify the behavior by using $erroractionpreference and not -erroraction. For example, this works:


    $ErrorActionPreference = "SilentlyContinue"
    get-aduser NonExistentUser
    "After get-aduser"
    

    It seems like it should behave the same way if you use -erroraction (get-aduser says it supports -erroraction), but it seems not to be the case.

    Bill
    Friday, July 12, 2013 8:05 PM
    Moderator
  • That's interesting, I didn't know that $ErrorActionPreference affected the display of terminating errors as well as non-terminating.  It's hard to tell without being able to debug the powershell engine, but I suspect it has to do with variable scope.  Setting the -ErrorAction parameter on an advanced function (and presumably on a cmdlet) has the effect of changing $ErrorActionPreference within that function's scope, but doesn't affect $ErrorActionPreference of the caller.  When PowerShell gets a terminating error from a command (via Cmdlet.ThrowTerminatingError), it seems to be checking $ErrorActionPreference in the caller's scope to decide what to do with it.

    Here's some code that plays around with the behavior of terminating and non-terminating errors from advanced functions pretending to be cmdlets ( using $PSCmdlet.WriteError and $PSCmdlet.ThrowTerminatingError ), as well as how -ErrorAction affects the behavior.

    function ThrowsTerminatingError {
        [CmdletBinding()]
        param (
    
        )
    
        Write-Host "Before terminating error."
        
        $exception = New-Object System.Exception("Test terminating exception.")
        $errorRecord = New-Object System.Management.Automation.ErrorRecord($exception,"Test Terminating Error Type",[System.Management.Automation.ErrorCategory]::InvalidOperation, $null)
    
        $PSCmdlet.ThrowTerminatingError($errorRecord)
    
        Write-Host "After terminating error."
    }
    
    function ThrowsNonTerminatingError {
        [CmdletBinding()]
        param (
    
        )
    
        Write-Host "Before non-terminating error"
    
        $exception = New-Object System.Exception("Test non-terminating exception.")
        $errorRecord = New-Object System.Management.Automation.ErrorRecord($exception,"Test Non-Terminating Error Type",[System.Management.Automation.ErrorCategory]::InvalidOperation, $null)
    
        $PSCmdlet.WriteError($errorRecord)
    
        Write-Host "After non-terminating error."
    }
    
    $ErrorActionPreference = "Continue"
    
    Write-Host "Before terminating call 1"
    ThrowsTerminatingError -ErrorAction SilentlyContinue
    Write-Host "After terminating call 1"
    
    Write-Host "Before terminating call 2"
    ThrowsTerminatingError -ErrorAction Stop
    Write-Host "After terminating call 2"
    
    Write-Host "Before non-terminating call 1"
    ThrowsNonTerminatingError -ErrorAction SilentlyContinue
    Write-Host "After non-terminating call 1"
    
    Write-Host "Before non-terminating call 2"
    ThrowsNonTerminatingError -ErrorAction Stop
    Write-Host "After non-terminating call 2"


    • Edited by David Wyatt Friday, July 12, 2013 8:28 PM edit
    Friday, July 12, 2013 8:22 PM
  • As strange as it sounds, the bug seems to be that $ErrorActionPreference affects terminating errors at all (at least according to PowerShell's documentation):

     

    $ErrorActionPreference
    ----------------------
    Determines how Windows PowerShell responds to a non-terminating
            error (an error that does not stop the cmdlet processing) at the
            command line or in a script, cmdlet, or provider, such as the
            errors generated by the Write-Error cmdlet.

            You can also use the ErrorAction common parameter of a cmdlet to
            override the preference for a specific command.

            Valid values:
        Stop:               Displays the error message and stops
                                    executing.

             Inquire:            Displays the error message and asks you
                                    whether you want to continue.

              Continue:           Displays the error message and continues
              (Default)           executing.

              SilentlyContinue:   No effect. The error message is not
                                  displayed and execution continues without
                                  interruption.

           NOTE: The Ignore value of the ErrorAction common parameter is not
                 a valid value of the $ErrorActionPreference variable. The
                 Ignore value is intended for per-command use, not for use as saved
                 preference.

           Neither $ErrorActionPreference nor the ErrorAction common parameter
           affect how Windows PowerShell responds to terminating errors (those
           that stop cmdlet processing).

           For more information about the ErrorAction common parameter, see
           about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).

    Friday, July 12, 2013 8:43 PM
  • This suggests to me that get-aduser is generating a non-terminating error and its erroraction parameter doesn't work as expected.

    Bill

    Friday, July 12, 2013 8:48 PM
    Moderator
  • However it does seem that the documentation is in error (or at least in need of clarification) regarding the behavior of $ErrorActionPreference:


    $ErrorActionPreference = "SilentlyContinue"
    throw "Test" # error is not output
    

    The error is captured in $Error but is not output.

    Bill

    Friday, July 12, 2013 8:59 PM
    Moderator
  • This suggests to me that get-aduser is generating a non-terminating error and its erroraction parameter doesn't work as expected.

    Bill

    It's really not.  Get-ADUser is throwing a terminating error.  You can test this:

    $ErrorActionPreference = "Continue"
    
    try {
        Get-ADUser -Identity FakeUser
    } catch {
        Write-Host "Caught a terminating error from Get-ADUser."
    }
    
    # For comparison, here's a cmdlet that throws a non-terminating error, to show that it
    # won't trigger the catch block.
    
    try {
        Get-Item C:\Does\Not\Exist
    } catch {
        Write-Host "Caught a terminating error from Get-Item."
    }
    

    Friday, July 12, 2013 9:05 PM
  • Agreed; also it seems that the behavior $ErrorActionPreference is confusing.

    Bill

    Friday, July 12, 2013 9:13 PM
    Moderator
  • It appears to work correctly on Windows 7 RSAT which is where I tested originally.


    ¯\_(ツ)_/¯

    Friday, July 12, 2013 9:55 PM
  • This is interesting.  I searched the Connect site for any existing bug reports on this issue, and turned up this old one (closed as "By Design"), with this comment from Microsoft: http://connect.microsoft.com/PowerShell/feedback/details/436264/erroraction-silentlycontinue-often-does-not-work

    Posted by Microsoft on 5/4/2009 at 10:06 AM                                        

    On any cmdlet, the –ErrorActionPreference variable controls (and / or influences) only non-terminating errors. The $errorActionPreference variable, on the other hand, manages both.
    PS C:\> $ErrorActionPreference = "silentlycontinue"
    PS C:\>  test-path $null

    They certainly described the current behavior of the parameter versus variable, but the documentation doesn't match that explanation.  I tried to submit a new documentation bug, but the Connect site was going screwy and wouldn't post it (but also didn't give me any errors).

    Friday, July 12, 2013 10:01 PM
  • On the earlier subject of the performance of using -ErrorAction Stop and try/catch blocks:

    I got curious about this, since all PowerShell errors (either terminating or non-terminating) are based on .NET Exceptions anyway, and ran this code as a test:

    $sb1 = {
        for ($i = 0; $i -lt 10000; $i++) {
            try {
                Get-Item "C:\Does\Not\Exist\$i" -ErrorAction Stop -ErrorVariable err
            } catch { }
        }
    }
    
    $sb2 = {
        for ($i = 0; $i -lt 10000; $i++) {
            Get-Item "C:\Does\Not\Exist\$i" -ErrorAction SilentlyContinue -ErrorVariable err
        }
    }
    
    Measure-Command -Expression $sb1 | Select-Object -ExpandProperty TotalMilliseconds
    Measure-Command -Expression $sb2 | Select-Object -ExpandProperty TotalMilliseconds
    
    <#
    
    Results:
    
    7633.4037
    
    4251.7335
    
    #>

    So while it's true that it does take nearly twice as long to catch the exception using -EA Stop and try/catch, no one's ever going to notice the difference.  It takes less than 1 millisecond per error either way, on my 5-year-old home computer (Intel Core 2 Duo 3GHz, DDR2 memory).
    • Edited by David Wyatt Sunday, July 14, 2013 10:32 PM edit
    Sunday, July 14, 2013 10:31 PM
  • I could not agree with you more, David.  This type of attitude does not help anyone.  If you (JRV, that is YOU) are here just to prove how smart you are, why even bother?  Most of us are here to learn and share information.  Join the club or get out.  Be a peer or don't be here at all.  I had a major issue with this user before, telling me how everything I was doing was wrong and that I should "do his method instead".  Well...come to find out, the only thing wrong with my code was misplacement of a bracket - I think maybe the feeble "one-liner" mind could not understand my complex code.  Peace, my friend.
    Sunday, January 24, 2016 10:11 PM