Lync Powershell and C#
I've been doing a lot of Powershell lately, beyond the typical - find a command, run a command, execute the command - business. I started off the with the following FREE pdf book - Master Powershell - if you are looking for a primer, this is a great place to spot. I learned a lot about the language and how it really differs from more strongly typed languages like C# - everything is so fluid and dynamic. If you don't believe how good Powershell can be, check out this post on using the Lync Client SDK INSIDE of Powershell... awesome.
My main goal was to figure out a better way to migrate a few couple thousand users over to Lync and set them up with some custom Client and Archiving policies. In the end I was able to do it merely through using some of the existing cmdlets available in Lync;
Get-CsAdUser -Filter (Enabled -ne $True) | Enable-CsUser -RegistrarPool "entpool.mydomain.com" -SipAddresstype EmailAddress -SipDomain mydomain.com
Get-CsAdUser -Filter {Enabled -eq $True} | ForEach-Object {Set-CsUser -Identity $_.SipAddress -AudioVideoDisabled $true}
Get-CsAdUser -Filter {Enabled -eq $True} | ForEach-Object {Grant-CSClientPolicy -Identity $_.SipAddress -PolicyName "IM Only Policy"}
Get-CsAdUser -Filter {Enabled -eq $True} | ForEach-Object {Grant-CsArchivingPolicy -Identity $_.SipAddress -PolicyName "Archive Policy"}
But even before starting this I had not used the ForEach-Objech command or even undersood the real value behind piping ("$_.SipAddress" is a property rendered from the initial query that only returns Enabled Lync users.
So then I was off to Phase 2 of by dastardly plans for World Domination which was to build an IM stress test tool for Lync that takes a couple of parameters, floods the system and doesn't require me to create a bunch of users in Active Directory and/or ask people for their passwords. To do this I'm using UCMA application endpoints that I will wire up at real-time and have them talk to each other.
So of course when I build anything I always want it to be self-contained. If I'm downloading free code, I want to install it and run with it. Not have to do 10 things somewhere else before I can use it - enter Powershell and C#. Having done this before with Exchange I was pretty confident that this wouldn't be too bad. If you are doing this straight from Powershell (not auto-provisioning your endpoints via UCMA) the execution order looks a little like this;
New-CsTrustedApplicationPool -identity entpool.mydomain.com -Registrar entpool.mydomain.com
Enable-CsTopology
New-CsTrustedApplication -ApplicationId "IMTester" -TrustedApplicationPoolFqdn entpool.mydomain.com -Port 5081
Enable-CsTopology
New-CsTrustedApplicationEndpoint -ApplicationId urn:application:imtester -TrustedApplicationPoolFqdn entpool.mydomain.com -SipAddress sip:IMUserA@mydomain.com -DisplayName IMTesterA
Not too bad - create a TrustedApplicationPool (if one does not already exist), reflect the change back to your topology, create the application, again enable topology and then start creating your endpoints. All-in-all pretty easy, until I got into the C# code.
I initially started with the following code to start Powershell and bring in the Lync module;
if (_runspace == null)
{
InitialSessionState state = InitialSessionState.CreateDefault();
_runspace = RunspaceFactory.CreateRunspace(state);
_runspace.Open();
}
_shell = PowerShell.Create();
_shell.AddScript(@"import-module Lync");
_shell.Commands.AddCommand("Out-String");
However when I did this I then started getting errors about the Powershell Code Policy and the module not actually being loaded (no notice given UNTIL I started doing something). I dug around and found an associated post where buddy basically boiled it down to two ways of accessing Lync Powershell from C#, the full article is here, but the one I went with is here;
if (_runspace == null)
{
InitialSessionState state = InitialSessionState.CreateDefault();
state.ImportPSModule(new[] { "Lync" });
_runspace = RunspaceFactory.CreateRunspace(state);
_runspace.Open();
}
_shell = PowerShell.Create();
I'm still trying to decipher the two methods, I know I have used the first snipped successfully when working with Exchange 2007 and never encountered an error at all. In addition to running the above "special" code snipped I had to modify the execution policy for Powershell on my server to "Unrestricted".
I'm not completely sold on these changes (one of those, keep making small changes until the experiment is so dirty you don't know if your problem mutated along the way) and right now I'm working on my dev server. Later this week I plan on bringing the code back into the office to give'r a whirl to see if I encounter the same issues.
Build Products as you would Run a Race
When I was training for running a half-marathon years ago the most important advice I received was to overtake people on the hills. I never understood what that meant until the day I was running against 2,000+ participants in the race. A Half-Marathon is a 21km race (Canadian), in practice trials I had run two before the big race with the number and chip. When the race started, everyone took off very quickly, I had no idea why but thought I would stay with the group, then when we turned around the corner, out of site of all spectators everyone slowed to their respective paces. And herein came the first lesson that I observed.
Lesson #1: Run your own race, don't put on a show for people - you only waste your own energy on activities that could be in direct conflict with achieving your own.
So the race continued, I set my pace, moved forward doing my own thing. I had never been in any kind of race like this before so it was completely new to me, I kept on going - blocked out all the people passing me - set a goal to stop every second drink station and walk while I drank (mainly because I didn't want to drop gatorade all over myself) and pushed on.
Lesson #2: You will not know everything, so start with something, set measureable goals and move towards them.
Then came Kilometre #13, it was at this point in the race that I had 8km left and I decided to start picking up the pace. I didn't come to not give it my all and not hurt the next day. But how and where? And then I remembered the key lesson that made no sense to me in training - "take them on the hills". And I did, when the ground was flat, I kept my pace, but when the inclines started to come (and many did), I pushed past people, many people. How did I do this?
Lesson #3: We all have a natural tendency to slow down as obstacles are put in our way. The thing is, so does everyone else, so the best time to put that extra pedal to the medal is when everyone is faced with the same hurdle. Changes in the product platforms, adding new features, etc.
Building products is very different then building a startup, you might be sprinting in the early days of a startup but you can't sustain it forever. Building a great product is extremely different and requires you to find your own rhythm, set your goals and power through the obstacles.
Meetings are like...
I find it interesting how an organization's culture shapes the framework for how a meeting is run. Whether it's meeting minutes, a scheduled agenda, people playing buzzword bingo, people checking their phones, etc, etc. I've had a lot of meetings with different audiences over the past couple of months and I've come to compare all meetings to video games. I don't classify them by genre or console, no I classify them by game.
Halo Meetings - Not be confused with "Left 4 Dead" meetings, Halo meetings occur when the sh*t is about to hit the fan (or it is), the chips are down, everyone's been putting in the extra time and the troops are just running ragged. This is when you bring in the Master Chief, he gives you a new clip, offers some words of encouragement and sends you on your way. You have an objective, you have checkpoints and if people can't keep up, move on.
Civilization Meetings - Now let's be clear, I'm not talking Civ I, I'm talking the latest Civ (4 or 5). These meetings are all about diplomacy, establishing relationships, keeping the peace and trying to push that bar forward. It doesn't matter how far forward, it just has to go forward. At the end of the meeting, if the projected moved forward an inch, it moved, if it moved forward 100 yard, it moved. That's all that matters, that and don't upset your neighbours, keep the peace and move on.
Driver Meetings - Okay, remember Driver when it first came out? I loved that game, it was the best game with one single objective. Get away from everything, don't stop at checkpoints, race through them. Driver meetings are most commonly witnessed in the presence of Project Status Meetings that are on a time limit. Here's the status, got a question, too long, hold it for next time, we got to move onto the next thing. You always know when you're about to enter a Drive meeting before you enter the room, you look at the Agenda, you look at your calendar and all you can think is - "No @#$#@ way", and then its time to hit the gas.
Myst Meetings - Remember Myst? Remember the frustration in that game? I can't count how many times I walked away from my computer ticked off at all the stupid puzzles in that game - "yes I would like to turn the crank, but you need to let down the drawbridge, to turn the key, to let the pail come down that holds the screw to turning the crank". Not my game and these are definitely not my meetings. I don't like wishy, washy meetings that start off with a clear objective (finish, achieve X), but get so screwed up along the way that by the end no one knows what you are supposed to be doing. Congratulations you just wasted an hour of everyone's time.
Grand Theft Auto Meetings - Aaah the GTA meeting - despite its redefining "Open Game Concept" - it does not make for a great meeting. You are not in a meeting to explore a world - "Okay so this bug has an issue with the SDK, what version of the SDK are we running, did we need to upgrade, what does everyone think of the SDK, why don't we go download this other SDK and try that, is this really a bug, it sounds more like a ... feature (or read quest). GTA - great game, bad meeting.
Starcraft Meetings - And I've saved the best for the last. The Starcraft meetings are interesting to be a part of, everyone is protecting their own and hoarding resources. What does that remind you of? Yes that's right... budget meetings - "Well if I dont' get x budget (crystals) I can't deliver y project (need Siege Tank). Yes Starcraft meetings emerge when resources are on the table, whether they be people, hardware, software, budgets, travel, etc, etc.
I'm sure there are more variants out there, these are the ones that have popped into my head over the last few months, culminating with today's Civilization meeting).
Perhaps this makes sense, perhaps it doesn't, all I know is I have a LAN party to go this weekend and I can't find my Starcraft CD.
Team Sports and Developers
Not usually two words you here go hand-in-hand but here I was thinking about this over the weekend and it brought up some past thoughts I had on the subject. It's always an interesting experience the first time you play a team sport with a co-worker, we've all been there and at the end of it the reactions usually range from it having been a great experience to you preferring to have a root canal done... twice... in the same day. Having thought about this a little over the weekend I got to thinking about every interview I've ever conducted where I asked a question related to teamwork, leadership, conflict, etc (you know the soft-skills, the skills that separate the transformers from the toaster ovens);
Do you enjoy working in teams or on your own? Oh both, yessir, I am definitely a team player but I am also happy to work on my own and get the job done. (They should post that answer on StockAnswers.com and rent it out).
Or
How would you resolve a conflict with a fellow co-worker or manager? Oh, well, let's be honest we wouldn't have any disagreements (wink, wink) BUT in the odd case that we would, I'd get everyone together and talk through it calmly and rationally so we can come to a win-win conclusion for everyone involved (again see StockAnswers.com).
Now let's re-phrase the two questions into some sports venacular;
If you are on my team, are you going to pass the ball or try and take it to the net on your own, every time, even when someone is open?
Or
When someone from the other team commits a penalty against you are the type to go nuts on that player argue to the nth degree with the referee, maybe seek some retribution? Or do you move on and keep playing?
Both sets of questions are pretty much the same, the only thing that changed was the context. You might think the adreline only comes into play in sports, but you'd be wrong - I've seen developers become possessive and highly argumentative about theirs and others code - true story.
It's very probable that the answers you would get to the above questions would be from StockAnswers.com, but maybe some die-hard players would start to open up a little bit (which is what we want);
- "Well if the opposing team is running my goalie, I'm going to get in their way and block them" - alright, willing to take one for the team and protect his group - leadership potential.
- "Well the ball went out on me and the ref called it the other way so I told him it was on me" - solid, honesty and respect for other teams in the organization.
- "I scored on our team once, but went out and kept trying" - READ: when I broke last night's build, it was my fault, so I stayed later to get it up and running so QA wouldn't be too far behind.
I wish it were that easy, I love both individual and team sports - I love seeing the transitions in personality in people I work with and when you step back to watch them you can totally see the similarities in how they approach their work, their style and ethics.
I am seriously looking forward to my next Interview because I'm thinking I'm going to hold it in a gym - play a little one-on-one, floor hockey, dodgeball, anything - if they get past that phase, I'll inject some technical questions near the end. At the very least, if the interview goes sideways I would have gotten some exercise and had a fun night at the gym.
BTW - We need more examples of sportsmanship like this - http://www.youtube.com/watch?v=NOMN__ozGSI
How to build a great Framework
Developers get delirious with excitement when you give them the task to build a new SDK or a framework - they immediately think of building something that will rival any and all frameworks that have come before them and that it will be so flexible it will be able to do things you have yet to think of. Think I'm exaggerating... go ahead... ask one of your Developers and watch their eyes light up. So if the desire to write a framework is met with such unbridled enthusiasm and ambition - why do the implementations for a number of SDKs suck and what makes a good framework? It really isn't complicated when you think about what you need to do.
Imagine you are the Consumer
When I start writing a framework that other developers are going to consume, the first thing I start writing is some pseudo code (a great combo of C#, JavaScript, maybe some XML or SQL, whatever) that I use to define the interface of how users will use the API. The goal here is to make accessing your work as efficient and logical as possible. I.e., do I really need 12 overloads on that 1 method? Will someone be able to connect the dots between initializing this member before calling this function to fire this event? If you can't logically walk the steps than how do you expect your users to? There is a great book out there called Framework Design Guidelines - it's all about some of the people that wrote the .NET framework - what they did right, what they did wrong. The book is 4 years old now, but it is such a great reference for accomplishing this sort of task. My favourite part is hearing from the guys who designed the System.IO namespace - when they put it in front of some skilled developers no one could figure out how to use it. It's an incredibly powerful namespace with much more functionality then its predecessors but the usability fell flat when put in front of its core audience.
Meaningful Responses
Alright - so you've got an API that's great to work with, users are getting it and then they hit an exception or error of some sort and what they get back is completely meaningless garbage that gives them no guidance as what they should try next. I love using "mature" .NET Interop wrappers that are specifically built to wrap around the complexity of COM components to make it easier for you to use only to give you some error that gives you an HRESULT to go with. What they couldn't intercept the message and write some code around what was going on internally? If you are lucky someone on the internet has encountered the same issue, if you are really, really lucky - that person has figured out what the error means, otherwise you're on your own to start down the road of trying to figure out what this error alludes to. I use COM Interop as an example, but there are many other examples - just the other night I was using the .NET Entity Framework against SQLCE4 and kept getting some "cannot open db" error. When I drilled down 6 levels in the inheritance chain I finally found that the error was in the password of my connection string. If this had of been bubbled up to the top of the stack I could have blissfully moved on (and saved myself some time). The point here is, you know why exceptions and failures are happening, so take the time to craft some informative messages to your user: Error - Impact - Suggestion. In the case of my EntityFramework example; "Cannot connect to the database, data will not be loaded, check your datasource or password in your connectionstring". Wordy? Maybe. Useful? Hell yeah.
Document thy Work
I don't want to read a 400 page novel on how to use your API - sometimes I do, but not 85% of the time. I just want to get up and running ASAP. .NET gives you the most simplistic tools to write comments - /// - that's it, type those 3 characters over any method, class, etc and it will give you the structure to work within. But do you do it? Really do you? But how much do you depend on it to help you in your daily programming? Recently I was working with this API that applies some metadata to files - it had NO documentation and NO comments. To top it all off it had great method signatures like GET, SET, DUMP, PEEK. A lot of my time was spent trying to determine which methods I should use in my task but had to aimlessly try different implementations. Something like - GET - Opens the file exclusively to access metadata, PEEK - Accesses the file's metadata without creating an exclusive lock - would have helped immensely. If you are writing external documents that your users need to read, add a reference to it in your code - what harm does that do? Here's a secret, beyond it's self-explanatory name, no one reads the "README" file until after they have hit an error, no one. So putting a comment into your code that says - "If you are trying to do this and are encountering errors, see the ReadMe file" is not going to ruin your framework.
Test Coverage
Over the last few weeks of 2011 I've been evaluating some logging frameworks for some applications that I have been working on. (I'll blog about my favourite one in my next post). When I installed some of these frameworks, I saw they had Unit Tests - great I thought, let's run these badboys and see what this baby can do. I was blown away when some where broken and didn't run. Here I was spending time validating unit tests when I wanted to be coding MY application. If the Unit Tests are broken, surely I must have done something wrong right? Not necessarily, in some cases there were some errors in the code - either through knowledge of known issues or lack of additional frameworks. If you are going to validate your framework against Unit Tests (YES PLEASE DO) then the onus is on you to make sure these things are rock solid against each and every release. If they are not and you make the call to not fix them (that's cool) do your users a favour and yank them. No harm no foul, I see no Unit Tests, I'm not going to try and run them (heck I won't even know they were broken). The last thing you want to do is give a guy a reason to not even look at your framework because your test suite broke before they even started writing code.
So here's the thing - developers can be lazy (not all, but we are a strong and proud number) and by having a simple API, with straightforward documentation with enhanced and useful response codes/messages that is well-tested and provides (PLEASE) a valid Unit Testing project you will be well on your way to getting your framework adopted by your developer community and getting the word out on what a great framework it is. Think of the last framework, third-party API, whatever you used - when it went great what was the first thing you said - "It was easy with component ABC" - that's what you want to happen, that's your end goal, always.