• Haiku #163

    Who needs doughnuts when

    You have diagnostic logs?

    You mean besides us?

     

    Today is Friday, July 29, 2011, a date that will live in infamy. Why? Well, several weeks ago the author of today's haiku was in a fast food restaurant when he saw a poster that read like this:

     

    Come Celebrate National Doughnut Day with Us!

    July 30, 2011

     

    Needless to say, that sparked his interest. After all, here was a major holiday – a day devoted to doughnuts, for crying out loud – and he had never even heard of it. As you might expect, the author of today's haiku took a careful look at the poster, and memorized the date of National Doughnut Day: July 30.

     

    Is it possible that the author of today's haiku made a mistake and got the date wrong? No. After all, when it comes to major holidays, people never get the date wrong. The Fourth of July always comes on July 4th. Christmas always comes on December 25th. Easter always comes on the first Sunday following the first full moon following the vernal equinox.

     

    Note. Incidentally, that last part, the one about Easter, is not only true, but the author of today's haiku didn't have to look it up: he actually knows when Easter comes. As it turns out, he's only half as dumb as he looks.

     

    So there.

     

    At any rate, there really is a National Doughnut Day: it was started in 1938 by the Salvation Army in order to serve as both a fund raiser and to honor the Salvation Army volunteers who handed out doughnuts to soldiers on the front lines during World War I. In fact, the only thing wrong with National doughnut Day is this: it doesn't actually fall on July 30th after all. Instead, National Doughnut Day comes on the first Friday in June every year. The fast food restaurant was wrong (!) and, as a result, the author of today's haiku missed National Doughnut Day by nearly two months.

     

    So is today, the day when he discovered the real date for National Doughnut Day, the worst day of his life? Yes, without a doubt.

     

    In case you're wondering, the author of today's haiku was planning to celebrate National Doughnut Day by trying out some of the more … unusual … flavors of doughnuts that, for some reason, have been created. Without doing much research he was able to uncover some … interesting … doughnut flavors, such as:

     

    ·         Habanero pepper jelly

    ·         Garlic glazed

    ·         Wasabi and seaweed

    ·         Hibiscus

    ·         Pork floss

     

    Pork floss, by the way, is "… a dried meat product that has a light and fluffy texture similar to coarse cotton." And yes, based on that description, a dental floss doughnut would probably be just as good.

     

    Plus you wouldn't have to brush your teeth afterwards!

     

    At any rate, the author of today's haiku is feeling a bit depressed today. And when he's down in the dumps, there's only one thing that can cheer him up: doughnuts. But seeing as how he doesn't actually have any doughnuts today, he decided to talk about the CsDiagnosticConfiguration cmdlets (Get-CsDiagnosticConfiguration, New-CsDiagnosticConfiguration, Remove-CsDiagnosticConfiguration, and Set-CsDiagnosticConfiguration).

     

    As you might have guessed, the CsDiagnosticConfiguration cmdlets are used to manage your diagnostic configuration settings in Microsoft Lync Server. Which leads to one obvious question: what in the world are diagnostic configuration settings? Well, if you enable logging in Lync Server then, by default, any traffic traveling to or from any domain or URI is included in the log files. Makes sense, right?

     

    Right. Unless, of course, it doesn't make sense. After all, in some organizations, that could result in your logs being filled with tons of information that you don't really care about. For example, suppose you're having problems with traffic involving one particular domain. In a case like that, you might want to log only traffic to and from that domain. That way, you can look through the logs and – with any luck –- pinpoint the problem, all without having to weed through information logged from every other domain you communicate with.

     

    That's where the diagnostic configuration settings come in. These settings allow you to specify a list of domains/URIs that will be logged; if such a list exists, then only the information about the traffic flowing to and from the domains shown on that list will end up in the log files.

     

    Well, that should just about wrap things up for – oh, good point: how do you add domains/URIs to a collection of diagnostic configuration settings? Well, as it turns out, to do this you need to create a diagnostic filter for the domain/URI and then add that item to the diagnostic configuration settings. For example, here's how we can add fabrikam.com to the global diagnostic configuration settings:

     

    $x = New-CsDiagnosticsFilter -Fqdn "*.fabrikam.com" -Enabled $True

    Set-CsDiagnosticConfiguration -Identity global -Filter $x

     

    As you can see, there's nothing too terribly difficult about this. We start off by using the New-CsDiagnosticsFilter cmdlet to set *.fabrikam.com as the fully qualified domain name of the domain to be included in the log files. (Why *.fabrikam.com? See haiku #114 for details.) In addition, we set the Enabled property to True; otherwise our new filter would exist, but wouldn't actually do anything. And then, finally, we use this command to set the Filter property of the global settings to, well, our new filter:

     

    Set-CsDiagnosticConfiguration -Identity global -Filter $x

     

    That's not too bad, right? Now, what it you want to add a second domain to that filter? Admittedly, the method for doing that is a bit clunky, but it works:

     

    $x = (Get-CsDiagnosticConfiguration -Identity global).Filter

    $x.Fqdn.Add("*.contoso.com")

     

    Set-CsDiagnosticConfiguration -Identity global -Filter $x

     

    As you can see, what we need to do here is first use the Get-CsDiagnosticConfiguration cmdlet to create an object reference ($x) to the global settings. Note that we enclose the call to Get-CsDiagnosticConfiguration in parentheses and then tack on .Filter:

     

    $x = (Get-CsDiagnosticConfiguration -Identity global).Filter

     

    Why do we do that? That's easy: that way we can retrieve just the Filter property, which is the only property we care about right now.

     

    After that, we use the Add method to add *.contoso.com to the collection of filters, then use the Set-CsDiagnosticConfiguration cmdlet to write these changes back to Lync Server.

     

    What will that do? That will give us a collection of diagnostic configuration settings that look like this:

     

    Fqdn                         : {*.fabrikam.com, *.contoso.com}

    Uri                          : {}

    Enabled                      : True

    ExcludeRegisterMessages      : False

    ExcludeConferenceMessages    : False

    ExcludePresenceNotifications : False

    ExcludeSubscriberMessages    : False

     

    Incidentally, if you run the command Get-CsDiagnosticConfiguration without any parameters you'll get output that looks like this:

     

    Identity     : global

    Filter       : Fqdn=IList<System.String>;Uri=IList<System.String>;Enabled=

                   True;ExcludeRegisterMessages=False;

                   ExcludeConferenceMessages=False;ExcludePresenceNotifications=

                   False;ExcludeSubscriberMessages=False

    LoggingShare :

     

    And yes, that does look like you've had one too many wasabi and seaweed doughnuts, doesn't it?

     

    Note. For those of you who like to keep track of this sort of thing, one wasabi and seaweed doughnut would be one too many.

     

    If you'd like to actually see the domains/URIs that are included in your filter, you need to run this command instead:

     

    Get-CsDiagnosticConfiguration | Select-Object –ExpandProperty Filter

     

    That will give you output like this:

     

    Fqdn                         : {*.fabrikam.com, *.contoso.com}

    Uri                          : {}

    Enabled                      : True

    ExcludeRegisterMessages      : False

    ExcludeConferenceMessages    : False

    ExcludePresenceNotifications : False

    ExcludeSubscriberMessages    : False

     

    And what if you have a whole bunch of domains included in the Fqdn property, and they end up being truncated onscreen like this:

     

    Fqdn                         : {*.fabrikam.com, *.contoso.com, "*.wing...}

     

    First of all, don't panic. Second of all, run this command:

     

    Get-CsDiagnosticConfiguration | Select-Object –ExpandProperty Filter | Select-Object –ExpandProperty Fqdn

     

    That will show you your list of domains:

     

    *.fabrikam.com

    *.contoso.com

    *.wingtiptoys.com

    *.northwindtraders.com

    *.cpandl.com

    *.alpineskihouse.com

     

    Etc., etc.

     

    Ah, another good question: How can you enable logging for every domain except contoso.com? Well, the truth is, you can't: the Enabled property enables (or disables) all the domains and URIs included in the Filter. But that's OK. If you don't want to log data for contoso.com then just remove contoso.com from the filter:

     

    $x = (Get-CsDiagnosticConfiguration -Identity global).Filter

    $x.Fqdn.Remove("*.contoso.com")

     

    Set-CsDiagnosticConfiguration -Identity global -Filter $x

     

    See? A little clunky, but no doubt you've seen far, far worse, right?

     

    As we've already seen, you can use the Get-CsDiagnosticConfiguration cmdlet to retrieve information about your diagnostic configuration settings. If you so desire, you can also use the New-CsDiagnosticConfiguration cmdlet to create a new collection of settings at the site scope. For example:

     

    $x = New-CsDiagnosticsFilter -Fqdn fabrikam.com -Enabled $True

     

    New-CsDiagnosticConfiguration -Identity site:Redmond -Filter $x

     

    And if you no longer need a separate collection for the Redmond site? Then it's Remove-CsDiagnosticConfiguration to the rescue:

     

    Remove-CsDiagnosticConfiguration -Identity site:Redmond

     

    All in all, not so bad.

     

    That's all we have for today. If any of you out there were also under the delusion that tomorrow would be National Doughnut Day, well, we apologize for being the bearers of bad news. But look on the bright side: July 30th is both Independence Day in the country of Vanuatu and the 592nd anniversary of the First Defenestration of Prague. So, all things considered, it should be a pretty fun weekend anyway.

     

    See you on Monday.

     

     

     

     

     

  • Haiku #162

    The next best thing to

    Getting a haircut: Trusted

    Application pools.

     

    Well, the author of today's haiku is back from his one-day journey to the TechReady conference. His overall impressions of the conference? Well, the mini-cannoli were surprisingly good, but the pasta salad in balsamic vinaigrette was a major disappointment. After all, if something is in a balsamic vinaigrette shouldn't there actually be some balsamic vinaigrette there, somewhere?

     

    As for the presentation he assisted on, well, the presentation was titled Extreme PowerShell and was aimed at people who, having mastered the basics of Lync Server PowerShell, were ready to take their scripting skills to the next level. However, when the author's co-presenter asked the crowd how many people had even opened the Lync Server Management Shell (let alone did anything with it) only 6 people raised their hands. And when he asked how many people had written Windows PowerShell scripts of any kind (not just Lync Server PowerShell scripts), only four people raised their hands. Interestingly enough, that's what we said: uh-oh.

     

    Oh, well: easy come, easy go. It was still way better than working, and with any luck, we managed to impart a little knowledge about Lync Server PowerShell, and how you can extend its capabilities, along the way. More importantly, the author of today's haiku also got a wristband that will allow him to attend tonight's Attendee Party. How exciting is that going to be? Well, here's one quote from the party flyer:

     

    "Need a haircut? There's even a salon and spa where you can take advantage of their express services during the party."

     

    Wow, you can go to a party and get your hair cut! And people keep think that Microsoft employees don't know how to have a good time.

     

    Here's another quote from the flyer:

     

    "The on-campus Company Store will be open during the party, providing you with the perfect opportunity to purchase Microsoft-branded merchandise, software, and hardware for yourself, your family, and friends."

     

    Whoa. Now the author of today's haiku is thinking that maybe he won't go to the party. After all, it is possible to have too much fun and too much excitement.

     

    That's especially true when you consider the subject of today's haiku: the CsTrustedApplicationPool cmdlets!

     

    Note. Sure, we can tell you what individual cmdlets are included in the CsTrustedApplicationPool cmdlets: Get-CsTrustedApplicationPool, New-CsTrustedApplicationPool, Remove-CsTrustedApplicationPool, and Set-CsTrustedApplicationPool.

     

    So what exactly do you do with the CsTrustedApplicationPool cmdlets? Well, in Microsoft Lync Server 2010, a trusted application is a third-party application that is granted trusted status and is allowed to run as if it was a built-in component of Lync Server. Trusted applications are allowed to run in any Lync Server pool. However, it's highly recommended that you create a separate trusted applications pool and run your trusted applications from within that pool. If you do that, you can more-easily manage all those applications, doing everything from specifying whether or not your trusted applications require authentication and whether or not the pool should take part in the Lync Server replication cycle. As you might have guessed, this is where the CsTrustedApplicationPool cmdlets come into play.

     

    Note. We know how incredibly cool that sounds, but just take a deep breath and try to relax. Like we said earlier, it's possible to have too much fun and too much excitement.

     

    Let's start out by showing you a simple command that creates a new trusted application pool:

     

    New-CsTrustedApplicationPool -Identity trustedpool.litwareinc.com -Registrar atl-cs-001.litwareinc.com -Site Redmond

     

    As you can see, that's actually a pretty simple little command. All we do there is call the New-CsTrustedApplicationPool cmdlet, specifying the Identity of the pool, the Registrar associated with the pool, and the site where the pool is homed. None of that is too-terribly difficult, but there are a few things you should know about these parameters. First, the Identity parameter should be the fully qualified domain name of the computer that is going to host the trusted applications. New-CsTrustedApplicationPool is actually a pretty easy cmdlet to get along with: it will accept pretty much any value for the Identity parameter, regardless of whether that value points to a real computer or not. But your trusted application won't actually work if the identity points to a mythical computer.

     

    Incidentally, it’s recommended that you run trusted applications on a dedicated computer. It’s generally not a good idea to run SQL Server, Exchange, SharePoint, Lync Server, and all your trusted applications on one machine.

     

    In fact, it's probably safe to say that that is never a good idea.

     

    Now, what about the Registrar parameter? The truth is, you don't have to include a Registrar when creating a trusted application pool; the cmdlet will run just fine without it. However, once again, your trusted application won't work unless it's associated with a Registrar.

     

    Note. What's that? You say you forgot to associate your trusted application with a Registrar? Oh, bother. Well, don't worry about it; after all, that's what the Set-CsTrustedApplicationPool cmdlet is for:

     

    Set-CsTrustedApplicationPool –Identity TrustedApplicationPool:trustedpool.litwareinc.com –Registrar atl-cs-001.litwareinc.com

     

    Oh, yeah: good observation. When we created our trusted application pool we gave it the Identity trustedpool.litwareinc.com. However, notice the Identity we used with the Set-CsTrustedApplicationPool cmdlet:

     

    –Identity TrustedApplicationPool:trustedpool.litwareinc.com

     

    What's the deal there?

     

    Well, the deal there is relatively simple. When you create a new pool you use the fully qualified domain name of the computer that will host the pool as the Identity. Once the pool is created, however, the Identity is prefaced with TrustedApplicationPool:. As for the original Identity, it becomes the value of the PoolFqdn property:

     

    Identity             : TrustedApplicationPool:trustedpool.litwareinc.com

    Registrar            : atl-cs-001.litwareinc.com

    FileStore            :

    ThrottleAsServer     : True

    TreatAsAuthenticated : True

    OutboundOnly         : False

    RequiresReplication  : True

    AudioPortStart       :

    AudioPortCount       : 0

    AppSharingPortStart  :

    AppSharingPortCount  : 0

    VideoPortStart       :

    VideoPortCount       :

    Applications         : {}

    DependentServiceList :

    ServiceId            : redmond-ExternalServer-1

    SiteId               : site:Redmond

    PoolFqdn             : trustedpool.litwareinc.com

    Version              : 5

    Role                 : TrustedApplicationPool

     

    As you can see, there are a whole bunch of other properties that can be configured on a trusted application pool. We're not going to discuss all these properties today, but we will briefly explain three of them:

     

    ·         ThrottleAsServer. This property determines how many simultaneous connections are allowed between trusted applications and the server. If you set this property to True you will be allowed a larger number of connections than if you set it to False. In other words, if performance is an issue then set ThrottleAsServer to False.

    ·         TreatAsAuthenticated. If set to True, then trusted applications within the pool will be treated as having already been authenticated, and will be able to connect to the server without having to provide credentials. If set to False, then trusted applications must be authenticated whenever they connect to the server.

    ·         OutboundOnly. If set to True, then trusted applications within the pool are not allowed to initiate contact with the server. Instead, they must wait for the server to contact them.

     

    As you might expect, you can set these property values at the time you create a trusted application pool:

     

    New-CsTrustedApplicationPool -Identity trustedpool.litwareinc.com -Registrar atl-cs-001.litwareinc.com -Site Redmond –ThrottleAsServer $False –TreatAsAuthenticated $False –OutboundOnly $True

     

    Or, you can set these property values any time after the pool has been created:

     

    Set-CsTrustedApplicationPool -Identity TrustedApplicationPool:trustedpool.litwareinc.com –ThrottleAsServer $False –TreatAsAuthenticated $False –OutboundOnly $True

     

    Oh, yeah: after you run either the New-CsTrustedApplicationPool or the Set-CsTrustedApplicationPool you should also run the Enable-CsTopology cmdlet. How much trouble is that going to be? Not too much:

     

    Enable-CsTopology

     

    As you might expect, the Get-CsTrustedApplicationPool cmdlet enables you to return information about your trusted application pools. For example, here's how you get information about all your pools:

     

    Get-CsTrustedApplicationPool

     

    And here’s how we can get information about a single pool:

     

    Get-CsTrustedApplicationPool –Identity trustedpool.litwareinc.com

     

    Note. Wait, didn't we say that after a pool has been created it gets a new Identity, one like TrustedApplicationPool:trustedpool.litwareinc.com? Well, yes, we did say that, and the pool really does get a new Identity. However, the CsTrustedApplicationPool cmdlets do allow you to leave off the TrustedApplicationPool prefix when specifying the Identity.

     

    And even though we are trying to keep the excitement level down a bit today, here's a command that returns all the trusted application pools that require replication:

     

    Get-CsTrustedApplicationPool | Where-Object {$_.RequiresReplication –eq $True}

     

    And here's one that lets you see all the pools that are not currently associated with a Registrar:

     

    Get-CsTrustedApplicationPool | Where-Object {$_.Registrar –eq $Null}

     

    And if trusted application pools are just too exciting for you to deal with, hey, no problem; just use Remove-CsTrustedApplicationPool to remove those pools. You can remove pools one at a time:

     

    Remove-CsTrustedApplicationPool –Identity trustedpool.litwareinc.com

     

    Or you can remove them all in one fell swoop:

     

    Get-CsTrustedApplicationPool | Remove-CsTrustedApplicationPool

     

    It's up to you. Just remember that removing a trusted application pool also removes any trusted applications, trusted application computers, and trusted application endpoints associated with that pool.

     

    And yes, that would be a fun activity to do at the Attendee Party, wouldn't it? Not quite as much fun as getting your haircut, true. But probably the next best thing.

     

    See you tomorrow.

     

     

     

  • Haiku #161

    Do you trust that Web

    Server? Of course; it has a

    Trusted CA cert.

     

    What? The Lync Server what of the day? Haiku?!? What in the world are you –

     

    Oh, right: the Lync Server PowerShell haiku of the day. You'll have to forgive the author of today's haiku: he's a bit out of it today, even more so than usual. Why? Well, as it turns out, today just happens to be TechReady 13, an internal technical conference for Microsoft support personnel.

     

    Note. How exciting is TechReady? Does this answer your question: "[TechReady] is a technical training and readiness event aligning our customer-facing technical field with the SMSG execution strategy."

     

    You know what? That's exactly what we said.

     

    Incidentally, as near as we can tell, SMSG is short for Sales, Marketing, Services, IT & Operations Group. (Well, it's kind of short for that.) Do these people really deserve to be executed? Well, not all of them …

     

    Another note. No, the execution strategy does not involve that kind of execution. That was just a joke.

     

    As you might recall, the author of today's haiku has spoken at TechReady in the past; this time around, however, he wasn't going to even attend the conference, let alone do anything there. At least he didn't intend to until yesterday afternoon, when, thanks to other people being called out of town, he suddenly got pressed into action, being asked to help out with a presentation on Extreme PowerShell for Lync Server. (Cool title, huh?) His reward for agreeing to help out in a pinch like this? He got to stay up until 1:00 in the morning working on the slides for the presentation, and then, as if that wasn't reward enough, got to get up four hours later to continue working on the presentation. Pretty cool, huh?

     

    Note. Yes, that does sound like burning the candle at both ends. The only problem with that analogy is that the author of today's haiku doesn't really have a candle that burns much at all these days. Maybe he was just smoldering a little at both ends.

     

    At any rate, because he didn't get everything finished last night, he got to get up early and head in for work at 5:30 in the morning. You know what's the best thing about going to work at 5:30 in the morning? That's right: absolutely nothing. But, then again, the author of today's haiku would probably say the same thing about going to work at 8:30 in the morning, 11:30 in the morning, 2:30 in the afternoon, etc., etc.

     

    Speaking of today's haiku, and recognizing that the author of said haiku needs to get that haiku done so he can actually go to TechReady, today we're going to talk about the New-CsWebTrustedCACertificate cmdlet, the cmdlet voted Sexiest Cmdlet of 2011 by the editors of People magazine.

     

    Note. Really? Beats us; to be honest, we don't read People all that often. But it probably would be voted Sexiest Cmdlet of 2011 by the editors of People magazine if the editors of People magazine actually voted on things like that. But they probably have a lot of other things to do.

     

    So what exactly is the New-CsWebTrustedCACertificate cmdlet, and what makes it so sexy? Well, each Web Server employed by Microsoft Lync Server 2010 has a property named TrustedCACerts. This property represents a collection of all the certification authorities trusted by Microsoft Lync 2010 Phone Edition: if you've obtained a certificate from one of these certification authorities then your Lync Phone Edition phone is able to make a secure connection to Lync Server. So how do you let Lync Server know that you have a new trusted certification authority (CA)? That's easy. First, you add the certificate chain for that CA to the local computer’s certificate store. After you have verified that the certificate chain has been installed, you then use – tah-dah! – the New-CsWebTrustedCACertificate cmdlet to create a certificate ID object that can be added to a collection of Web Services configuration settings.

     

    In other words, you run a pair of commands similar to these:

     

    $x = New-CsWebTrustedCACertificate -Thumbprint "D543DFF74FEEA425162FD25F342786F1AB453BB3" -CAStore TrustedRootCA

     

    Set-CsWebServiceConfiguration -Identity site:Redmond -TrustedCACerts @{Add=$x}

     

    As you can see, in the first command we call the New-CsWebTrustedCACertificate cmdlet followed by the certificate's thumbprint and its location in the certificate store. (The CAStore can be set to TrustedRootCA, IntermediateCA, or ThirdPartyCA.) As for the thumbprint of the certificate, we recognize that there's an off-chance that you haven't memorized the thumbprints of all your certificates. (Should you have memorized the thumbprints of all your certificates? Well, that's obviously another story.) But that's fine; after all, you can retrieve information (including the thumbprint value) for all your Lync Server certificates simply by running this command:

     

    Get-CsCertificate

     

    Note that, when you call New-CsWebTrustedCACertificate, you need to store the result object in a variable (in this case $x); if you don't, that new trusted CA certificate will disappear just as fast as it gets created. After you've stashed the certificate information in a variable, you can then use command number 2, and the Set-CsWebServiceConfiguration cmdlet, to add the certificate to the specified Web server:

     

    Set-CsWebServiceConfiguration -Identity site:Redmond -TrustedCACerts @{Add=$x}

     

    So what if you change your mind and want to get rid of a trusted CA certificate? Well, there are a couple of ways to do that. Suppose you just want to replace the existing certificate with a new one. That's fine; just repeat the process we showed you a moment ago, but this time use the Replace method instead of the Add method:

     

    $x = New-CsWebTrustedCACertificate -Thumbprint "ZRTEDFFHJT5414251OP9876F342ABGGG6B4P981HZ" -CAStore TrustedRootCA

     

    Set-CsWebServiceConfiguration -Identity site:Redmond -TrustedCACerts @{Replace=$x}

     

    If you want to get rid of all the trusted CA certificates assigned to a Web Server, well, that's even easier: just set the TrustedCACerts property to a null value. You know, like this:

     

    Set-CsWebServiceConfiguration -Identity site:Redmond -TrustedCACerts $Null

     

    Things get a tiny bit tricky if you have multiple certificates stashed in the TrustedCACerts property and want to get rid of just one of those certificates. That doesn't mean it can't be done. Like we said, it's just a tiny bit tricky.

     

    Ah, good point: maybe we should explain what we mean by that. Well, individual certificates are stored in the TrustedCACerts property as an array. For example, if you expand the value of that property you'll see output similar to this:

     

    Thumbprint : D543DFF74FEEA425162FD25F342786F1AB453BB3

    CA Store   : TrustedRootCA

     

    Thumbprint : ZRTEDFFHJT5414251OP9876F342ABGGG6B4P981HZ

    CA Store   : TrustedRootCA

     

    Note. How do you "expand" a property value? Like this:

     

    Get-CsWebServiceConfiguration –Identity site:Redmond | Select-Object –ExpandProperty TrustedCACerts

     

    As you can see, we have two certificates here. The first one (D543DFF74FEEA425162FD25F342786F1AB453BB3) has an index number of 0. Why? Because it's the first item in our array, and the first item in an array always has the index number 0. (Well, in Windows PowerShell anyway.) The second item (ZRTEDFFHJT5414251OP9876F342ABGGG6B4P981HZ) has the index number 1, which is the index number the second item in an array always has. Suppose we want to delete that second item, and only that second item. Here's how we can do that:

     

    $x = Get-CsWebServiceConfiguration –Identity site:Redmond

    $x.TrustedCACerts.RemoveAt(1)

    Set-CsWebServiceConfiguration –Instance $x

     

    See what we did there? We used the Get-CsWebServiceConfiguration cmdlet to retrieve our Web service settings, storing the returned object in a variable named $x. (Hey, we had to get up at 5:00 this morning. We can't come up with a more creative variable name than $x.) After we've done that, we next use the RemoveAt method to remove the second item in the array (the item with the index number of 1). That changes our Web service settings in memory, but doesn't actually write those changes back to Lync Server. As you might have guessed, that's what command number three is for.

     

    And that, as they say, is that. As we said, the author of today's haiku is getting ready to head off to TechReady, but don't worry: he'll take careful and copious notes, and report back on anything interesting that might take place.

     

    Unless, of course, he ends up sleeping through the entire presentation. But, then again, if he has to do much talking, he probably won't be the only one.

     

    See you tomorrow.

     

     

    Haiku Archive

     

     

  • Haiku #160

    The sky is sprinkling,

    The donuts aren’t. But our voice

    Config seems to work

     

    You may have already guessed by reading that haiku that the haiku writer is a little off today. The reason is that this writer was presented with a box of donuts this morning. Now, that’s normally a very good thing, and all in all it was today, too. But, being a little on the slow side this morning (yes, just this morning), this writer was the second person to get to the box of donuts. You might think that in a box of a dozen donuts that wouldn’t be a problem, but it turned out that there was only one donut in the entire dozen that had colored sprinkles on the top. And ‘lo and behold, the first person to the box snatched it up.

     

    Needless to say, we were just a little disconcerted. It still beats the time this same writer went to the coffee shop to get a donut and the person immediately in front of the writer took the last donut. That was pretty traumatic.

     

    So, the haiku writer at least got a donut this morning, but is still really missing those sprinkles. What the writer isn’t missing (besides the donut of course) is a way to test out voice configurations in Microsoft Lync Server. All what’s needed for that are the CsVoiceTestConfiguration cmdlets (Get-CsVoiceTestConfiguration, New-CsVoiceTestConfiguration, Set-CsVoiceTestConfiguration, Remove-CsVoiceTestConfiguration, and Test-CsVoiceTestConfiguration).

     

    Note. Yes, that was a lousy segue. It would have been better with some sprinkles.

     

    The CsVoiceTestConfiguration cmdlets allow you to set up scenarios that you can use to ensure that given a specific telephone number, that number would be correctly normalized and would follow the expected voice policy, voice route, and dial plan. As you can imagine, this is a pretty handy set of cmdlets to have. You can use them to ensure your Enterprise Voice implementation is set up correctly and to help you troubleshoot any issues you might be having. These cmdlets are sort of like the sprinkles on top of Enterprise Voice.

     

    Note. All right, we’ll stop with the sprinkles. For now.

     

    These test scenarios are defined at the global scope, so you can name them pretty much anything you want as long as you stay within the character limits (maximum of 32) and the name is unique within your Lync Server deployment. You can set up a very simple test scenario by calling New-CsVoiceTestConfiguration and giving the scenario a unique Identity, like this:

     

    New-CsVoiceTestConfiguration –Identity TestFourDigit

     

    A test scenario must include a phone number against which the test will be run. If you don’t define a number it will default to 1234. You can also configure a test scenario that will run against a specific dial plan and/or voice policy. For example, let’s say you’ve defined a voice policy for your Redmond site (site:Redmond). Now you want to configure a test scenario where you can enter a phone number and see what would happen to that number if it were dialed by a user who was using the site:Redmond voice policy. Here’s what the command to create the scenario looks like:

     

    New-CsVoiceTestConfiguration –Identity TestRedmondPolicy –DialedNumber 5551234 –TargetVoicePolicy site:Redmond

     

    Test scenarios are run against expected outcomes. By default the expected translated number is +1234. If you don’t expect the number you enter as the DialedNumber to be normalized to +1234, you need to specify a value for the ExpectedTranslatedNumber parameter. For example, suppose you’ve set up a dial plan named SevenDigitDialing. You’ve set up that dial plan so that if a user assigned to that dial plan dials the number 5551234, that number will be normalized to +12065551234. To make sure that the normalization rules are applied correctly, you’d create a test scenario that would check the dialed number against the expected results using that dial plan. Kind of like this:

     

    New-CsVoiceTestConfiguration –Identity TestSeattlePlan –DialedNumber 5551234 –TargetDialPlan SevenDigitDialing –ExpectedTranslatedNumber +12065551234

     

    To retrieve all your voice test configurations, simply all the Get-CsVoiceTestConfiguration cmdlet:

     

    Get-CsVoiceTestConfiguration

     

    If you’d like to retrieve all the scenarios configured against a specific dial plan, such as the Redmond site dial plan, use a command like this:

     

    Get-CsVoiceTestConfiguration | Where-Object {$_.TargetDialPlan –eq "site:Redmond"}

     

    To modify a test configuration, use the Set-CsVoiceTestConfiguration cmdlet. This command will change the expected translated number of the TestSeattlePlan configuration:

     

    Set-CsVoiceTestConfiguration –Identity TestSeattlePlan –ExpectedTranlatedNumber +15551234

     

    And of course, to remove a test configuration, call the Remove-CsVoiceTestConfiguration cmdlet:

     

    Remove-CsVoiceTestConfiguration –Identity TestSeattlePlan

     

    You might have noticed that, while we’ve configured some voice test scenarios, we haven’t actually run any. So let’s give that a try. To run our test scenarios, we use the Test-CsVoiceTestConfiguration cmdlet:

     

    Get-CsVoiceTestConfiguration -Identity TestSeattlePlan | Test-CsVoiceTestConfiguration

     

    The first thing you’ll notice is that you can’t simply call Test-CsVoiceTestConfiguration and pass it the name of a test configuration. Test-CsVoiceTestConfiguration requires you to pass it a reference to an actual voice test configuration object. We get that reference by calling Get-CsVoiceTestConfiguration, giving it the Identity of the configuration we want to use for our test, and piping that to Test-CsVoiceTestConfiguration.  Your output will look similar to this:

     

    Result:             Success

    TranslatedNumber:   +15551234

    MatchingRule:       Description=;Pattern=^(\d{4})$;Translation=+1\d;Name=Test;IsInternalExtension=False

    FirstMatchingRoute: site:Redmond

    MatchingUsage:      Local

     

    And that’s all there is to it. If your test doesn’t succeed, the Result will come back as Fail. The reasons for failure might be a little tough to figure out, but if FirstMatchingRoute is empty, that means that a voice route wasn’t found that can work with that scenario. You’ll just have to kind of work through any failures on your own.

     

    In the meantime, we’ll hope for brighter days in the future, where the sun is shining and the sky isn’t sprinkling, but the donuts are.

     

  • Haiku #159

    We can rebuild it.

    We have the technology.

    Policy entries.

     

    Well, it's Monday, and we're back after another typical Pacific Northwest weekend. What's a typical Pacific Northwest weekend, you ask? Well, a typical Pacific Northwest weekend somehow manages to combine the really good with the really bad. For example, this past weekend the author of today's haiku and his wife went down to Portland to visit his brother-in-law and his brother-in-law's girlfriend. The really good part of that? Well, they got to watch the brother-in-law's girlfriend perform in the play Boeing, Boeing, and absolutely steal the show as Gretchen, the … assertive … German "air hostess." And, with the sun shining and the temperature near 90 degrees (!), they also got to hike the Angel's Rest trail, 2.6 miles long, 1,500 feet in elevation gain. And absolutely killer views once you reach the top.

     

    And the really bad? How about this: it took nearly 6 hours to make the 180-mile trip home. During one memorable hour-long, traffic-filled stretch, the family traveled almost 12 miles. That's practically 12 miles an hour!

     

    Which as anyone who has traveled the freeways around here knows, really isn't all that bad.

     

    And now we're back at work, which also somehow manages to combine the really good with the really bad. The really bad? Well, perhaps you didn't catch it the first time around, but we are back at work. And the really good? Today we're going to talk about the New-CsClientPolicyEntry cmdlet.

     

    Note. Oh, and after having to deal with temperatures in the high 80s yesterday, today the current temperature is 59 degrees, it's overcast, and the author of today's haiku keeps hearing thunder off in the distance. Thank goodness we no longer have to deal with that nice weather!

     

    So what about the New-CsClientPolicyEntry cmdlet? Well, the New-CsClientPolicyEntry cmdlet provides a way for you to extend your client policies, to add management capabilities that aren't included among the default properties of a client policy. Now, before you get too excited about this – wow, does this mean I can add anything to a client policy?!? – we need to qualify this a little: this doesn't mean that you can add anything to a client policy. Instead, you'll need to wait for Microsoft to tell you what you actually can and cannot add to a client policy.

     

    You say you need an example of that? Well, at the moment we only know of one example: the ability to add an entry to your client policies that enables or disables the collecting of Microsoft Lync diagnostic logs. We won't bother to explain what it means to enable or disable the collecting of diagnostic logs; that's something we've already covered in a previous article. What we will do, however, is show you how you can add this entry to a client policy. And speaking of which, here's how you can add this entry to a client policy:

     

    $x = New-CsClientPolicyEntry -Name EnableDiagnosticsLogsCollection -Value 1

     

    Set-CsClientPolicy –Identity global –PolicyEntry @{Add=$x}

     

    As you can see, there's nothing too terribly complicated about this. In our first command, we call the New-CsClientPolicyEntry cmdlet along with two parameters: Name and Value (which are the only two parameters available for this cmdlet). The Name parameter is simply the name of the property being added (EnableDiagnosticsLogsCollection) and the Value parameter is, well, the value assigned to that property. In this case the value 1 enables diagnostic log collecting and the value 0 disables diagnostic log collecting.

     

    Note. So where did we get this name and value from in the first place? You got it: that information was released by the Microsoft Lync Server product team. You can put any name and any value you want into a client policy, but those names and values won't actually do anything. The name EnableDiagnosticsLogsCollection and the value 1 let you manage log collections because Microsoft Lync and Microsoft Lync Server have been architected to know what to do when those items show up in a client policy.

     

    At any rate, our new client policy entry is stored in a variable named $x, then is added to the PolicyEntry property using this command:

     

    Set-CsClientPolicy –Identity global –PolicyEntry @{Add=$x}

     

    And what does our global client policy look like now? It looks something like this:

     

    Identity                    : Global

    PolicyEntry                 : {Name=EnableDiagnosticsLogsCollection;Value=1}

    Description                 :

    AddressBookAvailability     : WebSearchAndFileDownload

    AttendantSafeTransfer       :

    AutoDiscoveryRetryInterval  :

     

    And you're right: if we'd only thought to bring the New-CsClientPolicyEntry cmdlet with us those six hours in the car would have seemed like six minutes. Next time we'll pack a little smarter.

     

    Ah, good question: what if you did have a second client policy entry you wanted to add (one that we've stashed in a variable named $y)? That's no problem; you can add multiple entries in a single command:

     

    Set-CsClientPolicy –Identity global –PolicyEntry @{Add=$x,$y}

     

    In other words, suppose we did this:

     

    $x = New-CsClientPolicyEntry -Name Test1 -Value 1

    $y = New-CsClientPolicyEntry -Name Test2 -Value 2

     

    Set-CsClientPolicy -PolicyEntry @{Add=$x,$y}

     

    That will give us a client policy that looks something like this:

     

    Identity                     : Global

    PolicyEntry                  : {Name=Test1;Value=1, Name=Test2;Value=2}

    Description                  :

    AddressBookAvailability      : WebSearchAndFileDownload

    AttendantSafeTransfer        :

     

    What's that? You say you don't actually want policy entries $x and $y? You say that what you really wanted to do was replace $x with $y? That's fine; just use the Replace method, like so:

     

    Set-CsClientPolicy -PolicyEntry @{Replace=$y}

     

    Or how about this: you currently have a policy that includes a pair of entries (Test1 and Test2) and you'd like to remove just Test1, leaving Test2 as-is. Can you do that?

     

    Of course you can. It's just, alas, a tiny bit clunky.

     

    What do we mean by that? Well, you can't remove a policy entry just by specifying the name; for example, by using a command similar to this one:

     

    Set-CsClientPolicy -PolicyEntry @{Remove="Test1"}

     

    The Remove method is the correct method to use, but the PolicyEntry parameter can only work with instances of the Microsoft.Rtc.Management.WritableConfig.Policy.Client.PolicyEntryType class. A plain old string value (like Test1) is just going to result in an error message:

     

    Set-CsClientPolicy : Unable to cast object of type 'System.String' to type 'Microsoft.Rtc.Management.WritableConfig.Policy.Client.PolicyEntryType'.

     

    So how do you get around that problem? There are two possibilities. For one, you can create a new policy entry object identical to the entry to be removed; you can then use that variable as the value passed to the Remove method. In other words:

     

    $x = New-CsClientPolicyEntry -Name Test1 -Value 1

     

    Set-CsClientPolicy -PolicyEntry @{Remove=$x}

     

    It's kind of any odd thing to do – to remove something, first create a second instance of that something – but it works.

     

    The other way is to go down this path:

     

    $z = Get-CsClientPolicy -Identity global

    $z.PolicyEntry.RemoveAt(0)

     

    Set-CsClientPolicy -Instance $z

     

    What's going on here? Well, the PolicyEntry property stores individual policy entries in an array. Items in an array are always given an index number: the first item in the array is item 0, the second item in the array is item 1, and so on. What we're doing here is first using the Get-CsClientPolicy cmdlet to create an object reference to the global client policy. We then use the RemoveAt method to remove the array item with the index number 0:

     

    $z.PolicyEntry.RemoveAt(0)

     

    And then, finally, we use the Set-CsClientPolicy cmdlet and the Instance parameter to write the changes back to Lync Server:

     

    Set-CsClientPolicy -Instance $z

     

    Like we said, it's a little clunky. But it also works.

     

    And there you have it: the New-CsClientPolicyEntry cmdlet. That's the really good news for today. The really bad news? You know, come to think of it, it's Monday, the sun isn't shining anymore, and we're back at work. Looks like there isn't any really bad news today after all!

     

    See you tomorrow.