Category Archives: PowerShell

Talk to Skype for Business

Ever wondered if you could get Skype for Business to respond to Powershell? This post will give you the basics for a script that writes to Skype for Business contacts on your behalf. I started writing code for Lync 2010 and have since then migrated to Skype for Business without any backwards compatibility issues.

While it is possible to have a script running that sets your status to ‘Do not Disturb’ every time a certain person (your manager) tries to talk to you, this would result in a DDos attack on your Skype for Business (SfB) server. There is a way to go on ‘Do not Disturb’ after the first message has been received, which I will shortly explain at the end of this post. In order to make this post as readable as possible, I’ll write the code sequential, without any functions. This way the code reads in the same order as Powershell executes it.

But first some things you need in order to get SfB to acknowledge the existence of Powershell in the first place. Sadly SfB Does not have its own windows SDK, but the Lync SDK works just as well. Inside are a couple of dll’s that we will need. So download de SDK, open it with any archive program like 7-zip. Inside are the following dll’s that we will need:

  • \LYNC..M.L.MODEL.dll
  • \LYNC..M.O.UC.dll
  • \LYNC..M.L.Utilities.dll

Place the dll files in the same folder as your script or working directord and import them:

Import-Module -Name ".\LYNC..M.L.MODEL.dll"
Import-Module -Name ".\LYNC..M.L.C.FRAMEWORK.dll"
Import-Module -Name ".\LYNC..M.o.uc.dll"
Import-Module -Name ".\LYNC..M.L.Utilities.dll"

Next we will make a connection to your local Skype for Business client.

#Try to connect using a bit of dotnet
Try {
$Client = [Microsoft.Lync.Model.LyncClient]::GetClient()
Catch {
Write-Output "Skype for Business client not running"
#check if the client is actually signed in, not just running
If ($Client.State -ne "SignedIn") {
Write-Output "Skype for Business client not signed in"

Next, grab the client status, the contact manager and the status of your contacts:

#get the clients status (put it on 1 line)
$Status_Info = New-Object 'System.Collections.Generic.Dictionary
[Microsoft.Lync.Model.PublishableContactInformationType, object]'
#get all contacts
$contact_man = $Client.self.Contact.ContactManager
#get availability status of all contacts
$contact_stat = $contact_man.GetContactInformation("Availability")

Changing your status

In order to change your Skype for Business status, you have to know what number in $Status_info corresponds to what status (instead of numbers, you could use strings in the switch):

1 {$status = 3000} # "Available"
2 {$status = 6000} # "Busy"
3 {$status = 9000} # "Do Not Disturb"
4 {$status = 12000} # "Be Right Back"
5 {$status = 15000} # "Away"
6 {$status = 15500} # "Off Work"
7 {$status = 18000} # "Appear Offline"

So if you wanted to have a script that changes your Skype for Business status between busy and available, you could do something like this (withouth a switch in this case):

if ($Client.self.Contact.GetContactInformation("Availability") -eq 6500)#for some reason $client always reports 500 more then it wants to receive
$status = 3000 #available}
elseif($Client.self.Contact.GetContactInformation("Availability") -eq 3500)
$status = 6000 #busy
#publish the change to the client
$Status_Info.Add([Microsoft.Lync.Model.PublishableContactInformationType]::Availability, $status)
$Publish = $client.Self.BeginPublishContactInformation($Status_Info, $null$null)

Sending a message

So how about sending a message? Given some prior knowledge about your contact list, or the sip of your contact, you can write a script to talk to any contact or person that you would normally be able to talk to through the GUI.

Finding the addres or name of the SfB contact:

#The name of a group:
#The displaynames in the group:
#the SIP addresses in the group:
# $contact is now the email address of my first contact (group1, contact 1)
$Contact = $Client.ContactManager.Groups[0].getcontactinformation(11)[0]
#what do you want to say:
$message = "Hello World"
#start the conversation:
$Conversation = $Client.ConversationManager.AddConversation()
#add your contact to it
#make the message
$Msg = New-Object "System.Collections.Generic.Dictionary[Microsoft.Lync.Model.Conversation.InstantMessageContentType,String]"
#set the modality to instant message (rather then audio or any other modality)
$Modality = $Conversation.Modalities[1]
#send the message:
$Modality.BeginSendMessage($Msg, $null$Msg)

Now that you have a basic handle on how to talk to Skype via Powershell, go ahead and explore all the possibilities!

The new Az module – Connecting to Azure

With the introduction of the new Az PowerShell module, the merger of the Azure.* and AzureRM.* modules, comes a new way of connecting to Azure.

When we get a list of the available commands to do something with an AzAccount, you’ll end up with the following:

As you can see, there are now Connect-/Disconnect-AzAccount and Login-/Logout-AzAccount cmdlets. So if you want to connect to Azure and use PowerShell cmdlets to manage your environment, which one do you use?

If you use either Connect-AzAccount or Login-AzAccount, you’ll end up with the following message:

For this, one would require user interaction. Would that not negate the whole concept of automation?

One of our customers contacted me with the request if we could automate this. His idea was that we would write something that could read the url and code, utilize a browser and through that automate the login.

Although I love billing customers, I don’t like to bill them unnecessarily. I decided to educate them instead:

The solution is already available

The solution is simply by using the cmdlet the way it is intended to be used. For an interactive environment, you can simply go to that website and fill in the code. When you require the cmdlet to be used in an automated process / script, you can use the cmdlets’ parameters to tweak its behavior so that it works in automation

If you look at help of the cmdlets, you’ll notice that it has quite a few parameters that you can use. Amongst those is the -Credential parameter:

Big fat note:
This approach doesn’t work with Microsoft accounts or accounts that have two-factor authentication enabled.

But what if you’re using an account with Multi Factor Authentication?

Well, let me introduce you to Service Principals and Managed Identities.
Service principals are non-interactive Azure accounts. Like other user accounts, their permissions are managed with Azure Active Directory. By granting a service principal only the permissions it needs, your automation scripts stay secure.

If you want to know how you can create Azure Service Pricipals, take a look here.

Next to the Service Principal, the Connect-AzAccount cmdlet also requires you to provide its application ID, sign-in credentials, and the tenant ID associate with it:

Manage identities are a subset of Service Principals, and have therefor the same constraints.
They are assigned to resources that run in Azure. You can use them for sign-in, and acquire an app-only access token to access other resources. Managed identities are only available on resources running in an Azure cloud.