Introduction to PowerShell

All references to PowerShell version 2.0 downloaded May 2010.

  1. Getting PowerShell installed
    1. What is PowerShell?

      PowerShell is a powerful scripting language from Microsoft.

    2. How do I get it?

      You can download PowerShell 2.0 from here. PowerShell is only officially supported on the Windows platform.

    3. How do I start it?

      Start Menu / Programs / Accessories / Windows PowerShell / Windows PowerShell

      A command window similiar to "cmd" will open and be ready for your input.

  2. Interacting with PowerShell

    At the command prompt you can enter simple commands like,

    PS C:\> 7 * 6 
    42
    

    PowerShell will try to intelliqently decide when you want multiple line entries:

    PS C:\> 7 *
    >> 6
    >>
    42
    

    It will also respect quotes:

    PS C:\> "hello"
    hello
    PS C:\> "hello
    >> there"
    >>
    hello
    there
    PS C:\>
    

    You can force it to expect more input by using the backtick character (`) at the end of the line

    PS C:\> 7`
    >> * 6
    >>
    42
    PS C:\>
    

    The "up" and "down" arrows allow you to scroll through your history and select previous commands, also try "F9".

  3. The magic of Tab

    When you want PowerShell to suggest a completion to your command enter "Tab"

    PS C:>Hel(Tab)
    

    will complete to "help".

  4. You can always Escape

    If you want to start over on a line just hit "ESC"

  5. Comments

    The "#" character starts a comment

    PS C:\> $g = 9.81 #set value for gravity
    
  6. You can use wildcards in commands
    PS C:\> cd p*les
    PS C:\Program Files>
  7. Piping and Redirects

    Using the pipe character, "|" you can redirect the output of one command into the input of another. For example, the "Get-ChildItem" command will return a list of files that you can redirect to "Sort-Object" to get a sorted list.

    PS C:\> Get-ChildItem | Sort-Object -Property LastWriteTime

    Using the ">" character will redirect all the output to a file.

    PS C:\> Get-ChildItem | Sort-Object -Property LastWriteTime > SortedFiles.txt

    Using ">>" will append to a file.

  8. Editing files

    To open a file in your editor give part of the path name

    PS C:\> .\SortedFiles.txt
  9. Storing output in variables

    You can execute a command and store the result in a variable (names start with "$").

    PS C:\> $a = date.exe
    PS C:\> $a
    Tue May  4 10:00:36 CDT 2010
  10. Simple Calculations

    PowerShell does simple math:

    PS C:\> 7*6
    42
    PS C:\> "abc"*4
    abcabcabcabc
    PS C:\> 20mb / 7kb
    2925.71428571429
    PS C:\> 6 * 0x77
    714
    
  11. Executables

    Some executable names can be entered into powershell:

    PS C:\> tracert fincher.org
    
    Tracing route to fincher.org [208.97.191.221]
    over a maximum of 30 hops:
    
      1     1 ms    <1 ms    <1 ms  172.30.78.1
      2     1 ms    <1 ms    <1 ms  192.168.65.26
      3    29 ms    28 ms    44 ms  10.255.240.249
      4    40 ms    40 ms    40 ms  10.255.240.241
    

    Only some can be entered because not all executables are within the default "Path".

    To see what directories are in your path,

    PS C:\> $env:Path
    C:\Program Files\Windows Resource Kits\Tools\;
    

    To add directories,

    PS C:\> $env:path += ";C:\home\mfincher\bin"
    

    The "&" preceeding a string tells powershell to execute the string as a command:

    PS C:\> & "C:\home\mfincher\bin\backup.exe"
    
  12. Saving your current directory location

    Sometimes you need to temporarily change directories. The unix "pushd" and "popd" are availible (aliases for "Push-Location" and "Pop-Location".

    PS C:\> pushd
    PS C:\> cd tmp
    PS C:\tmp> popd
    PS C:\>
    
  13. Cmdlets Cmdlets are real powershell commands. They have the form "verb-noun", like "Get-Date". These are the most common verbs:
    • Add
    • Clear
    • Compare
    • Convert
    • Copy
    • Export
    • Format
    • Get
    • Group
    • Import
    • Measure
    • Move
    • New
    • Out
    • Read
    • Remove
    • Rename
    • Resolve
    • Restart
    • Resume
    • Select
    • Set
    • Sort
    • Split
    • Start
    • Stop
    • Suspend
    • Tee
    • Test
    • Trace
    • Update
    • Write
  14. Help
    1. The "Get-Command" cmdlet

      The command "Get-Command -verb get" will return all the commands with the verb "Get"

      PS C:\> Get-Command -verb  get
      
    2. Get-Command for cmdlet

      This will show all cmdlets

      PS C:\home\mfincher> Get-Command -commandType  cmdlet
      
      Cmdlet Write-Warning Write-Warning [-Message] <String> [-Verbose] [-D...
    3. Help on individual commands

      Use the "Get-Help" command followed by the command. (add "-detailed" for way more info than you need).

      PS C:\> Get-Help Get-Process
      
    4. Wildcards

      You can use a wildcard "*" to expand the results. For example, "Get-Command *" will return all commands (5,426 on my machine, your results will vary).

    5. Parameters

      PowerShell has 3 types of parameters: Named, Switch, and Positional.

      1. Named

        Named parameters start with a "-" followed by the name, a space, and a value. They are like adding named value pairs to your cmdlet.

        Get-ChildItem -path "C:\Program Files"
        
      2. Switch

        Switch parameters turn a feature "on" or "off". They have no value following themselves.

        Get-ChildItem -recurse
        
      3. Positional

        Positional parameters follow a command in certain positions. For example, below "C:\home\mfincher" is the first position and "*.txt" is the second.

        PS C:\home\mfincher> Get-ChildItem "C:\home\mfincher" *.txt
        
            Directory: C:\home\mfincher
        
        Mode                LastWriteTime     Length Name
        ----                -------------     ------ ----
        -a---        11/15/2004   2:22 PM        392 ant.txt
        -a---         11/7/2001   8:18 AM       4059 ascii.txt
        -a---        10/10/2002   2:40 PM      13143 Day.txt
        -a---         1/21/2010   1:50 PM          0 Defrag_2010-01-21-13-50-33.42.txt
        

        The above command is the same as below, which explicitly tells the cmdlet what the parameters are:

        Get-ChildItem -path "C:\home\mfincher" -filter *.txt
        

        If you look for help on the "path" named parameter, it will tell you it has a postion of "1", meaning you can omit the "-path" and PowerShell will assume the first paramter is "path"

        PS C:\home\mfincher> Get-Help Get-ChildItem -parameter path
        
        -Path <string[]>
            Specifies a path to one or more locations. Wildcards are permitted. The default location is the current directory (
            .).
        
            Required?                    false
            Position?                    1
            Default value
            Accept pipeline input?       true (ByValue, ByPropertyName)
            Accept wildcard characters?  false
        

        Parameters themselves can be abbreviated to their shortest, non-ambiguous length.

        Get-ChildItem -pa "C:\home\mfincher" -fil *.txt
        
      4. Common Parameters

        All cmdlets can accept these common parameters: -Verbose, -Debug, -ErrorAction, -ErrorVariable, and -OutVariable. Enter "get-help about_commonparameters" for more details.

      To see parameters use the "-full" parameter:

      PS C:\> Get-Help Get-ChildItem -full

      example:

      PS C:\> get-childitem . -include *.exe -recurse -force
  15. Aliases

    Just as we give our friends and family members nicknames, you can assign a shorthand term for PowerShell commands.

    Since typing "Get-ChildItem" is rather tedious, let's give it an alias of "l".

    PS C:\> Set-Alias l Get-ChildItem
    

    Now, whenever I type "l" PowerShell will list all the files in the current directory.

    To see what an alias represents use the "Get-alias" command. Use with no arguments to get them all.

    PS C:\> Get-Alias -name l
    
    CommandType     Name                                                Definition
    -----------     ----                                                ----------
    Alias           l                                                   Get-ChildItem
    
    

    You can also use $alias: format. $

    PS C:\> $alias:l
    Get-ChildItem
    
  16. Functions

    Functions are more powerful than aliases. You can do multiple lines and pass in arguments. Let's assume you want to see all processes containing "devenv".

    PS C:\> Get-Process | Out-String -Stream | Select-String "devenv"
    
    PS C:\> function proc { Get-Process | Out-String -Stream | Select-String "devenv" }
    

    Produces:

    PS C:\> proc
    
        713      30    51768      85420   285     4.42    532 devenv
       1538      56   193080     207940   643    20.95   4884 devenv
    

    You can use "$args" in a function definition to pass in arguments making it more flexible

    PS C:\> function proc { Get-Process | Out-String -Stream | Select-String $args }
    PS C:\> proc emacs
    
         96       4    18668      20220   300   855.55    352 emacs
    
    
  17. Creating PowerShell scripts

    PowerShell scripts have the extension "ps1". Let's create one called "gd.ps1" and enter the following command into it. This should be in a directory that is in your PATH variable.

    Get-Date
    

    Let's run it.

    PS C:\> gd
    File C:\home\mfincher\bin\gd.ps1 cannot be loaded because the execution of scripts is disabled on this system. Please s
    ee "get-help about_signing" for more details.
    At line:1 char:3
    + gd <<<<
        + CategoryInfo          : NotSpecified: (:) [], PSSecurityException
        + FullyQualifiedErrorId : RuntimeException
    

    Hmm.. We need to add permission to have a local PowerShell script run.

    Set-ExecutionPolicy RemoteSigned
    

    Now, it runs and shows the date

    PS C:\> gd
    
    Friday, June 18, 2010 2:21:13 PM
    
  18. Command Hierarchy

    PowerShell searches the following in order when interpreting a command: Alias, Function, Cmdlet, Application, Script, Files.

  19. Virtual Drives

    A virtual drive is a datastore that is treated as a real drive with a tree structure of items. Some examples are "env", "Function", "C", "Alias", and "HKCU". The contents of virtual drives can be listing by using "dir", "ls", or "Get-ChildItem". "Get-PSProvider" will show all PSProviders and their virtual drives.

    PS C:\> get-PSProvider
    
    Name                 Capabilities                                      Drives
    ----                 ------------                                      ------
    WSMan                Credentials                                       {WSMan}
    Alias                ShouldProcess                                     {Alias}
    Environment          ShouldProcess                                     {Env}
    FileSystem           Filter, ShouldProcess                             {C, D, M}
    Function             ShouldProcess                                     {Function}
    Registry             ShouldProcess, Transactions                       {HKLM, HKCU}
    Variable             ShouldProcess                                     {Variable}
    Certificate          ShouldProcess                                     {cert}
    
  20. Variables
    1. Basics

      Varibles names start with "$" and contain letters, numbers, or the underscore "_" and are case-insensitive. Variables can contain simple objects like strings and integers, or complex objects.

      PS C:\> $name = "Inigo Montoya"
      PS C:\> $secs = 6
      PS C:\> "My name is $name, you killed my father, prepare to die in $secs seconds"
      My name is Inigo Montoya, you killed my father, prepare to die in 6 seconds
      

      If you must have strange characters in a variable name, enclose the name in curly braces

      PS C:\> ${my variable with wierd $%^ characters} = "Howdy"
      PS C:\> ${my variable with wierd $%^ characters}
      Howdy
      

      or complex objects

      PS C:\> $myfiles = Get-ChildItem
      PS C:\> $myfiles
      
      
          Directory: C:\
      
      
      Mode                LastWriteTime     Length Name
      ----                -------------     ------ ----
      d----         8/10/2009  11:09 AM            8ac45b2e935881d6d92e68
      d----        11/21/2003  10:00 AM            alphablox
      d----         8/11/2008   3:14 PM            Cheops3
      d----          6/1/2007   4:13 PM            dell
      d----         9/25/2009   4:54 AM            Documents and Settings
      d----         2/19/2007   2:56 PM            drivers
      d----         7/16/2009   3:55 PM            e-tabs
      d----         2/20/2006   7:08 PM            ed
      d----         10/9/2009   3:13 PM            home
      
    2. Multiple variables can be set at the same time.
      PS C:\> $a = $b = $c = 0
      
    3. Multiple variables can be set on one line
      PS C:\> $one,$two,$three = 1,2,3
      
    4. Swapping values

      Using the comma syntax below you can swap the contents of two variables

      PS C:\> $var1 = 1; $var2 = 2;
      PS C:\> $var1, $var2 = $var2, $var1
      PS C:\> $var1
      2
      
    5. Directory of Variables

      PowerShell remembers all your variables in the "variable" virtual drive. More on these below. You can get a list of variables using "dir variable:". (I've removed some of them).

      PS C:\> dir variable:
      
      Name                           Value
      ----                           -----
      a                              0
      b                              0
      c                              0
      myfiles                        {8ac45b2e935881d6d92e68, alphablox, Cheops3, dell...}
      name                           Inigo Montoya
      one                            1
      secs                           6
      three                          3
      two                            2
      var1                           2
      var2                           1
      
    6. How to test if a directory already exists

      Use "Test-Path" which will return a boolean

      if(Test-Path C:\inetpub\wwwroot) {
      ...
      }
      
    7. Does a variable exist?

      Use the Test-Path cmdlet with the "variable" virtual drive.

      PS C:\> Test-Path variable:one
      True
      PS C:\> Test-Path variable:four
      False
      
    8. Variable Meta-data

      Using "New-Variable" you can set metadata associated with a variable.

      PS C:\> New-Variable life -value 42 -Description "Meaning of life, the universe and everything."
      

      To see the description you can use "Format-Table"

      PS C:\> dir variable:\life | Format-Table Name, Value, Description -autosize
      
      Name Value Description
      ---- ----- -----------
      life    42 Meaning of life, the universe and everything.
      
    9. Readonly

      You can set a variable to be readonly. Let's delete our old variable first.

      PS C:\> del variable:\life
      PS C:\> New-Variable life -value 42 -option ReadOnly
      PS C:\> $life
      42
      PS C:\> $life = 43
      Cannot overwrite variable life because it is read-only or constant.
      At line:1 char:6
      + $life <<<<  = 43
          + CategoryInfo          : WriteError: (life:String) [], SessionStateUnauthorizedAccessException
          + FullyQualifiedErrorId : VariableNotWritable
      
      
    10. Deleting Variables

      To delete we use "-force"

      PS C:\> del variable:\life -force
      
    11. Constants

      For variables that really are constants we can use the "Constant" option.

      PS C:\> New-Variable gravity -value 9.81 -option Constant
      PS C:\> del variable:\gravity -force
      Remove-Item : Cannot remove variable gravity because it is constant or read-only. If the variable is read-only, try the
       operation again specifying the Force option.
      At line:1 char:4
      + del <<<<  variable:\gravity -force
          + CategoryInfo          : WriteError: (gravity:String) [Remove-Item], SessionStateUnauthorizedAccessException
          + FullyQualifiedErrorId : VariableNotRemovable,Microsoft.PowerShell.Commands.RemoveItemCommand
      
    12. System Variables

      PowerShell uses internal variables some of which are shown below:

      PS C:\> dir variable: | Sort-Object Name | Format-Table Name, Description -autosize
      
      Name                          Description
      ----                          -----------
      $
      ?                             Execution status of last command.
      ^
      _
      a
      amount
      args
      b
      c
      ConfirmPreference             Dictates when confirmation should be requested. Confirmation is requested when the Con...
      ConsoleFileName               Name of the current console file.
      DebugPreference               Dictates action taken when an Debug message is delivered.
      Error
      ErrorActionPreference         Dictates action taken when an Error message is delivered.
      ErrorView                     Dictates the view mode to use when displaying errors.
      ExecutionContext              The execution objects available to cmdlets.
      
    13. Environmental Variables

      The virtual drive "$env:" contains the environmental variables.

      PS C:\> $env:PATH
      C:\Program Files\Windows Resource Kits\Tools\;c:\program files\imagemagick-6.3.6-q16;C:\WINDOWS\SYSTEM32;C:\WINDOWS;C:\
      WINDOWS\SYSTEM32\WBEM;C:\MINGPATH;C:\E-TABS\BIN;C:\PROGRAM FILES\ATI TECHNOLOGIES\ATI CONTROL PANEL;c:\mingspec;C:\Prog
      
    14. Operations on Environmental Variables

      These only affect your processes local copy, not the system's values

      PS C:\> $env:myNewEnvVar = 12   #create a new environmental variable
      PS C:\> del env:\CLASSPATH      #deletes the environmental variable
      PS C:\> $env:TMP = "C:\NewTemp" #replace the contents of an environmental variable
      PS C:\> $env:PATH += ";C:\newBinDir"  # append to variable
      
  21. Encoding

    PowerShell by default uses Unicode. So when you do something like this it will write in Unicode

    PS C:\> get-date >> t1.txt
    

    Produces:

    Monday, June 21, 2010 2:52:25 PM
    
    but if you are using an older text editor you may see this:

    Produces:

    ^M^@
    ^@M^@o^@n^@d^@a^@y^@,^@ ^@J^@u^@n^@e^@ ^@2^@1^@,^@ ^@2^@0^@1^@0^@ ^@2^@:^@5^@2^@:^@2^@5^@ ^@P^@M^@^M^@
    ^@
    

    To pipe output from a program into a file

    PS C:\> get-date | Out-File c:\t1.txt
    

    Using and Encoding option will let you write in something other than Unicode.

    PS C:\> get-date | Out-File -Encoding UTF8 c:\t1.txt
    
  22. To view the contents of a file

    Either of these will work:

    PS C:\> cat "C:\defrag.txt"
    PS C:\> ${c:\defrag.txt}
    
  23. PS C:\> echo "testme" > "$env:TEMP\temp.tmp"
    PS C:\> cat "$env:TEMO\temp.tmp"
    Get-Content : Cannot find path 'C:\temp.tmp' because it does not
    At line:1 char:4
    + cat <<<<  "$env:TEMO\temp.tmp"
        + CategoryInfo          : ObjectNotFound: (C:\temp.tmp:Strin
        + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.
    
    PS C:\> cat C:\temp.tmp
    Get-Content : Cannot find path 'C:\temp.tmp' because it does not
    At line:1 char:4
    + cat <<<<  C:\temp.tmp
        + CategoryInfo          : ObjectNotFound: (C:\temp.tmp:Strin
        + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.
    
    PS C:\> cat "C:\temp.tmp"
    Get-Content : Cannot find path 'C:\temp.tmp' because it does not
    At line:1 char:4
    + cat <<<<  "C:\temp.tmp"
        + CategoryInfo          : ObjectNotFound: (C:\temp.tmp:Strin
        + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.
    
    PS C:\> echo "$env:TEMP"
    c:\windows\temp
    PS C:\> $mycommand = 'echo "testme" > "$env:TEMP\temp.tmp"'
    PS C:\> Invoke-Expression $mycommand
    PS C:\> cat "C:\windows\temp\temp.tmp"
    testme
    PS C:\>
    
  24. To see code behind a function

    Enter the name of the function and PowerShell will return the code

    PS C:\> $function:prompt
    $(if (test-path variable:/PSDebugContext) { '[DBG]: ' } else { '' }) + 'PS ' + $(Get-Location) + $(if ($nestedpromptlev
    el -ge 1) { '>>' }) + '> '
    
  25. Variable Scope

    Variables and functions in PowerShell have a scope in which they are accessible. PowerShell has four scopes (from "Get-Help scope"):

        Global:
            The scope that is in effect when Windows PowerShell
            starts. Variables and functions that are present when
            Windows PowerShell starts have been created in the
            global scope. This includes automatic variables and
            preference variables. This also includes the variables, aliases,
            and functions that are in your Windows PowerShell
            profiles.
    
        Local:
            The current scope. The local scope can be the global
            scope or any other scope.
    
        Script:
            The scope that is created while a script file runs. Only
            the commands in the script run in the script scope. To
            the commands in a script, the script scope is the local
            scope.
    
        Private:
            Items in private scope cannot be seen outside of the current
            scope. You can use private scope to create a private version
            of an item with the same name in another scope.
    
    
        Numbered Scopes:
            You can refer to scopes by name or by a number that
            describes the relative position of one scope to another.
            Scope 0 represents the current, or local, scope. Scope 1
            indicates the immediate parent scope. Scope 2 indicates the
            parent of the parent scope, and so on. Numbered scopes
            are useful if you have created many recursive
            scopes.
    

    You can modify the scope of a variable or function by prefacing its name with the scope, $global:rate, $local:cost.

    variables inside scripts by default have a local scope. After they run the outer environment is unchanged.

    test.ps1:
    $song = "Hero"
    
    PS C:\home\mfincher> $song = "Mirror, Mirror"
    PS C:\home\mfincher> .\test.ps1
    PS C:\home\mfincher> $song
    

    Now if we change our tiny script we get the following:

    test.ps1:
    $global:song = "Hero"
    
    PS C:\home\mfincher> .\test.ps1
    PS C:\home\mfincher> $song
    Hero
    
  26. Types PowerShell is a weakly typed language, it tries to assign a type to a variable based on usage. To see the type use ".Get-Type().Name"
    $song.GetType().Name
    String
    PS C:\home\mfincher> (12).GetType().Name
    Int32
    PS C:\home\mfincher> (12.6).GetType().Name
    Double
    

    You can specify a date by prepending the variable with "[" type "]" as shown below. This allows you to access member methods.

    PS C:\home\mfincher> $date = "January 1, 2012"
    PS C:\home\mfincher> $date.GetType().Name
    String
    PS C:\home\mfincher> [datetime]$realdate = "Janaury 1, 2010"
    PS C:\home\mfincher> $realdate.DayOfWeek
    Friday
    

    Common Types: array, bool, byte, char, datetime, decimal, double, guid, hashtable, int16, int32, int64, nullable, psobject, regex, regex, sbyte, single, string, switch, timespan, type, uint16, uint32, uint64, xml

    Declaring a variable to be XML datatype brings many advantages

    PS C:\home\mfincher> [xml]$periodic = "<atoms>" +
    >>   "<atom name='actinium' atomic_number='89'></atom>" +
    >>   "<atom name='aluminum' atomic_number='13'></atom>" +
    >> "</atoms>"
    >>
    PS C:\home\mfincher> $periodic.atoms
    
    atom
    ----
    {actinium, aluminum}
    
    PS C:\home\mfincher> $periodic.atoms.atom
    
    name                                                        atomic_number
    ----                                                        -------------
    actinium                                                    89
    aluminum                                                    13
    
    PS C:\home\mfincher> $periodic.atoms.atom[0]
    
    name                                                        atomic_number
    ----                                                        -------------
    actinium                                                    89
    
    PS C:\home\mfincher> $periodic.atoms.atom[0].atomic_number
    89
    
  27. PSVariables

    When you create a variable, PowerShell creates a backend object to store information about the variable - it's value is only the tip of the iceberg. You can get at the real variable object by using "Get-Variable".

    PS C:\home\mfincher> $psvar = Get-Variable periodic
    PS C:\home\mfincher> $psvar | Format-List
    
    
    Name        : periodic
    Description :
    Value       : #document
    Visibility  : Public
    Module      :
    ModuleName  :
    Options     : None
    Attributes  : {System.Management.Automation.ArgumentTypeConverterAttribute}
    
    
    You can even change properties of the variable by modifying its PSVariable.
    PS C:\home\mfincher> $psvar.Description = "Periodic table, well the first two elements"
    PS C:\home\mfincher> $psvar | Format-List
    
    
    Name        : periodic
    Description : Periodic table, well the first two elements
    Value       : #document
    Visibility  : Public
    Module      :
    ModuleName  :
    Options     : None
    Attributes  : {System.Management.Automation.ArgumentTypeConverterAttribute}
    
    

    You can also set its "Options" to "None", "ReadOnly", "Constant", "Private", or "AllScope":

    PS C:\home\mfincher> $psvar.Options
    None
    PS C:\home\mfincher> $psvar.Options = "Private"
    
  28. Validating Variables

    An interesting feature of PowerShell is variable validation. You can set a variable to have a range of length, match a regular expression, be between a range of values, or be in a set of values. Below is a simple example of using regular expressions.

    $phonenum = "622-333-3444"
    $varObject = Get-Variable phonenum
    $pattern = "[0-9]{3}-[0-9]{3}-[0-9]{4}"
    $varObject.Attributes.Add($(New-Object System.Management.Automation.ValidatePatternAttribute -argumentList $pattern))
    $phonenum = "444-332-3433"
    $phonenum = "AR4-332-3433"   #bad
    
    
  29. Arrays
    1. Basics

      PowerShell commands return arrays when more than one object is returned.

      PS C:\home\mfincher> $myfiles = dir c:\
      PS C:\home\mfincher> $myfiles
      
      
          Directory: C:\
      
      
      Mode                LastWriteTime     Length Name
      ----                -------------     ------ ----
      d----         8/10/2009  11:09 AM            8ac45b2e935881d6d92e68
      d----        11/21/2003  10:00 AM            alphablox
      d----         8/11/2008   3:14 PM            Cheops3
      d----          6/1/2007   4:13 PM            dell
      d----         9/25/2009   4:54 AM            Documents and Settings
      ...
      
      PS C:\home\mfincher> $myfiles.Count
      67
      PS C:\home\mfincher> $myfiles -is [Array]
      True
      

      You can access an individal element with [num].

      PS C:\home\mfincher> $myfiles[3]
      
      
          Directory: C:\
      
      
      Mode                LastWriteTime     Length Name
      ----                -------------     ------ ----
      d----          6/1/2007   4:13 PM            dell
      
    2. PowerShell almost always return an array

      PowerShell will return a single object if only one object is returned. This could be a little confusing to your programs because it returns arrays sometimes and single objects at other times. For example above "dir c:" returned an array, but below it returns a single object.

      PS C:\home\mfincher> $myfiles = dir c:\del*
      PS C:\home\mfincher> $myfiles.Count
      PS C:\home\mfincher> $myfiles
      
      
          Directory: C:\
      
      
      Mode                LastWriteTime     Length Name
      ----                -------------     ------ ----
      d----          6/1/2007   4:13 PM            dell
      
      
      PS C:\home\mfincher> $myfiles -is [Array]
      False
      

      To force a command to return an array use @().

      PS C:\home\mfincher> $myfiles = @(dir c:\del*)
      PS C:\home\mfincher> $myfiles -is [Array]
      True
      PS C:\home\mfincher> $myfiles.Count
      1
      
    3. Piping

      The "|" character will pipe the contents of one command to another. With each line being its own object, you can search for a particular string in the output like this to find all files modified in 2009 (well, and all files that contain "/2009" in their name too).

      PS C:\home\mfincher> $myfiles = dir c:\
      PS C:\home\mfincher> $myfiles | Select-String "/2009"
      
      C:\SortedFiles.txt:38:d----         2/12/2009   3:13 PM            switchboard
      C:\SortedFiles.txt:39:-a---         4/10/2009  10:14 AM        422 Shortcut to installs.lnk
      C:\SortedFiles.txt:40:d----         5/11/2009   1:30 PM            TEMP
      C:\SortedFiles.txt:41:d----         7/16/2009   3:26 PM            tmpsd
      C:\SortedFiles.txt:42:d----         7/16/2009   3:55 PM            e-tabs
      
      
    4. Piping objects

      While traditional shells like 'sh', 'csh', and bash process raw text, PowerShell processes objects. This is very cool.

      PS C:\home\mfincher> $jobs = ps
      PS C:\home\mfincher> $jobs
      
      Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
      -------  ------    -----      ----- -----   ------     -- -----------
          294      10     6364      14656    68     0.75   5516 AdobeARM
          108       5     1512       5740    33     0.06   2196 alg
          258       4     1832        300    46    10.80   6040 ALMon
          162       4     1756       1872    37    15.59   3040 ALsvc
      ...
      
      PS C:\home\mfincher> $jobs[1]
      
      Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
      -------  ------    -----      ----- -----   ------     -- -----------
          108       5     1512       5740    33     0.06   2196 alg
      
      
      PS C:\home\mfincher> $jobs[1] | Format-List *
      
      
      __NounName                 : Process
      Name                       : alg
      Handles                    : 108
      VM                         : 34553856
      WS                         : 5877760
      PM                         : 1548288
      NPM                        : 5448
      Path                       : C:\WINDOWS\System32\alg.exe
      Company                    : Microsoft Corporation
      ...                  :
      
      
    5. How to create an array

      PS C:\home\mfincher> $one2five = 1,2,3,4,5
      PS C:\home\mfincher> $one2five
      1
      2
      3
      4
      5
      PS C:\home\mfincher> $one2file = 1..5
      PS C:\home\mfincher> $one2five
      1
      2
      3
      4
      5
      

      Arrays can contain objects of different types

      PS C:\home\mfincher> $mydate = "January 1, 2012", 1, 1, 2012
      PS C:\home\mfincher> $mydate
      January 1, 2012
      1
      1
      2012
      

      How to create an array of length 1 or empty

      PS C:\home\mfincher> $one = @(1)
      PS C:\home\mfincher> $one.Length
      1
      PS C:\home\mfincher> $one -is [Array]
      True
      PS C:\home\mfincher> $empty = @()
      PS C:\home\mfincher> $empty.Length
      0
      
    6. Accessing the last element of an array

      Like Ruby, PowerShell lets you access the last element by using a negative index

      PS C:\home\mfincher> $colors = "red","green","blue"
      PS C:\home\mfincher> $colors[-1]
      blue
      PS C:\home\mfincher> $colors[-2]
      green
      PS C:\home\mfincher> $colors[0]
      red
      PS C:\home\mfincher>
      

      If you go to far negative, nothing is returned

      PS C:\home\mfincher> $colors[-5]
      PS C:\home\mfincher>
      
    7. Access multiple elements

      Simply by using a comma separated list you can create a subset of an existing array.

      PS C:\home\mfincher> $colors[1,2]
      green
      blue
      
    8. Reverse elements

      PS C:\home\mfincher> $colors[2..0]
      blue
      green
      red
      
    9. Adding elements

      The "+=" operator creates a new array with one more element and copies the old contents to the new array

      PS C:\home\mfincher> $colors += "yellow"
      PS C:\home\mfincher> $colors
      red
      green
      blue
      yellow
      
    10. Hashtables

      Hashtables are pretty much what you'd expect. You can access an element either with brackets, var["key"], or with dot notation, var.key. The brackets has to have the double quotes, the dot notation does not.

      PS C:\home\mfincher> $capitals = @{Alabama = "Montgomery"; Alaska = "Juneau"; Arizona = "Phoenix"}
      PS C:\home\mfincher> $capitals
      
      Name                           Value
      ----                           -----
      Alaska                         Juneau
      Arizona                        Phoenix
      Alabama                        Montgomery
      
      
      PS C:\home\mfincher> $capitals["Alaska"]
      Juneau
      PS C:\home\mfincher> $capitals.Alaska #using dot notation
      Juneau
      PS C:\home\mfincher> $capitals.keys
      Alaska
      Arizona
      Alabama
      PS C:\home\mfincher> $southern = "Alabama"
      PS C:\home\mfincher> $capitals.$southern
      Montgomery
      

      You can add hashtable elements with either bracket or dot notation:

      PS C:\home\mfincher> $capitals["Arkansas"] = "Little Rock"
      PS C:\home\mfincher> $capitals.Arkansas = "Little Rock"
      

      "Remove" removes the hashtable entry

      PS C:\home\mfincher> $capitals."Puerto Rico" = "San Juan"
      PS C:\home\mfincher> $capitals
      
      Name                           Value
      ----                           -----
      Puerto Rico                    San Juan
      Alaska                         Juneau
      Arkansas                       Little Rock
      Arizona                        Phoenix
      Alabama                        Montgomery
      
      
      PS C:\home\mfincher> $capitals.Remove("Puerto Rico")
      PS C:\home\mfincher> $capitals
      
      Name                           Value
      ----                           -----
      Alaska                         Juneau
      Arkansas                       Little Rock
      Arizona                        Phoenix
      Alabama                        Montgomery
      
      
      
    11. Copying Arrays

      An array variable really only contains a pointer to the real array object. When you assign one array to another you are merely copying the pointer to the array, not the contents of the array. Use the "Clone()" method to create a copy.

      PS C:\home\mfincher> $colors2 = $colors
      PS C:\home\mfincher> $colors2
      red
      green
      blue
      yellow
      PS C:\home\mfincher> $colors[0] = "pink"
      PS C:\home\mfincher> $colors2
      pink
      green
      blue
      yellow
      PS C:\home\mfincher> $colors2 = $colors.Clone() # this creates a new array
      
    12. Type Safe Arrays

      Although the default is to have non-homogeneous arrays, you can specify that an array can only have one type. If you try to add something that cannot be coerced into the specified type, an error is thrown.

      PS C:\home\mfincher> [int[]]$years = 2009,2010,2011
      PS C:\home\mfincher> $years += twentytwelve
      The term 'twentytwelve' is not recognized as the name of a cmdlet, function, script file, or operable program. Check th
      e spelling of the name, or if a path was included, verify that the path is correct and try again.
      At line:1 char:23
      + $years += twentytwelve <<<<
          + CategoryInfo          : ObjectNotFound: (twentytwelve:String) [], CommandNotFoundException
          + FullyQualifiedErrorId : CommandNotFoundException
      
  30. Misc
    1. Print a line to the console

      Use "write-host" to print a string to the console. Also see "write-debug", and "write-error".

      Write-host "Hello World!"
      
    2. Read a string from the user
      $selection = Read-Host "Please enter the number"
      
    3. Use powershell commands straight from the console.

      This writes the working directory to a file.

      powershell -C pwd > c:\t1
      
    4. Embed the date in a filename

      This pipes the output of "mycommand" to the Tee-Object and then to a log file with the date in the name.

      $filename = "MyImportLog-{0:yyyy-MM-dd}.txt" -f (Get-Date)
      mycommand | Tee-Object -file $filename
      
    5. For Loop

      for ($i=1; $i -le 5; $i++)
      {
         Write-host $i
      }
      
      
    6. How to wait, or sleep

      You can specify "-s" for seconds or "-m" for milliseconds.

         Start-Sleep -s 1
      
    7. How to add quotes in a string

      The escape character is the backtick '`', so preface a double quote within double quotes to have PowerShell insert a literal double quote.

      $db = "MyDatabase"
      $DatabaseServer = "Venus"
      Write-Host "On server `"$DatabaseServer`", upgrading database `"$db`" from version 1.0 to 1.1"
      

      The backtick also works to insert a single quote inside single quotes, 'It`'s too early in the morning to kill princes.'

  31. Passing in parameters to Powershell

    PowerShell has a very good concept of parameters. These will be passed directly to variables with those names.

    Param(
      [Parameter(Mandatory=$True,Position=1)][string]$DatabaseServer, 
      [Parameter(Mandatory=$False,Position=2)][switch]$live
      )
    Write-Host "On dbserver `"$DatabaseServer`", upgrading database `"$db`" from version 1.0 to 1.1"
    

    Whatever is passed in after "-DatabaseServer" will automatically be put in the variable $DatabaseServer. Since it is marked as Mandatory, if it's not passed in, Powershell will ask the user for a value. The boolean variable $live will be set to true if the user adds "-live" on the command line, otherwise it's false.

  32. How to make a read-only file writable

    Set-ItemProperty MyFile.txt -name IsReadOnly -value $false
    
  33. How to invoke scripts on other computers

    invoke-command -computername mars,jupiter,venus -scriptblock {
    
  34. How to find the version of Powershell

    $PSVersionTable
    
Go to Home page. Kindly report errors, typos, or misspellings here.