Archives

Archives / 2014 / August
  • Why every .net developer should learn some PowerShell

    It has been 8 years since PowerShell v.1 was shipped in 2006. I have looked into PowerShell closely except for using it in the Nuget Console. Recently, I was forced to have a much closer look at PowerShell because we use a product that exposes its only interface in PowerShell.

    Then I realized that PowerShell is such a wonderful product that every .net developer should learn some. Here are some reasons:

    1. PowerShell is a much better language that the DOS batch language. PowerShell is real language with variable, condition, looping and function calls.
    2. According to Douglas Finke in Windows Powershell for Developers by O’Reilly, PowerShell is a stop ship event, meaning no Microsoft server products ship without a PowerShell interface.
    3. PowerShell now has a pretty good Integrated Scripting Environments (ISE). We can create, edit, run and debug PowerShell. Microsoft has release OneScript, a script browser and analyzer that could be run from PowerShell ISE.
    4. We can call .NET and COM objects from PowerShell. That is an advantage over VBScript.
    5. PowerShell has a wonderful pipeline model with which we can filter, sort and convert results. If you love LINQ, you would love PowerShell.
    6. It is possible to call PowerShell script from .net, even ones on a remote machine.

    Recently, I have to call some PowerShell scripts on a remote server. There are many piecewise information on the internet, but no many good examples. So I put a few pointers here:

    1. When connecting to remote PowerShell, the uri is : http://SERVERNAME:5985/wsman.
    2. It is possible to run PowerShell in a different credential using the optional credential.
    3. Powershell remoting only runs in PowerShell 2.0 or later. So download the PowerShell 2.0 SDK (http://www.microsoft.com/en-us/download/details.aspx?id=2560). When installed, it actually updates the 1.0 reference assemblies . On my machine, they are in: C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0

     

    So the complete code runs like:

    using System.Management.Automation; // Windows PowerShell namespace
    using System.Management.Automation.Runspaces; // Windows PowerShell namespace
    using System.Security; // For the secure password
    using Microsoft.PowerShell;
    
    	    Runspace remoteRunspace = null;
                //System.Security.SecureString password = new System.Security.SecureString();
                //foreach (char c in livePass.ToCharArray())
                //{
                //    password.AppendChar(c);
                //}
                //PSCredential psc = new PSCredential(username, password);
                //WSManConnectionInfo rri = new WSManConnectionInfo(new Uri(uri), schema, psc);
                WSManConnectionInfo rri = new WSManConnectionInfo(new Uri(""http://SERVERNAME:5985/wsman"));
                //rri.AuthenticationMechanism = AuthenticationMechanism.Kerberos;
                //rri.ProxyAuthentication = AuthenticationMechanism.Negotiate;
                remoteRunspace = RunspaceFactory.CreateRunspace(rri);
                remoteRunspace.Open();
    
    	    using (PowerShell powershell = PowerShell.Create())
                    {
                        powershell.Runspace = remoteRunspace;
                        powershell.AddCommand(scriptText);
                        Collection results = powershell.Invoke();
                        remoteRunspace.Close();
                        foreach (PSObject obj in results)
                        {
                            foreach (PSPropertyInfo psPropertyInfo in obj.Properties)
                            {
                                Console.Write("name: " + psPropertyInfo.Name);
                                Console.Write("\tvalue: " + psPropertyInfo.Value);
                                Console.WriteLine("\tmemberType: " + psPropertyInfo.MemberType);
                            }
                        }
                    }