So What's the Deal With the Three Dots?

You know, it's not often that those of us here at the Lync Server PowerShell blog get the chance to show off our knowledge. OK, admittedly, that might be because we don't actually have much knowledge to show off in the first place. Still, it's nice to get the chance every now and then to demonstrate that we do know something, even if that something has very little to do with either Lync Server or with Windows PowerShell.

Good question: what are we talking about? Well, suppose you run the following PowerShell command in the Lync Server Management Shell:

Get-CsImFilterConfiguration –Identity Global

If you do run that command, you'll probably get back output that looks something like this:

Identity : Global

Prefixes : {callto:, file:, ftp., ftp:...}

AllowMessage :

WarnMessage :

Enabled : False

IgnoreLocal : True

BlockFileExtension : False

Action : Allow

Pretty good, except for one thing: note the three dots following the prefixes:

Prefixes : {callto:, file:, ftp., ftp:...}

Are those three dots supposed to mean something? We are so glad you asked that question!

Yes, the three dots do mean something. The three dots are known as an ellipsis (and less commonly known as a suspension point), and are a grammatical device used to denote the fact that there are some missing words in our sentence (or, in this case, in our output). Supposedly, the ellipsis was first used by writers of the Old Norse language somewhere around the year 200 BC, which means that no sooner did people begin to learn how to write than they were already looking for ways to write less. Did the Old Norse also invent OMG, LOL, and BFF? That remains a source of heated debate within the academic community.

Note. In all fairness, we should probably point out that Old Norse looked a lot like this:

En er fram liðu stundir, þá ójafnaðisk mannfólkit: váru sumir góðir ok rétt trúaðir, en myklu fleiri snerusk eptir girndum heimsins ok órœktu guðs boðorð, ok fyrir því drekti guð heiminum í sjávargangi ok ǫllum kvikvendum heimsins nema þ eim er í ǫrkinni v á ru me ð N ó a.

With that in mind, it might not be too surprising that the Old Norse almost immediately began looking for ways to leave out words.

Oh, and in case you're wondering, trúaðir is a past participle, nominative plural masculine of trúa (ð), meaning to have faith in.

But, then again, you probably already knew that.

To be honest, we don't know whether or not the Old Norse invented Windows PowerShell. We don't think they did but every now and then you see a PowerShell command that looks like this:

pclip | %{[Regex]::Split($_,'(.{0,60}(?:\s|$))')}|%{if($_){"> $_"}}

Kind of makes you wonder, doesn't it?

Whether or not the Old Norse invented PowerShell, it does appear that the Windows PowerShell team was heavily influenced by the Old Norse; after all, PowerShell consistently uses the ellipsis to indicate the fact that information has been omitted from the display. Remember this line of output:

Prefixes : {callto:, file:, ftp., ftp:...}

Well, just like it did in Old Norse, the ellipsis indicates that there's more information. That output kind of implies that there are only four items listed in the Prefixes property: callto:, file:, ftp., and ftp:. However, our global IM filter configuration actually contains 17 prefixes:

callto:

file:

ftp.

ftp:

gopher:

href

http:

https:

ldap:

mailto:

news:

nntp:

sip:

sips:

tel:

telnet:

www*:

The ellipsis indicates that there are more prefixes in the Prefix property than the four that are shown. They just wouldn't all fit on screen.

Any other questions about the ellipsis before we call it a day? Hey, that's one we never thought of: how do you deal with the ellipsis in Windows PowerShell? That sounds like something that might actually be worth knowing about.

Option 1: The ExpandProperty parameter

As you could probably guess, trying to work around the ellipsis can be a little tricky; in large part, it depends on how many different properties you need to work with. For example, let's suppose we're only interested in the Prefixes property for the global IM filter configuration settings. In other words, we'd be perfectly happy with output that looks like this:

callto:

file:

ftp.

ftp:

gopher:

href

http:

https:

ldap:

mailto:

news:

nntp:

sip:

sips:

tel:

telnet:

www*:

If that's the case then we have a very simple solution for you: the Select-Object cmdlet and the ExpandProperty parameter. As you probably know, the Select-Object cmdlet enables you to specify the property values you want to display. (If you didn't know that you should take a peek at our article Dealing with Information Overload, Part 1.) In turn, the ExpandProperty parameter lets you "expand" the values stored in a single property. (And yes, we did say "a single property." We'll discuss that limitation in a minute or two.) For example, what do you think will happen if you run this command:

Get-CsImFilterConfiguration -Identity Global | Select-Object -ExpandProperty Prefixes

If you said, "I bet all the prefixes stored in the Prefixes property will be displayed on screen," well, congratulations; you're absolutely right:

callto:

file:

ftp.

ftp:

gopher:

href

http:

https:

ldap:

mailto:

news:

nntp:

sip:

sips:

tel:

telnet:

www*:

And you thought this was going to be hard! As you can see, it's not hard at all.

Option 2: Using ForEach-Object

But (and there's always a “but,” isn’t there?) that's due, in part, to the fact that we only cared about one property for one collection of IM filter configuration settings. Suppose we have two collections of IM filter configuration settings, one at the global scope and one at the site scope, and we'd like to see all the prefixes for both of these collections. Is this command going to help much:

Get-CsImFilterConfiguration | Select-Object -ExpandProperty Prefixes

Well, it kind of depends on what you mean by "help." This is the output we get:

callto:

file:

ftp.

ftp:

gopher:

href

http:

https:

ldap:

mailto:

news:

nntp:

sip:

sips:

tel:

telnet:

www*.

callto:

file:

ftp.

ftp:

gopher:

href

http:

https:

ldap:

mailto:

news:

nntp:

sip:

sips:

tel:

telnet:

www*.

test:

As it turns out, all the prefixes for all the collections are there; it's just difficult to tell where one collection leaves off and the other begins, and even more difficult to tell which collection is which. No problem, you say? We'll just expand the Identity property along with the Prefixes property, you say? You mean like this, right:

Get-CsImFilterConfiguration | Select-Object -ExpandProperty Identity, Prefixes

OK, let's run that up the flagpole and see if anyone salutes:

Select-Object : Cannot convert 'System.Object[]' to the type 'System.String'

required by parameter 'ExpandProperty'. Specified method is not supported.

At line:1 char:45

+ Get-CsImFilterConfiguration | select -expand <<<< Identity, pref*

    + CategoryInfo : InvalidArgument: (:) [Select-Object], ParameterBindingException

    + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.SelectObjectCommand

Hmmm, not exactly the output we were hoping for. That's because PowerShell only lets you expand a single property. (If you don't believe us, run the command Get-CsImFilterConfiguration | Select-Object -ExpandProperty * and see what happens.) And before you ask, no, this command won't work either:

Get-CsImFilterConfiguration | Select-Object Identity, -ExpandProperty Prefixes

If you run that command Select-Object will ignore the Identity property altogether and just expand the Prefixes property.

Which leaves us right back where we started.

But here's a little tip for you. Any time we find ourselves stymied by Windows PowerShell we say to ourselves, "What would the Old Norse do in this situation?" We have a feeling that the Old Norse would do something like this:

Get-CsImFilterConfiguration | ForEach-Object {$_.Identity; $_.Prefixes; Write-Host}

What's going on here? Well, to begin with, we're using Get-CsImFilterConfiguration to return all the IM filter configuration collections currently in use in our organization. We're then taking the returned information, piping it to the ForEach-Object cmdlet, and asking ForEach-Object to do three things:

· Take the first collection of settings, and display the value of the Identity property ($_.Identity).

· Display the values stored in the Prefixes property ($_.Prefixes).

· Print a blank line (Write-Host), then grab the second collection of settings and repeat the process.

The net result is output that looks a little like this:

Global

callto:

file:

ftp.

ftp:

gopher:

href

http:

https:

ldap:

mailto:

news:

nntp:

sip:

sips:

tel:

telnet:

www*.

Site:Redmond

callto:

file:

ftp.

ftp:

gopher:

href

http:

https:

ldap:

mailto:

news:

nntp:

sip:

sips:

tel:

telnet:

www*.

test:

Those Old Norse thought of everything, didn't they?

Option 3: Out-GridView

The problem we ran into when working with the IM filter configuration cmdlets is that there were too many values stored in the Prefixes property to display onscreen. Sometimes you'll encounter a different problem: a property will contain only a single property value, but that lone value will be too long to fit onscreen. Need an example of what we're talking about? OK, try running this command:

Get-CsWindowsService

You'll no doubt get output that looks like this:

Status Name ActivityLevel

------ ---- -------------

Running MASTER

Running REPLICA

Running RTCSRV Incoming Requests per Second=0,Messages In ...

Running RTCCAA Concurrent Calls=0

Running RTCCAS Concurrent Conferences=0

Running RTCRGS Current Active Calls=0

Running RTCPDPAUTH

Running RTCPDPCORE Active Client Connections=0,Active Edge Co ...

Running RTCCPS Total Parked Calls=0

Running RTCIMMCU Active Conferences=0,Connected Users=0

Running RTCDATAMCU Active Conferences=0

Running RTCAVMCU Number of Conferences=0,Number of Users=0

Running RTCASMCU Active Conferences=0,Connected Users=0

Running RTCACPMCU

Running RTCMEDSRV Current Outbound Calls=0,Current Inbound ...

Running RTCMEETINGMCU Active Conferences=0

Running FTA

Running RtcProv

As you can see our old friend the ellipsis pops up several different times in the ActivityLevel property. So will the ForEach-Object technique we just showed you take care of the problem here? You bet it will; just run this command and see what happens:

Get-CsWindowsService | ForEach-Object {$_.Name; $_.Status; $_.ActivityLevel; Write-Host}

But in a case like this one (that is, a case when we're not dealing with a multi-valued property) there's another little trick you might find useful: the Out-Gridview cmdlet.

Note. If you take a look at the article on multi-valued properties you might be thinking, "Wait a minute: isn't that article awfully similar to this article?" Well, it's definitely similar. However, based on some questions we've received over the past couple of months, we decided to do this second article, one that goes a bit beyond the simple ExpandProperty approach we discussed in the original article. As we've found out, ExpandProperty won't always work.

Out-GridView (which we really should do an article on one of these days) is one of the more useful yet less-known Windows PowerShell cmdlets. When Windows PowerShell was first released, users loved the technology itself; however, they didn't always love the console window output. As a result, an entire cottage industry (no doubt based on techniques originally pioneered by the Old Norse) arose devoting to creating functions and scripts that enabled users to output their data to Microsoft Excel.

In response to this, when Windows PowerShell 2.0 was released it included a new cmdlet, Out-Gridview, which – wonder of wonders! – could display data in a grid view. It wasn't Excel, needless to say, but it was definitely Excel-like output. And you could use it on any computer running Windows PowerShell, even if Excel wasn't installed on that computer.

And in response to that – well, in response to that nothing much really happened: hardly anybody uses Out-Gridview. Be that as it may, it can still be a handy little cmdlet to know about. To see what we mean, try running this command:

Get-CsWindowsService | Out-Gridview

You should get back something that looks like this:

Well, what do you know: complete, and completely readable, output for the ActivityLevel property. Could it get any better than that?

At any rate, Out-Gridview is just something to keep in mind. It's not always going to work; for example, if you try using it with the Get-CsImFilterConfiguration cmdlet (or any other cmdlet that includes multi-valued properties) you'll be a bit disappointed:

That's all we have time for in this article. Thank you for reading and, as the old Norse used to say, "Knúta flesk búfé!"

Note. OK; as all you fluent speakers of Old Norse know, that actually translates as "Knuckle-boned bacon farm cattle." But you know what we mean.