5

I'm having trouble googling up a clear answer on this. Are there any practical differences between, for example, throw 'temper tantrum' and Write-Error 'temper tantrum' -ErrorAction Stop?

They both generate terminating errors and set $? to False. I can see that there are differences in the CategoryInfo and FullyQualifiedErrorId. The operative word is practical. Do they have any different effects? Are there reasons to prefer one over the other in particular situations?

Adi Inbar
  • 12,097
  • 13
  • 56
  • 69
  • possible duplicate of [When should I use Write-Error vs Throw?](http://stackoverflow.com/questions/9294949/when-should-i-use-write-error-vs-throw) – Andrew Savinykh Jun 27 '13 at 23:25
  • Nope, not a duplicate. My question is more specific. The main difference between **Write-Error** and **throw** is that **throw** generates a terminating error, and **Write-Error** by default does not. I was already aware of that. My question was specifically whether there are any differences in functionality if "-ErrorAction Stop" is used to make Write-Error generate a terminating error. I now see (due to the hint in Ansgar's answer) that they populate $error with different object types. What I'd like to know is whether there are any pros, cons, caveats, or different uses between the two. – Adi Inbar Jun 28 '13 at 00:47

1 Answers1

10

throw generates a terminating error, Write-Error without -ErrorAction Stop would generate a non-terminating error. Since -ErrorAction Stop turns the non-terminating into a terminating error, the two instructions are basically the same.

There are differences, though. throw <expression> populates $error[0].TargetObject with <expression>, while Write-Error <expression> -ErrorAction Stop does not.

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
  • That does point me in a direction, though it seems rather confusing. I see that in fact there are a lot of differences in the way $error gets populated, apparently because **throw** unshifts an ErrorRecord object onto the $error array, whereas **Write-Error -ErrorAction Stop** unshifts an ActionPreferenceStopException object. Oddly enough, though, when **Write-Error** creates a *non*-terminating error, it adds an ErrorRecord object to $error. So, back to my emphasis on the word "practical": in what kinds of situations would either one be more suitable or have different behavior than the other? – Adi Inbar Jun 28 '13 at 00:38
  • In fact, from what I'm reading at MSDN, apparently the error generated by **Write-Error -ErrorAction Stop** technically isn't even a terminating error, though it does terminate the script (http://msdn.microsoft.com/en-us/library/system.management.automation.errorrecord%28v=vs.85%29.aspx, http://msdn.microsoft.com/en-us/library/system.management.automation.actionpreferencestopexception%28v=vs.85%29.aspx). Still wondering if there are any practical differences in use because of this. – Adi Inbar Jun 28 '13 at 00:55
  • 5
    This would be far from the first time someone found multiple different ways to do the same thing in PowerShell. :-) Using `throw` is the canonical way to express terminating errors and `Write-Error` is the canonical way to express non-terminating errors (doh that one file out of 1000 is in use - I'll note a non-terminating error but continue processing the other 999). It is really just by virtue that all cmdlets implement the ubiquitous parameter -ErrorAction that this corner case (Write-Error -ea Stop) exists. – Keith Hill Jun 28 '13 at 01:18
  • 2
    @AdiInbar I would always use `throw` for generating a terminating error. Not only is it shorter, but it's also a syntax well-known from other languages, and it's more self-explanatory with respect to what it does. I'd use `Write-Error` only for what its name suggests: to write error messages to the error stream. – Ansgar Wiechers Jun 28 '13 at 10:03
  • @KeithHill Good point - in fact, that explains the oddness I commented above: using **-ea Stop** with Write-Error does terminate the script, but I guess it's not really there as part of the intended behavior of Write-Error, it's there because it's a common parameter, and actually circumvents the intended behavior of Write-Error. However, what I like about using `Write-Error -ea Stop` is that it lets you set the error category. Also, it lets you define the entire ErrorRecord object. Is there anyway to create a genuine terminating error and also control ErrorRecord and Category? – Adi Inbar Jul 10 '13 at 22:50
  • 1
    @AdiInbar Yes. If you're writing an advanced function, you can (and should) use `$pscmdlet.WriteError()` which takes an ErrorRecord that you create. You can then specify the Category, etc. – Keith Hill Jul 11 '13 at 21:26
  • You can also construct an exception, for example `Management.Automation.CommandNotFoundException` and an errorrecord `Management.Automation.ErrorRecord`, link them together, fill out whatever fields you want and throw the exception you created. – Χpẘ Jul 12 '13 at 02:53
  • Thanks for all the info. I was hoping to get some examples like "'throw' works best if you're trying to do such-and-such, but 'Write-Error' is more effective if you're trying to do this-and-that, because..." - that's what I mean by *practical* differences. I'll accept this answer since it pointed me in a direction that helped me understand the difference in how they operate, and improve the way I handle errors in my scripts. But if anyone can think of any practical examples of where one works better than the other for a particular purpose, please add more answers, and I'll upvote them. Thanks! – Adi Inbar Jul 13 '13 at 20:27