3

I'm setting a handler for the InstantMessageReceived event, but it only seems to fire on outgoing text messages, not incoming. Here is the code I'm running:

# Register the app with Growl
$icon = "https://docs.google.com/uc?export=download&id=0B1Weg9ZlwneOZmY2b1NSVXJ0Q2s"
$types = '"new-im","new-call","invitation","share"'
& 'C:\Program Files (x86)\Growl for Windows\growlnotify.exe' /a:Lync /ai:$icon /r:$types "Registration."

#We just need the Model API for this example
import-module "C:\Program Files (x86)\Microsoft Lync\SDK\Assemblies\Desktop\Microsoft.Lync.Model.Dll"

#Get a reference to the Client object
$client = [Microsoft.Lync.Model.LyncClient]::GetClient()

#Set the client to reference to the local client
$self = $client.Self

# What do we do here?
$conversationMgr = $client.ConversationManager

# Register events for existing conversations.

$i = 0

for ($i=0; $i -lt $conversationMgr.Conversations.Count; $i++) {

Register-ObjectEvent -InputObject $conversationMgr.Conversations[$i].Modalities[1] -EventName "InstantMessageReceived" `
                    -SourceIdentifier "new im $i" `
                    -action {
                               $message = $EventArgs.Text
                               Write-Host "DEBUG: New incoming IM - $message"

                               # Try to get the name of the person...
                               $contactInfo = $Event.Sender.Conversation.Participants[1].Contact.GetContactInformation([Microsoft.Lync.Model.ContactInformationType[]] @("FirstName", "LastName", "DisplayName", "PrimaryEmailAddress", "Photo", "IconUrl", "IconStream"))
                               $name = " "
                               if ($contactInfo.Get_Item("FirstName")) { $name = $contactInfo.Get_Item("FirstName") + " " + $contactInfo.Get_Item("LastName") + ":" }
                               elseif ($contactInfo.Get_Item("DisplayName")) { $name = $contactInfo.Get_Item("DisplayName") + ":"}
                               else { $name = $contactInfo.Get_Item("PrimaryEmailAddress") + ":" }

                               # We need to check if the Lync window (conversation?) has focus or not.
                               if (1) {
                                  # We need to send our growl notification.
                                  & 'C:\Program Files (x86)\Growl for Windows\growlnotify.exe' /a:Lync /n:new-im /t:"New Instant Message" "$name $message" 
                               }

                            }
}

# If this exits, no more events.
while (1) { }

Every time I type out an IM message to someone else, it does what I'm trying to do for incoming messages. But nothing ever fires for those, just outgoing. I've been through all the documentation, and there aren't any other candidate events, I'm sure it's this one. But the Modality object just stores some stuff about whether it's an IM or screensharing and the like, nothing useful.

http://msdn.microsoft.com/en-us/library/lync/microsoft.lync.model.conversation.instantmessagemodality_di_3_uc_ocs14mreflyncclnt_members(v=office.14).aspx

Where am I screwing up on this? I prefer answers in Powershell, but I don't think this is a problem specific to Powershell, so if you know how to do it in C# or Visual Basic or something like that, I'd appreciate that too.

Alex
  • 12,749
  • 3
  • 31
  • 45
John O
  • 4,863
  • 8
  • 45
  • 78
  • I know this is bad form but you seem to be asking the same question that I have. Did you ever get this working for receiving messages? I tried to combine your original post with the answer you selected but It wasn't recognizing the cast [ModalityTypes.InstantMessage] saying it was an unexpected token. – SureThing May 15 '20 at 17:09

1 Answers1

3

I don't have Lync so I can test this myself, but take a look at this link where it shows how to use the API.

The problem is(from what I understand) that there is a modality per participant per media. So for a conversation with two members using only text, there will be 2 modalities, one for incoming messages(from the remote participant) and one for outgoing. This is specified here in

Occurs when an instant message is received, or sent if the InstantMessageModality belongs to the local participant.

Source: MSDN

When you register your object-event, you register it to "your modality", and not the remote modality. To fix it it seems to you need to take each conversation from the manager, look at each participant except the one representing you (check the IsSelf property). Then take the modality from the participants(except yourself) and register for the InstantMessageReceived event.

At least that's what I got out of it, but as said I have no experience with Lync so I could easily be wrong.

My guess at how it could be done(VERY untested):

# What do we do here?  You get the manager the keeps track of every conversation
$conversationMgr = $client.ConversationManager

# Register events for existing conversations.

#You may need to use '$conversation in $conversationMgr.GetEnumerator()'
foreach ($conversation in $conversationMgr) {

    #Get remote participants
    $conversation.Participants | where { !$_.IsSelf } | foreach {
        #Get IM modality
        $textmod = [InstantMessageModality]($_.Modalities[ModalityTypes.InstantMessage])

        Register-ObjectEvent -InputObject $textmod -EventName "InstantMessageReceived" `
                    -SourceIdentifier "new im $i" `
                    -action {
                            #...

        }
    }
}
Frode F.
  • 52,376
  • 9
  • 98
  • 114
  • Thank you for answering, but if I do a count on modalities, I actually get 6. http://msdn.microsoft.com/en-us/library/microsoft.lync.model.conversation.modalitytypes_di_3_uc_ocs14mreflyncclnt.aspx The Conversation object's Modalities property is one of these values, it doesn't seem to be a per-participant thing. I will dig into it more though, wouldn't be the first time I've been dumb. – John O Mar 07 '13 at 01:16
  • You are indeed correct. There is a Modality object for each participant, and the Conversation obj just has its own for the self participant. Now that I'm accessing the correct one, I'm getting what I expect. Thank you. I gotta learn some better ways to debug in Powershell, this would have taken 10 seconds if I could have just seen a list of child objects for any given one. – John O Mar 07 '13 at 04:45
  • Glad I could help. :) Was the code correct or did you modify it in any way? I'd like to have a working example in my answer. – Frode F. Mar 07 '13 at 06:57
  • 1
    I don't seem to need the cast, I took that out in an edit. The rest is good. – John O Mar 07 '13 at 14:27
  • Great :) We'll let the cast stay there just to make sure you get the correct modality type. It won't hurt the code. – Frode F. Mar 07 '13 at 17:37