Continue an Instant Messaging Conversation

Continue an Instant Messaging Conversation

Have you ever had a conversation with someone and later thought “Oh, I should have said this,” or “I wish I’d said that”? (True, sometimes you say “I wish I hadn’t said that,” but that’s another story.) If you're like most of us, you tend to come up with the perfect thing to say 20 minutes after the conversation is over. Well, that’s the cool thing about instant messaging. You can keep the conversation window open and just keep adding to it for as long as you want. As it turns out, you can even do that with a script.

A while ago we wrote an article about how to write a script that would use the Lync 2010 SDK to send an instant message. The script started a conversation, added participants, and sent a message. Now, we thought that might be a pretty handy script to have, but it turns out we can make it even handier. We received email from one of our avid readers (we’re going to assume he’s an avid reader anyway) asking how to modify the script so that you can continue an existing IM conversation rather than start a new conversation each time the script is run. And our response was “Hey, that’s a good question, how would you do that?”

When we realized no one else was going to answer our question, we got to work. (Something we do on rare occasions.) And, as it turns out, it is possible to find an existing conversation and add more messages to that conversation. We ended up with what might be considered a little bit of a workaround, and our solution isn’t completely foolproof, but it seems to work.

Note. Before we get started we’ll remind you that in order for this script to work you have to have the Lync 2010 SDK installed on the computer on which you’re running the script. Also, the script must run against a currently open Lync session. If Lync isn’t open, this script won’t work. For more details on installing the Lync SDK and making sure you’re all set up, see our previous article.

This script looks for a specific IM conversation based on the subject of the conversation. If it finds that conversation it adds a message. If it doesn’t find the conversation, it creates a new conversation and sends the message. Here’s the script:

When we send the instant message, that message must be sent as a Dictionary object. So here we’ve defined that object and then added the text that will be in the message (System tests are complete). This is where you’ll put whatever message you want to send.

Now we call the GetClient method of the LyncClient object. This line captures the currently-running instance of Lync and saves it to the variable $cl:

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

If Lync isn’t running on the computer, your script will crash right here.

Note. Are there ways to check for this so your script will handle the error nicely without crashing? Yes. But that’s another article for another day.

Now that we’re all set up, the fun begins. (Aren’t you having fun? We thought this was the fun part. Although our definition of “fun” sometimes doesn’t line up with most people’s.)

At this point we look to see if we have any IM sessions currently running on the computer. We do that by checking the Count property of the Conversations collection:

if (($cl.ConversationManager.Conversations).Count -ge 1)

The Count property contains the number of conversations in progress; if the Count is greater than or equal to (-ge) 1 then there is at least one conversation in progress. If there is at least one conversation, we want to check to see whether one of those conversations is the one we want to continue. To do that we have to loop through the collection of conversations with a foreach loop:

foreach ($c in $cl.ConversationManager.Conversations)

The way we’ve decided to go about finding a specific conversation is by looking at the Subject of the conversations that are in progress. Earlier we said this solution isn’t necessarily foolproof, and this is the spot where you could have a problem. If you happen to have more than one conversation with the same subject, you might end up adding your message to the wrong conversation. But we decided the odds of having multiple conversations with the same subject, especially since we set the subject value (which we’ll show you in just a bit), are pretty slim.

At this point we run into this line of code:

$subject = $c.Properties[524289]

Yes, we know, that looks a little odd. What’s happening here is we’re saving the Subject property of the conversation to the variable $subject. The properties available as part of a Conversation object are stored as an enumeration. If we were writing this in C# we could simply use syntax something like this: c.Properties.Subject. Unfortunately Windows PowerShell doesn’t understand enumerations as easily as managed programming languages like C# do. So instead of just saying we want the Subject property, we have to specify the value that represents the Subject property, which just happens to be 524289.

Note. How did we know the value was 524289? We checked the SDK documentation. We were going to include a link to the documentation on MSDN here, but unfortunately the values aren’t listed there. However, when you install the Lync SDK you’ll get a CHM file. Check the ConversationProperty enumeration there and you’ll find all the values.

Note. If you’re not sure what the Subject property is, look under More Options (the >> symbol) in your conversation window. You’ll see an option named Change Conversation Subject. This allows you to give a name to your conversation, which will be displayed in the title bar of the conversation window. We’ll show you in a moment how we do this in a script.

Now that we have the subject name of the conversation, we check to see whether that conversation is the one we want to add to:

if ($subject -eq "Send Alerts")

In this case we’re looking for a conversation we named “Send Alerts.” (Where did we set that conversation name? Be patient, we’ll show you that soon.) If the subject of the current conversation is Send Alerts, we want to add our message to that conversation. The first thing we do if we find the conversation is to set the variable $found to True:

$found = $True

We’re using this flag to let the script know that we found an existing conversation so we don’t need to create a new one. Since we found the conversation we want to continue, we’re ready to add our message to that conversation:

$m = $c.Modalities[$IMType]

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

We set the modality to specify that we’re sending an instant message, then we send the message. (Remember that the message is in our Dictionary object, stored in the variable $d.)

If the current conversation in the foreach loop didn’t have a subject matching the subject we were looking for, we would continue to loop through all the active conversations until we’d either checked all of them or found the one we were looking for.

Once we’re done looping around we reach an if statement:

if (!$found)

Remember the flag we set to tell our script we found the conversation? Well, if we never found the conversation we wanted, $found would still be False and we’d want to begin a new conversation to send our message. So we check to make sure that $found is False (that’s what !$found means, it really means not $found, or $found is not True).

If we didn’t find the conversation, we need to call the AddConversation method to create it:

$conv = $cl.ConversationManager.AddConversation()

When we were looking for the conversation earlier in the script, we looked for a specific subject name. Back then we told you to be patient, that we’d show you where we set that, and we didn’t lie. (We never lie. Well, almost never.) After we create the conversation, we add a subject to it, like this:

Now, you might think that, since we retrieved the subject name like this:

$subject = $c.Properties[524289]

That we could set it like this:

$c.Properties[524289] = "Send Alerts"

Initially that’s what we thought, too. But we were wrong. (That does happen on occasion.) Instead, in order to set a conversation property, you have to call the BeginSetProperty method. We pass the full name of the enumeration (Microsoft.Lync.Model.Conversation.ConversationProperty) followed by the name of the property (Subject). And no, we didn’t even have to use the enumeration value (524289) here. That made the code a little longer, but this is how it works and it’s easier to decipher.

At this point we retrieve the user we want to send the IM to and send the message. We’re not going to explain the rest of this here, this is exactly the same as the script in our article on sending an instant message.

And that’s all there is to it. The script is a little long, but it’s really not that complicated once you break it down. Which, coincidentally, is what we just did. We’ve been told we’re very good at breaking things.

I found that using the actual property name (since Conversation.Property is a Dictionary) instead of the enum value worked and was more readable

So $c.Properties["Subject"] instead of $c.Properties[<arbitrarynumber>]

Also, you don't neccessarily need to pass a Dictionary<IMContentType, blah> into the BeginSendMessage method - a string would do (though I'm assuming that a dictionary supports more Lync functionality like passing multiple messages etc, but in this case is just an extra line of code)

Additionally a very minor quip - I'd modify the script so that the message is sent at the end, and the conditional statements just perform the task of getting hold of a conversation.message instance, just for ease of maintenance if the method of sending the message needs to change (only one place to maintain vs two)

Hey Charles, This is great feedback, thanks! You're right, your syntax for the Properties is much simpler, we just missed that one. And also putting the send message at the end would be a little better for maintenance, assuming your message was the same for the initial message and subsequent messages.