Comparando C# com PowerShell no Desenvolvimento de Scripts

No lançamento do Windows Server 2008 li diversos artigos falando como o PowerShell (PSH) é poderoso. O meu interesse para aprender essa linguagem começou a aumentar após o PowerShell v2, devido as novas extensões, especialmente a do ActiveDirectory. Além disso, a capacidade de usar e/ou instanciar as funções do .NET no PowerShell, teoricamente, facilitam a sua utilização para quem conhece C#.

De forma a experimentar um pouco do PSH, resolvi fazer um pequeno teste. Selecionei um programa em C# desenvolvido em 2005 e o portei para PSH. O programa é bem simples, ele procura os objetos AD do tipo computer que não sincronizam a senha com o AD a mais de 90 dias. Esse script é muito usado para avaliar quais estações de trabalho não estão mais ativas.

De forma a facilitar o teste, retirei as interações com o usuário que perguntavam o domínio e tipo de objeto AD.

O teste não tem como objetivo analisar qual a melhor linguagem de programação, mas avaliar a facilidade, flexibilidade e poder para desenvolvimento de scritps. Não está em questão desenvolvimento de sistemas.

Seguem os códigos:

C#

 

using System;

using System.Text;

using System.Xml;

using System.DirectoryServices;

using ActiveDs;

 

namespace ADpwdLastSet

{

       public class ADpwdLastSet

       {

              public static void Main(string[] args)

              {

                     int count = 0;

               int count2 = 0;

                     System.DirectoryServices.DirectoryEntry adRef =

                           new System.DirectoryServices.DirectoryEntry("LDAP://DC=CONTOSO,DC=COM");

             

                     System.DirectoryServices.DirectorySearcher adSearcher = new

                           System.DirectoryServices.DirectorySearcher(adRef);

                     adSearcher.PropertiesToLoad.Add("Displayname");

                     adSearcher.PageSize = 5000;

                     adSearcher.Filter = "(&(objectClass=computer))";

                     foreach(System.DirectoryServices.SearchResult Result in adSearcher.FindAll())

                     {            

                           count ++;

                            System.DirectoryServices.DirectoryEntry ObjComp =

                                  new System.DirectoryServices.DirectoryEntry(Result.Path.ToString());

                                                      

                if (ObjComp.Properties.Contains("pwdLastSet"))

                           {

                                  try

                                  {

                        IADsLargeInteger li = (IADsLargeInteger)ObjComp.Properties["pwdLastSet"][0];

                                         long date = (long)li.HighPart << 32 | (uint)li.LowPart;

                                         DateTime dtTime = DateTime.FromFileTime(date);

                                         //Console.WriteLine(dtTime.ToString());

                        if (dtTime.AddDays(90) < DateTime.Now)

                        {

                            count2++;

                            Console.Write(Result.Properties["DisplayName"][0].ToString() + "\t");

                            Console.WriteLine(Result.Path.ToString());

                        }

                                  }

                                  catch(Exception e)

                                  {

                                         Console.WriteLine(e.Message);

                                  }

                           }               

                     }

                     Console.WriteLine(count2.ToString() + "Computadores que não sincronizam a 90 dias de " + count.ToString());

              }

       }

}

 

PowerShell v2

 

PS > function ConvertTimeStamp([double] $TimeStamp)

>> { $ts=(get-date 1/1/1601).adddays(($TimeStamp)/(60*10000000)/1440)

>> $ts }

>> 

PS > Get-ADObject -LDAPFilter "(objectClass=computer)" -SearchBase 'DC=contoso,DC=com' -Properties Name,pwdLastSet | ForEach-Object { $dts=ConvertTimeStamp($_.pwdLastSet); if ($dts.Adddays(90) -lt (Get-

Date)) {$_.Name + " - " + $dts}}

 

A única diferença no meu teste é que o programa em C# apresenta também a quantidade de objetos verificados e os que estão a mais de 90 dias sem sincronizar. Entretanto, pela diferença de linha de código do C# e do PSH é fácil de concluir que essa informação é facilmente tirada em mais duas linhas no PSH.

Eu utilizei apenas os recursos da Internet para me ajudar a entender o PowerShell, demorei menos de 2 horas para portar o script, o que mostra a facilidade de desenvolvimento, mesmo para quem não esta familiarizado com a linguagem.

Outro ponto MUITO importante é que para desenvolver em PowerShell basta você o ter disponível (o que já é padrão no Windows Server 2008 e Windows 7), e para desenvolver em C# é preciso instalar o Visual Studio em algum computador. No caso específico deste teste, em PSH não foi preciso gravar um arquivo para execução, montei a função diretamente no prompt e na linha seguinte já consumi a função.

Se você ainda resiste ao PSH acredito que o exemplo acima o incentive a estudar a linguagem. Eu já sucumbi, e a partir de agora meus scripts vão ser todos em PSH de forma a criar uma biblioteca da linguagem.

Se você quiser aprender um pouco mais sobre PowerShell recomendo os links abaixo:

Scripting with Windows PowerShell

https://technet.microsoft.com/en-us/scriptcenter/dd742419.aspx

TechNet Webcast: Next Generation Command Line Scripting with Monad

Part 1

https://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032277851&EventCategory=5&culture=en-US&CountryCode=US

Part 2

https://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032277853&EventCategory=5&culture=en-US&CountryCode=US

PowerShell on Channel9

https://channel9.msdn.com/tags/PowerShell/

Monad on Channel9

https://channel9.msdn.com/tags/Monad/

 

By Artur Rodrigues.