Category Archives: PowerShell

suppressing external errors

I’ve been playing with powershell a lot lately. i say playing…  one of the things i keep coming up against is errors when i call external programmes. With a powershell cmdlet, it’s easy to suppress an error; just add

–errorAction silentlyContinue

after the cmdlet, and the pesky red text is quiesced.

Capture1

however, this isn’t possible when calling an external program, so, one way to do it might be to change the ErrorActionPreference variable so that all errors are suppressed:Capture2

 

what am i doing there? fiddling with my default gateway. nothing to see here. move along.

the important bit is that if the routes i am trying to add already exist, it’ll throw a huge amount of crimson mess all over my screen, which i don’t want it to do. temporarily setting the $EAP to silentlyContinue before the loop runs, and returning it afterward will suppress the errors and ensure that the rest of the code will throw errors as intended; thanks to the good people at Get-PSUKUG for suggesting that method.

however, if you write gruesome code that’s all over the place, like what i do, you may find yourself repeatedly calling that construct. it might get old, fast. so luckily there is another way; directing STDERR to null. you what, now?

since the middle ages programs have used three standard communications streams:

  • #0, STDIN, which by default takes input from the keyboard and directs it to the program,
  • #1, STDOUT, which takes the output of the program and directs it to the screen, and
  • #2, STDERR, which takes any error the program produces and again throws it to the screen

 Stdstreams-notitle

lots more about Standard Streams on Wikipedia.

so, what do you do with it? redirect it, in my case, to $null:

Capture3

and hurrah – the ghastly errors are gone.

Advertisements

Exchange 2013: setting diagnostic logging levels the quick way

TL;DR how to set a bunch of logging levels with similar names to a specific level, plus a script that sets *everything* back to the defaults.

 

I’ve got a customer who is having trouble with Exchange 2013 and Active Directory, flip-flopping between DCs. i can see it occurring in the event log, but there’s no suggestion of what the problem might be. No worries, lets just hoik* the logging level up on ADAccess, and have a look at what’s happening.mmmm…

first problem with that; with the demise of anything approaching a usable GUI in exchange 2013, we’ll have to use powershell. it’s the “set-eventloglevel” cmdlet that i need, but usage examples are pretty thin on the ground. in fact, there’s just one.

Set-EventLogLevel -Identity "Exchange01\MSExchangeTransport\SmtpReceive" -Level High

which is peachy, but i don’t know which of the many adaccess logging objects i need. there are quite a few:

image

i don’t fancy running that cmdlet ten times, and my customer fancies it even less. what we need is some powershell magic. Why don’t we get the objects, and then feed them via the pipeline into the set-eventloglevel cmdlet? we can use the get-eventloglevel cmdlet. unfortunately it returns a great long list of objects, so we’ll need to filter them.

image

oh well, worth a try**. to do that we’ll need the where-object cmdlet and the “–like” comparator.

get-EventLogLevel | Where-Object {($_.identity) –like “*adaccess*”}

image

now we can feed that straight into the set-eventlogginglevel cmdlet:

get-EventLogLevel | Where-Object {($_.identity) –like “*adaccess*”} | set-EventLogLevel –level medium

image 

you’ll not want to leave it there, though. that’ll fill your event log up quicksmart. once you’re done, set everything back. the handy “default” radio button that used to work in 2010 is gone:

image

 

so what you’ll need is a little script that puts everything back where you found it. if you run get-eventloglevel you’ll see that nearly everything is set at lowest, but there are one or two exceptions:

image

is that MSExchange RBAC\RBAC that’s set to low, there? god knows. my eyesight isn’t all that. let’s run a bit more powershell and dump out all the objects that aren’t set to lowest:

image

Bugger. that didn’t work. let’s run get-eventloglevel | gm and find out why .level didn’t select the –level parameter:

image

aha – why call your property after the parameter it sets? what we want isn’t called .level, it’s called .eventlevel. duh.

image 

great, so everything needs to be set to “lowest” apart from those objects.

so, we could run a script that sets everything to ”lowest”, and then sets them to”low” afterwards, except… what about those “2”s there. you can’t set a value of 2 with set-EventLogLevel .I’ve tried. there’s two things we could do there, either ignore them, or use the registry powershell provider to set them back to 2 afterward. ignoring them is the easiest way, isn’t it? mm?

 

so my script looks like this:

<# this script returns Exchange 2013 server diagnostic levels to their default.

The first line sets everything but "msexchange oauth\server" and

"msexchange backendrehydration\server" objects to "lowest".

these objects are set to 2 by default, a value that can’t be set using set-EventLogLevel.

you can set them in the registry at

HKLM\currentcontrolset\services\msexchange backendrehydration\diagnostics

and

HKLM\currentcontrolset\services\msexchange oauth\diagnostics

the rest of the script sets the exceptions to their correct level

this script will only work on the local server, obviously#>

Get-EventLoglevel | where-object {($_.eventlevel) -notlike "2"} | set-eventloglevel -level lowest

set-eventloglevel -identity "MSExchange RBAC\RBAC" -level low

set-eventloglevel -identity "MSExchange ADAccess\Topology" -level low

set-eventloglevel -identity "MSExchange ADAccess\Validation" -level low

set-eventloglevel -identity "MSExchangeADTopology\Topology" -level low

set-eventloglevel -identity "MSExchange OAuth\Configuration" -level low

set-eventloglevel -identity "MSExchange BackEndRehydration\Configuration" -level low

how could it be improved? well, adding the two lines to set those values to 2 in the registry would make it quicker, rather than filtering them out. adding in a line for server identity that defaults to the local host would be good. signing it might be a good idea. maybe later.

 

why am i using “–notlike” in the first line, instead of “–ne”? i *think* it’s because the value is an integer, and –ne is interpreting the input as a string… whatever. “-ne” doesn’t work. “-notlike” does.

ttfn.

* yeah, that’s a word. hoik.

** turns out that get-EventLogLevel “msexchange adaccess*” DOES work though…never mind, this way is betterish.