lab49feature-drdobbs-windowspowershell

Upload: xmeszeus

Post on 07-Apr-2018

216 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/6/2019 Lab49Feature-DrDobbs-WindowsPowershell

    1/16

  • 8/6/2019 Lab49Feature-DrDobbs-WindowsPowershell

    2/16

    First, this PowerShell example illustrates the use of the range operation. Second, although no explicit looping or print com-mands are defined, note that PowerShell iterated and printed the numbers in the range. This is not to say that PowerShelllacks looping constructs (it has foreach, for, do, and while). Rather, it is an example of abstracting away unnecessarydetails. This is a key idea behind PowerShell.

    Here is an example of using ForEach and a glimpse at piping with PowerShell.

    Note the $_ variable in the previous example. This is an automatic PowerShell variable indicating the current object in thepipeline (variables will be discussed later). In short, PowerShell preserves the looping constructs you are familiar with andprovides simpler ways to get things done.

    How Does PowerShell Work?

    When starting to work with PowerShell, one of the first things youll use is a cmdlet (pronounced Command Let). Acmdlet is a single-feature, built-in command a building block by which an operation is completed. For example, one suchcmdlet is Get-Date. Note the verb (Get) and noun (Date) are separated by a dash; all cmdlets use this memorable verb-noun form. You can imagine what Get-Date does it returns the date. PowerShell also makes use of familiar commands,

  • 8/6/2019 Lab49Feature-DrDobbs-WindowsPowershell

    3/16

    such as dir. (Digging a bit deeper, you find that dir is a memorable alias for the Get-ChildItem cmdlet.) The cmdlets deliv-ered with PowerShell are covered later.

    The runtime performs another role information used within the environment is done through structured information:objects with properties. These data objects are compatible with the .NET Framework. Data objects are supplied to and fromcommands through the pipeline. PowerShell pipes objects and provides parameter binding. This innovation provides rapiddevelopment of software solutions for many challenges. Developers are not burdened with creating plumbing betweencmdlets.

    How Does PowerShell compare with .NET?

    PowerShell provides features that are accessible and robust. For example, you can create an XML document in a variablebased on the contents of an XML file. Refer to the following example:

    The task can be completed in a few keystrokes. In contrast, to accomplish the same task in .NET requires several steps andbackground information: launch the IDE, create a project, know the System.Xml namespace, and use the Load method. Yeteven after all those steps, the data has yet to be printed. To print the data requires returning to the IDE, adding more code,compiling, running, and waiting for the results. In PowerShell, you can easily see the nodes:

  • 8/6/2019 Lab49Feature-DrDobbs-WindowsPowershell

    4/16

    Programs help users concentrate and focus by quickly providing user feedback to issued commands. (Inellisense is a goodexample of employing such feedback loops.) PowerShell, is a terrific high-speed feedback loop at many levels.

    Real-World Examples in PowerShell

    One of the most effective ways of highlighting the flexibility and usability of PowerShell is by example. The following twoexamples focus on simple handling of directory listings. However the principles demonstrated here will be applicable toother areas of PowerShell.

    Example 1: Handling Directories using PowerShell

    This example addresses some practical examples for using PowerShell to list the contents of directories. Consider if you wantto simply list all files in a directory and below that have been modified within the past week. You could resort to walkingthe directory structure and try to capture the output in DOS. Or, you might use a number of other creative approaches. WithPowerShell, the solution is efficient and elegant-two cmdlets work collaboratively (dir and where) using pipes.

    dir . -r | Where { $_.LastWriteTime -ge (Get-Date).AddDays(-7) } | Select name

    In reviewing this code, we see that objects with properties-not text-is being piped between commands using the pipe (|).First, a recursive directory listing is retrieved (using the -r flag). The dir cmdlet produces a System.IO.FileInfo object foreach located item, based on the parameters passed. Each time this object is presented, it is piped to the Where cmdlet.

    The Where cmdlet allows a script block; this is defined between the two curly braces. The $_ is a PowerShell automatic

    variable which has the current object in the pipeline (a System.IO.FileInfo outputted from the dir cmdlet). To access the con-tents of the date property, the conventional object notation is used: $_.LastWriteTime. The purpose of LastWriteTime is usedto restrict the list to only those files modified within the last seven days. Finally, the name of the file is displayed. All this isaccomplished in one line of code.

    A similar command-only restricting by a fixed date and a filetype of .cs-would be:

    dir . -Recurse *.cs| Where {$_.LastWriteTime -gt "11/14/2006"}

    Note in this example that the -gt represents the greater-than comparison operator. The LastWriteTime is of typeSystem.DateTime, so when the greater than comparison is done, PowerShell coerces the .LastWriteTime and String for us to

    be compared. Note also that the mathematical greater-than symbol ">" cannot be used; PowerShell interprets that characteras a command to redirect the output.

    Example 2: Formatting Directory Outputs using PowerShell

    Taking the previous example one step further, we can also define the format of the output by using the Sort-Object andFormat-Table cmdlets. The Format-Table cmdlet trims down the verbose data. The -AutoSize parameter automaticallyadjusts the contents of each column. We can also define the properties we wish to be printed-specifically each filesLastWriteTime and Name.

  • 8/6/2019 Lab49Feature-DrDobbs-WindowsPowershell

    5/16

    dir . -Recurse *.cs| Where {$_.LastWriteTime -gt "11/12/2006"} | |Format-Table -AutoSize LastWriteTime, Name

    We can also use wildcards when providing the properties to Format-Table such as *Time. This will display any property thatends with the letters Time. This will produce a table with CreationTime, LastAccessTime and LastWriteTime as shown inthe following screenshot.

    Notice the retrieved data is in random order. By inserting a pipe to the Sort-Object (between the Where and Format-Table)and adding the LastWriteTime as a parameter, we can sort the files by when the file was last written.

    dir . -Recurse *.cs| Where {$_.LastWriteTime -gt "11/12/2006"} |Sort LastWriteTime | Format-Table -AutoSize LastWriteTime, Name

    To see the table in descending time order, add the -Descending parameter to the sort cmdlet.

  • 8/6/2019 Lab49Feature-DrDobbs-WindowsPowershell

    6/16

    dir . -Recurse *.cs| Where {$_.LastWriteTime -gt "11/12/2006"} |Sort LastWriteTime -Descending | Format-Table -AutoSize LastWriteTime, Name

    To review, PowerShell shows its strengths by being able to pipe output through multiple commands to achieve the desiredoutput.

    Functionality in PowerShell

    Weve introduced to the power of PowerShell and some examples of how it can be used in daily operations with directories.Now, well review some of the common operations within PowerShell and how they work together to achieve time-saving

    results. This will be fundamental for our deeper dive into PowerShell.

    Parameters in PowerShell

    PowerShell is about automation and saving time. This is applicable to both using cmdlets and as well see later-authoringthem. In the previous example, three parameters have been specified to three of the cmdlets. -Recurse, -Descending and -AutoSize. PowerShells parameter binding mechanism accepts -R, -D, and -A as legal representations.

    When a cmdlet supports multiple parameters, such as Path and Pass, parameter binding allows the fewest characters to betyped for a match to bind. For example, the characters of Pat and Pas are sufficient for the Path and Pass parameters.

    Get-Stuff -Pat "c:\" -Pas $true

    Additionally, you do not need to be concerned with the order of parameters when authoring cmdlets. This is handled byPowerShell.

    Providers in PowerShell

    You can access the help facility within PowerShell by typing help about_provider at the command line. The short descrip-tion on providers is as follows:

    Windows PowerShell providers provide access to data and components that would not otherwise be easily accessible at thecommand line. The data is presented in a consistent format that resembles a file system drive.

    Using another cmdlet that ships-Get-PSDrive-yields the following:

  • 8/6/2019 Lab49Feature-DrDobbs-WindowsPowershell

    7/16

    So what does this mean? It means you can change directory to the registry, certificate store, environment variables, variablesyou create, functions you create and even your C drive.

    Furthermore, because these providers are similar, cmdlets such as dir (aliased for Get-ChildItem) operate as if they wereanother drive mapped to your system. For example, if you execute cd HKLM: you will navigate to the registry. Typing dirdisplays the contents of that registry. Similarly, you can cd to SOFTWARE and display its contents.

    For information about an alias, you can use the Get-Alias cmdlet. The command Get-Alias dir would retrieve the following:

    Objects in PowerShell

    Since PowerShell is based on .Net, you can create objects using the New-Object cmdlet. The following example generates arandom number using the base class libraries; it simulates rolling a single die 1,000 times. Using only 67 characters, a hashtable collects and prints the frequency each side is rolled:

    Looking at each of these commands separately, we can review how they interrelate. First, a range is defined (1-1000).Second, this range is piped into a foreach loop, which creates a hash table with the variable name of $freq. Third, for eachvalue from the hash table, a random number between 1 and 7 is generated. Finally, that value is printed.

    cmdlets in PowerShell

    A cmdlet is a unit of work in PowerShell. Over 100 cmdlets ship With PowerShell. Want to see just how many cmdlets? Usethe system to figure out the system by executing the intuitive Get-Command command.

  • 8/6/2019 Lab49Feature-DrDobbs-WindowsPowershell

    8/16

    The following two tables outline the unique verbs and nouns with which PowerShell is shipped. The contents can beobtained using the following command:

    Get-Command | ForEach { $_.Name.Split("-")[0] } | Sort -Unique

    Syntax in PowerShell

    In PowerShell, the syntax is intuitive and familiar. For instance, variables are designated with a dollar symbol ($). Here aresome typical methods of creating variables.

  • 8/6/2019 Lab49Feature-DrDobbs-WindowsPowershell

    9/16

    Since PowerShell is rooted in .Net, if we set $a = "Hello World", $a is of type System.String. From the command line wehave access to all the familiar methods and properties of a string; this is demonstrated in the following screenshot.

    Another out of the box cmdlet is Get-Member. By piping $a to it, the Get-Member cmdlet reflects over the $a (aSystem.String type) and displays the variables methods and properties as shown below.

  • 8/6/2019 Lab49Feature-DrDobbs-WindowsPowershell

    10/16

    Variables in PowerShell

    In the following example, $v is a PowerShell variable. The dollar sign designates v as a variable; it will store the result ofa simple multiplication operation. Note that the data type of $v is undefined. The variable $v is an object and is basedon.Net. As such, we can invoke methods such as the GetType() method to display the RunTimeType information. Notice $vis of type Int32 and has a base type of ValueType.

    Using the same variable $v, we set it to a string; we print out the type information using the GetType() method.

    Similarly, we can create an array simply by setting the variable to a list of comma-separated values. The GetType() methodshows $v is an array of objects. Later well cast variables to strongly-typed arrays.

    Finally, we can key value pairs in a hash table using the @{} PowerShell syntax. This will be verified again through theGetType() method. PowerShell handles both the display and iteration of the namevalue pairs in the hash table.

    Directories in PowerShell

    To discuss a little housekeeping for PowerShell, it is a good practice is to have two subdirectories: src and lib. The srcdirectory contains the projects created for the managed code; these will be accessed from PowerShell. The lib directory con-

  • 8/6/2019 Lab49Feature-DrDobbs-WindowsPowershell

    11/16

    tains the DLLs; pointing the build area to this directory allows access to PowerShell. Also, add the root directory-wherethe scripts are kept-to your path. That way, when you launch PowerShell, you can type in the name of your command with-out the file extension .ps1 to execute the script.

    Diving Deeper in PowerShell

    Having reviewed some of the fundamentals of PowerShell, its time to dive deeper into some specific examples. Thesewill cover how PowerShell works seamlessly with .Net components, scripts, files, and other applications.

    Example 1: Developing a Simple .Net Class

    In this example, well create a simple .Net class library called Calculator. It contains a single class (Calc) and only onemethod (DoAddition). This method returns the sum of two arguments.

    namespace Calculator{

    public class Calc{

    public int DoAddtion(int var1, int var2){

    return var1 + var2;}

    }

    }

    Once weve created the class, we must compile the code, start PowerShell and change directory to where the DLL is. TheDLL needs to be loaded into the current domain using the static method LoadFrom located in the Reflection.Assemblynamespace. PowerShell has special syntax for loading the DLL-it requires the namespace and class containing the staticmethod to be in braces, two colons, and the name of the static method. The LoadFrom method also needs the path and nameof the DLL. For the path, the $pwd automatic variable is used. The complete syntax is as follows:

    [Reflection.Assembly]::LoadFrom("$pwd\Calculator.DLL")

    If the DLL is found and loads successfully you should see the following:

    Now an instance of the class needs to be created using the New-Object cmdlet. It must be fully qualified with the name-space. Once successfully created, you can call the DoAddition method.

  • 8/6/2019 Lab49Feature-DrDobbs-WindowsPowershell

    12/16

    PowerShells scripting ability is expanded with .Net. Using the range syntax and the ForEach cmdlet, we can useDoAddition to count by twos.

    Note, as mentioned earlier, the $_ PowerShell variable refers to the current object in the pipeline. However, alternate syntaxis available. The following lines of code accomplish the sameOption A:1..5 | ForEach { $calc.DoAddition($_, $_) }

    Option B:1..5 | ForEach { $calc.DoAddition($i, $i) }

    Example 2: Developing Advanced .Net Classes

    In this example, well create another class library and return a custom type. The class library will be called People and willcontain two classes, PeopleHelper and our custom type Person. Person is a simple class; it has three properties: FirstName,LastName and a Guid. All three properties get set in the constructor. The PeopleHelper class has one method (NewPerson)and takes two strings (FirstName and LastName).

    using System;namespace People{

    public class PeopleHelper{

    public Person NewPerson(string firstName, string lastName){

    return new Person(firstName, lastName);}

    }public class Person{

    private string _firstName;private string _lastName;

    private Guid _guid;public Guid Guid{ get { return _guid; } set { _guid = value; } }

    public string LastName{ get { return _lastName; } set { _lastName = value; } }public string FirstName{ get { return _firstName; } set { _firstName = value; } }

    public Person(string firstName, string lastName){

    _firstName = firstName;_lastName = lastName;_guid = Guid.NewGuid();}

    }}

  • 8/6/2019 Lab49Feature-DrDobbs-WindowsPowershell

    13/16

    We create this DLL as we would any other .Net component. In PowerShell we load it into the current application domain,instantiate the class, and call the NewPerson method with parameters.

    To illustrate the functionality, we create an array of first names at the command line. This array is piped in order to create aPerson object for each one.

    If first names are listed in a file (for example, names.txt), we can retrieve the data using the Get-Content cmdlet. Thiscmdlet will read the file, pipe it, and create a Person object for each name.

    In both cases whether the source data is file-based or an array at the command line the results are the same. Our .Netcomponents are used in conjunction with PowerShell in order to create unique identifiers and first-last name combinations.

    Example 3: Creating Scripts

    The previous example illustrated the seamless interaction between PowerShell and .Net DLL. Now well build these up intoconstructs that are reusable. Both a legacy .Net component and the People.DLL will be wrapped in PowerShell constructs so

    they can operate seamlessly in the pipeline. This will demonstrate PowerShells ability to script existing .Net DLLs.

    In effect, this example will enable a transformation of data from one form to another. Starting with a simple array of names,well transform the array to a table of objects. Then, the input will come from an alternative source-a file. Moving along-while using the People.DLL -well filter the list of names (similar to a WHERE clause in SQL). The data-transformationwill be will be complete as the data is exported to a CSV file.

    First, well build a script file with the PowerShell file extension: People-Setup.ps1. The contents of this script file will be theindividual PowerShell commands. In the script well setup two functions, a filter and code to call one of them. The contentsof the file are as follows:

    1. $scriptDefinition = $MyInvocation.MyCommand.Definition

  • 8/6/2019 Lab49Feature-DrDobbs-WindowsPowershell

    14/16

    2. $scriptDir = Split-Path $scriptDefinition3. $libDir = Join-Path $scriptDir "lib"4. $dllName = "People.dll"5. $resolvedDLL = Join-Path $libDir $dllName6. [Reflection.Assembly]::LoadFrom($resolvedDLL)

    In line 1, the $MyInvocation automatic variable is used to determine the source of the script and the location of the DLL libdirectory. This path is then split using the Split-Path cmdlet. Then, it is built up with the lib directory and DLL that is need-ed for the LoadFrom cmdlet in Line 6.

    The function Add-Assembly takes two arguments-a script definition ($MyInvocation.MyCommand.Definition) and the DLLname (People.DLL). The $MyInvocation.MyCommand.Definition command-when used in the script-returns the full name ofthe script location. Using this as a starting point along with two cmdlets (Join-Path and Split- Path) well resolve our PeopleDLL location and load the DLL.

    As the previous example shows, we can create scripts that work with both .Net and PowerShell components. Reaching backto our previous Calculator class, we can see a simple example.

    [reflection.assembly]::loadfrom("$pwd\Calculator.dll") | Out-Null1..10 | % { $calc.DoAddition($_, $_) }1..10 | % { $calc.DoAddition($_, $_*2) }

    1..10 | % { $calc.DoAddition($_, $_*3) }

    This example presents an interesting way of using .Net DLLs. The feedback loop of code, compile, run, and observe isreduced dramatically. More importantly, existing .Net components can be scripted.

    Example 4: Working with Microsoft Excel

    With PowerShell, you have the ability to uniquely handle data in Microsoft Excel. Not only can you retrieve data from aworksheet within a workbook, but you can create custom properties for the created objects using PowerShells wrapperobject: PSObject. In this example, well connect to an Excel workbook, retrieve the data from a specific worksheet, and thenuse PSObject within nested loops to add custom properties.

    In the following code, observe that in the Get-ConnectionString cmdlet, we build a connection string to connect to an Excelworkbook. The specific workbook is passed in as a parameter.

    param($workbook, $sheetName)begin{

    function Get-ConnectionString{

    param ($workbook)"Provider=Microsoft.Jet.OLEDB.4.0;Data

    Source=$workbook;Extended Properties=Excel 8.0;"}

    In the Get-Data function, we retrieve the data from the specified workbook. Moreover, we will be extracting data from a

    specific worksheet within the workbook (as defined by the parameter). By using ADO.NET, we consider the sheet like apseudo-database. As such, we can execute a SQL statement against it and store the output. Note that we suppress the outputby piping to the Out-Null cmdlet.

    function Get-Data{param($workbook, $sheetName)$workbook = Resolve-Path $workbook$cnnString = Get-ConnectionString $workbook$cnn = new-object System.Data.OleDb.OleDbConnection($cnnString)$cnn.open()if(!$sheetName.EndsWith("$")) {$sheetName += "$"}

  • 8/6/2019 Lab49Feature-DrDobbs-WindowsPowershell

    15/16

  • 8/6/2019 Lab49Feature-DrDobbs-WindowsPowershell

    16/16

    ple levels. For example, re-purposing existing services glued together with a script is far quicker and more flexible than onedone in compile code.

    Because of PowerShells strengths, there are signs of good growth-a strong user community has already taken shape;Microsoft is already building version 2.0; a third-party market is also emerging just as it did when Visual Basic emerged.The reason for the excitement is clear: PowerShell is flexible, extensible, and easily integrated.

    (#16992) Reprinted with permission from the February 27, 2008 online edition of Dr. Dobbs Journal. Copyright 2008 United Business Media.

    For more information about reprints from Dr. Dobbs Journal, please contact PARS International Corp. at 212-221-9595.