Tuesday, 14 June 2011

WINRM - Loosely Translated as SSH for Windows

When I am developing a side project, I always make sure it is on a different operating system and a different language than what I would normally use in my day job.  I want there to be a clear distinction or else the lines can become all too blurred.  My current side project is written in ruby and rails and it is while developing this that I have fallen in love with both SSH and Capistrano.  SSH or secure shell is a protocol for remote administration of Unix computers.  Simply put, SSH allows me to stay in the same terminal instance when I am moving from my client machine to other remote servers.  

Capistrano is a DSL for deploying ruby on rails applications.  Capistrano has highlighted just what a gaping hole this is in current ugly .NET deployment practices.  I very much include my own crude powershell scripts in this dirty breed.  Capistrano uses SSH to connect to the remote server and run your deployment from your client machine.  Pretty nifty and yet another source of rails envy I now have.

Returning to my day job and windows, I missed this facility and started looking at powershell for a similar capability.  There is more than one way of executing powershell on a remote server.  Winrm looked to be the best fit for me.  With winrm, you can start and finish powershell sessions on the remote server.  In the examples I am about to give, all the machines have powershell 2.0 installed.  There are different requirements for each operating system.  The following guide should help you install winrm on the client and on any remote servers you wish to access.

Enabling Winrm on a remote Server for Client Requests

Enabling WinrRM between computers on the same domain is very easy, simply run the following command in an elevated Powershell console on the remote server.  

PS> Enable-PSRemoting                  

You should get a response like this:



If you do not get a response like above you might want to check that winrm is installed and that the windows service is running.

By default winrm runs over http on port 5985 and you might need your network guys to open a hole in the firewall for this port.   It took the network guys I work with five weeks to accomplish this task which is an absurd amount of time for such a task but I better not get into that now.  We also restricted access to this port to an I.P. range for extra security.  

If the server is on a different domain, you also need to run the following command which sets a registry entry that allows a client server to authenticate from a different domain to the local server.

PS> New-Itemproperty -name LocalAccountTokenFilterPolicy -path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -propertyType DWord -value 1

Another gotcha that I fell for is to make sure that you restart the winrm windows service to pick up the changes. 

Enabling Winrm on the Client

You might not need to do this but I had to add a trust entry for every server I wanted to connect to with the following command on my workstation:

PS> winrm s winrm/config/client '@{TrustedHosts="samedomainserver,99.999.999.999"}'       

You will note that I have more than one server listed here and they are comma delimited.  I also have a computer name and an I.P. address in my list.  The IP address is for a server on a different domain.

Executing Commands on the Remote Server

There are two ways that I know of executing commands on the remote server.  The first is by invoking the Invoke-Command cmdlet which allows you to access one off commands:

PS>  Invoke-Command -ComputerName MyRemoteServer -ScriptBlock {Get-Process} -Credential Get-Credential   

The Get-Credential cmdlet opens a windows form dialog to allow you to log in against the required account:



The second allows you to start a remote powershell session using the Enter-PSsession cmdlet:

PS> Enter-Pssession -ComputerName MyRemoteServer -Credential Get-Credential            

I can also exit my remote session with the Exit-PSsession cmdlet.                                                                                                            

The Icing on the Winrm Cake

I talked about the powershell profile in this post and starting a remote powershell session is a prime candidate for adding to my powershell profile.  I have the following two functions defined in my powershell profile:

  1. function PS-Production
  2. {
  3.     Enter-PSSession -ComputerName 99.999.999.999 -Credential Get-Credential
  4. }
  5.  
  6. function PS-Demo
  7. {
  8.     Enter-PSSession MyRemoteServer -Credential Get-Credential
  9. }

It can get confusing when bouncing about from server to server so I have the following function in my profile to let me know exactly which account I am running under:

  1. function whoami
  2. {
  3.     (get-content env:\userdomain) + "\" + (get-content env:\username);
  4. }

If you are on windows and still flapping about with Dos or worse, using windows explorer to do everything then I beseige you to pick up powershell.  It is worth the effort.

I think a capistrano like experience could be created with powershell and winrm.  Maybe something I will look into at some stage.


Tuesday, 7 June 2011

Gracefully handling Nil and Empty in Ruby

One of the nice side effects of extension methods in .NET is that you can easily handle nulls without littering your code with null checks.  

For example if you look at the following extension method that I have defined in C#:

  1.      public static bool HasElements<T>(this IEnumerable<T> collection)
  2.      {
  3.          return collection != null && collection.Count() != 0;
  4.      }

I can then use this method on any object that is an IEnumerable of T:

  1.     if (trainingEvent.Contacts.HasElements())
  2.     {
  3.         //do something
  4.     }

Which is much easier on the eye than:

  1.     if (trainingEvent.Contacts != null && trainingEvent.Contacts.Count > 0)
  2.     {
  3.         //do something
  4.     }

The reason this is possible is because an extension method in .NET is really a bit of syntactic sugar that effectively rearranges the method into a static method call, which might be equivalent to this:

  1.     if (EnumerableExtensions.HasElements(trainingEvent.Contacts))
  2.     {
  3.         // do something
  4.     }

It is all done with compiler magic.

When coding in Ruby, I found myself wanting the same experience.  All too often, I found myself writing code like this:

  1. if !lead.address.nil? && !lead.address.empty?

or this:

  1. if lead.contacts.nil? || lead.contacts.empty?

In ruby everything is an object even Nil (null in .NETspeak) and everything is open for extension.  You just redefine the class and add your own customisations.  I actually thought about extending Nil myself before telling myself that was very hacky.  I then found out that this is exactly what happens in the core extensions of the activesupport module.

In this set of extensions, the authors have extended a number of the core objects to add support for a blank? method.  According to the documentation:

An object is blank when it's false, empty or a whitespace string.  

All that I need to do is add the following line to my ~/config/initializers/requires.rb file and I get the blank? extension method over the whole project.  

  1. require 'active_support/core_ext/object'

I can then use blank? with strings:

  1. if !address.blank?

Or with arrays:

  1. if lead.contacts.blank?

That will take care of nil, empty strings, and arrays with no elements.

I get the same result for arrays, booleans and hashes.

So how is this achieved?  A quick look at the source reveals that some of the core objects are extended (hence the name stupid!).

For example the Nil class is extended to always return true for a call to blank?:

  1. class NilClass #:nodoc:
  2.   def blank?
  3.     true
  4.   end
  5. end

This will obviously elegantly handle all our nil? cases in one full swoop.  The code then opens up several other classes for extension and adds the blank? method.

For example Array is opened and a nice alias is added to enable a call to blank? to respond with empty?

  1. class Array #:nodoc:
  2.   alias_method :blank?, :empty?
  3. end

The Sting class is nicely extended with the ruby not matches operator on a simple regex:

  1. class String #:nodoc:
  2.   def blank?
  3.     self !~ /\S/
  4.   end
  5. end

But the nice bit is the extension that is added to the Object class:

  1. class Object
  2.   def blank?
  3.     respond_to?(:empty?) ? empty? : !self
  4.   end
  5. end

The respond_to? method simply checks whether the object you are sending a blank? message to has such a method.

There are other useful extensions in this module that you can find out about here.

I think this is quite nice and has tidied up my code a lot.  


If you are a seasoned Ruby developer, you probably knew this and have not bothered reading this far.