Author Archives: Koen Halfwerk

The Automated Career Gap

Tags :

Category : Uncategorized

Automation in IT is great! It removes boring tasks, gets managers off your back and lowers the FTE required for complete departments. But the widespread use of Automation, Desired State Configuration and Infrastructure As Code in IT has led to a foreseen but untackled side effect:

The step up from a junior position is getting bigger and bigger.

Here’s how this works.

Imagine a junior sys admin, Edd, starting out in a new position. What are the kinds of tasks that he gets entrusted with? Creating new users, doing password resets and sorting out which tickets should be sent back to the service desk (or fixing it himself since that’s less of a hassle) and which should go on to the senior sys admins.

After the first few weeks, Edd gets his hands on a request for change for some new server VM and gets his first chance at writing up a plan, getting it reviewed and installing and configuring the actual VM. After a year or two, Edd has seen and done enough in the environment to be left in control of the day-to-day IT operation.

While Edd is running the operation, the seniors have started automating. They decided to use Powershell, Azure Resource manager, Desired State Configuration and Azure functions to automate most IT tasks, ranging from password resets by the end user up to spinning up new, fully configured VM’s. Now all the things he used to do at the service desk and most of his current daily work is automated (this is of course an ideal hypothetical situation), leaving him with routing the tickets from the first line service desk to the senior sys admins. Anything that can’t be handled by the service desk is either automated or too complex for Edd to handle on his own.

The Aftermath

Luckily for Edd, the seniors involve him in the automation process and the few incidents that still pop up in the IT operation, but HR will have to find a cost-efficient way to get the next sys admin up and running without having to hire a senior right off the bat.

So what are the options?

At first glance, the most logical option would be to train juniors on the job, but this is getting less and less feasible as there is little work left for juniors. Instead,
training needs to be done intensively, via longer courses provided by the employer or an external company. The former would require company trainers, but could end up more tailored to the company’s specific characteristics. In contrast, the latter could be either cheap and generic or expensive and tailored.

The challenge is that you need some form of actual experience with a system before you can automate it. For stand-alone automated systems like an AD with Exchange or VM creation, setting up a course with enough hands-on experience is very doable. But with complete Identity Management automation, automated monthly billing reports or any product that incorporates multiple systems, it’s the intricacies that make the 3 or 5-day courses that we typically see in the IT world almost impossible.

The alternative, to only hire seniors, would probably be too expensive and would diminish the recruiting pond over the years. In the end, training your juniors while under contract, though challenging in various ways, still seems like the best option.

The Conclusion

Train your juniors to know your products and to quickly and correctly figure out how these products should connect. Give them test environments to create things manually and break things while trying to automate it. Give them a tutor and time-managed (!) play time. And most importantly, involve them in breakages and incidents arising from integrations between systems. Yes, your seniors can do it faster, but invest in your Edds so that they can become your future seniors.


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.L.C.FRAMEWORK.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"
Exit
}
#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"
Exit
}

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):

switch($status_String){
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)
$client.self.EndPublishContactInformation($Publish)

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:
$Client.ContactManager.Groups[0].Name
#The displaynames in the group:
$Client.ContactManager.Groups[0].getcontactinformation(10)
#the SIP addresses in the group:
$Client.ContactManager.Groups[0].getcontactinformation(11)
#or
$Client.ContactManager.Groups[0].uri
 
# $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
$Conversation.AddParticipant($contact)
#make the message
$Msg = New-Object "System.Collections.Generic.Dictionary[Microsoft.Lync.Model.Conversation.InstantMessageContentType,String]"
$Msg.Add(0,$Message)
#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!