Send an Instant Message from a Script


Here are a couple of interesting facts:

 

·         Elephants can make sounds that humans can’t hear.
People who work closely with elephants know this because if you get close enough you can feel the sound waves.

·         Earth, and more accurately life on Earth, would not exist without Jupiter.
Jupiter is so large its gravitational field pulls in most of the space junk – stray comets and asteroids and things – before they can move on and crash into Earth.

 

These are just a couple pieces of trivia this author has stumbled upon over the years and has managed to remember because she found them interesting. Has she used this information for anything useful in her life? (For that matter, has she used any information for anything useful in her life? We won’t try to answer that.) Has it helped her in her career at all? (For that matter, has anything… Well, we already know the answer to that.) The answer to both questions is no; this information has been completely useless to her.

 

Which brings us to the topic of this article. Here at the Lync Server PowerShell blog we like to think the articles and scripts we publish are actually useful to some of you. As a matter of fact, most of the time we write about things people have specifically asked us about. This article started out that way, but, like so many things in life, we ran into some snags and everything sort of veered off course. But on the chance that some of you might still find this useful, or at least interesting, we’ve decided to go ahead and show you what we came up with.

 

Note. Okay, we’re being a little harsh here. The scripts we’re about to show you can actually come in pretty handy, but, as we’re about to explain, you have to go through a few steps to get started.

 

We began with the intent of figuring out how to perform some client management tasks in Microsoft Lync Server. In this case, we wanted to figure out how to use a Windows PowerShell script to send an instant message (IM) to various Lync contacts or groups.

 

Now, a script that sends an instant message can potentially be pretty useful. Suppose you’re running a report, and you want to send an instant message to all your contacts in a particular group when the report has finished running. Wouldn’t it be nice to have a script that would do that for you? Or you have an announcement you’d like to quickly IM to all your contacts. That could be useful, too. Unfortunately, Lync Server 2010 doesn’t provide any cmdlets that can help you with this. So we turned to the Microsoft Lync 2010 SDK.

 

The good news is that we accomplished what we set out to. We have four scripts here for you. Each one sends an instant message from the currently logged on user to various sets of that user’s contacts. From the testing we did they all run flawlessly and can easily be modified to monitor processes and send the message based on process completion.

 

Now for the not-so-good news. (We never have “bad” news for our customers here at Microsoft. Remember: it’s a feature.) As we said, the way we found to do this was by using the Microsoft Lync 2010 SDK. SDKs are typically made to be used by application developers, not so much by script writers. So while you can use them in scripts, keep in mind that there are sometimes extra things you need to do to work with them. To start with, in order to use the Lync 2010 SDK you need to download and install it. But, before you can do that you need to download and install the Microsoft Silverlight 4 Tools for Visual Studio 2010. And before you do that, you need to make sure you have either Microsoft Visual Studio 2010 with the Visual Studio Web Developer feature or Microsoft Visual Web Developer 2010 Express installed. (The latter is a free download.) Like we said, the assumption is you’re using this in a development environment, so of course you’d be running Visual Studio, right?

 

Now, an interesting thing about all this is that in order to use the SDK with Windows PowerShell, all you really need are the DLLs that the SDK installs. That means that once you have all this installed, you can simply copy the DLL files (and, in the case of the scripts we’re going to show you here, you need only one DLL) and the scripts you want to run to the whatever computer you want to run from and you can run the scripts from there.

 

Yes, we know, that seems like a lot of trouble to go to for one little DLL. But that’s the way it goes.

 

Note. The DLL you’ll need is Microsoft.Lync.Model.DLL, saved by default in the folder C:Program Files (x86)Microsoft LyncSDKAssembliesDesktop. If you copy the DLL to a computer rather than install the full SDK you’ll need to register the DLL before these scripts will work. To register the DLL, type this at a command prompt:

 

regsvr32 Microsoft.Lync.Model.DLL

 

If you don’t run the command from the folder where you put the DLL you’ll need to include the full path with the filename.

 

The final thing to note before we continue is that these scripts run against the currently running instance of Lync on the local machine. You must be logged on to Lync for the scripts to run. The instant messages that are sent will be sent from the user logged in to Lync. In addition, the scripts work against the contacts in that user’s instance of Lync. They don’t access all contacts within a Lync Server deployment.

 

Send an Instant Message to All Your Contacts

 

So now that we’ve explained what you have to do to get ready for this, we’ll show you the first script. (The script is going to seem like child’s play after all that.) This script will send an instant message to all contacts in the running instance of Microsoft Lync:

 

$assemblyPath = “C:Program Files (x86)Microsoft LyncSDKAssembliesDesktopMicrosoft.Lync.Model.DLL”

Import-Module $assemblyPath

 

$added = @{}

$PlainText = 0

$IMType = 1

 

$cl = [Microsoft.Lync.Model.LyncClient]::GetClient()

 

$conv = $cl.ConversationManager.AddConversation()

 

$gs = $cl.ContactManager.Groups

 

foreach ($g in $gs)

{

 

    foreach ($contact in $g)

    {

               

        if (!$added.ContainsKey($contact.Uri))

        {

            $null= $conv.AddParticipant($contact)

            $added.Add($contact.Uri,0)

        }

           

    }

 

}

 

$d = New-Object “System.Collections.Generic.Dictionary[Microsoft.Lync.Model.Conversation.InstantMessageContentType,String]”

$d.Add($PlainText, “This is just a test.”)

 

$m = $conv.Modalities[$IMType]

$null = $m.BeginSendMessage($d, $null, $d)

 

The first two lines of code are the same for every script we’re going to show you in this article:

 

$assemblyPath = “C:Program Files (x86)Microsoft LyncSDKAssembliesDesktopMicrosoft.Lync.Model.DLL”

Import-Module $assemblyPath

 

The first line places the full path to the DLL named Microsoft.Lync.Model.DLL into a variable ($assemblyPath). The path shown here is the default path the DLL is installed to. If you didn’t install to the default path, or if you’ve copied the DLL to a different location, be sure to update this path. The second line calls the Import-Module cmdlet, passing it the variable with the path to the DLL. This makes it so we can use all the classes, methods, properties, and so on that are in that DLL.

 

Next we create some variables:

 

$added = @{}

$PlainText = 0

$IMType = 1

 

The $added variable is an array (that’s what the @{} means) that is currently empty. We’ll be using this array to store a hash table. If you’re not sure what a hash table is, don’t worry, we’ll get to that in a little bit. We’ll use the second variable, $PlainText, to specify what type of message we’ll be sending. A value of 0 represents a plain text message. We’ll use $IMType to tell Lync what type of conversation we’re going to be starting. The value 1 represents an instant messaging conversation.

 

Now it’s time to connect to our Lync client:

 

$cl = [Microsoft.Lync.Model.LyncClient]::GetClient()

 

Remember that you have to have Lync up and running and be logged on for this command to work. All this is doing is calling the GetClient method to get a reference to the client and store it in the variable $cl. This allows us to access Lync from our script.

 

In Lync, an instant message is a type of conversation. (Other types of conversations include conferences and phone calls.) Because we want to send an instant message, we need to start a conversation in our running instance of Lync. We do that by calling the AddConversation method, like this:

 

$conv = $cl.ConversationManager.AddConversation()

 

Now that we’ve started a conversation, we need to find the contacts who we want to participate in that conversation. In this script we’re going send the instant message to all of our contacts, so we need to grab every contact in every group in our contacts list. We start by getting all of our groups and storing them in the variable $gs, like this:

 

$gs = $cl.ContactManager.Groups

 

Now we need a foreach loop to loop through each group:

 

foreach ($g in $gs)

 

Next we get to do what’s called a “nested loop,” which is simply one loop within another. As we get each group, we need to loop through that group and pull out each contact. We do that with another foreach loop:

 

foreach ($contact in $g)

 

This is where things get a little tricky. It’s possible that a contact can be in more than one group. For example, you might have a contact in your Current Contacts group and your Frequent Contacts group. We want to add each contact as a participant in our IM conversation, but we can only add each contact once. If we try to add a contact more than once our script will return an error. So we need to make sure that we haven’t already added a contact to the conversation before we add them. There are probably many ways you can do this, but we decided to go with a hash table.

 

A hash table is basically just an array, but it stores values as key/value pairs. That means that each entry has a key, which must be unique, and an associated value. By adding a contact’s URI to the hash table when we add them to the conversation, the next time we go through the loop we can check the table to see if the contact is already there. If they are, we know not to try to add them to the conversation again. Here’s what that looks like:

 

        if (!$added.ContainsKey($contact.Uri))

        {

            $null= $conv.AddParticipant($contact)

            $added.Add($contact.Uri,0)

        }

 

We start by using the ContainsKey method to check our hash table (which, you’ll recall, is stored in $added). We pass ContainsKey the URI of the current contact. Notice the exclamation point (!) at the beginning. This means not. So what the if statement says is “if the $added hash table does not contain a key that matches the URI of the current $contact, then we want to go into the if statement and do what follows.”

 

Comments (14)
  1. Anthony Caragol says:

    I had a little trouble, but still love the code! Thanks for taking the time to write this!

  2. Russ says:

    This worked great for me!! Thank you. To take one step further, I would like to tag the scripted message as High-Importance. How could this be done?

  3. Amir says:

    Hi,
    Can we send IM to a chat rooms in persistent chat with this command?
    Cheers,

Comments are closed.