PowerShell

Topics related to PowerShell:

Getting started with PowerShell

Loops

Foreach

There are multiple ways to run a foreach-loop in PowerShell and they all bring their own advantages and disadvantages:

SolutionAdvantagesDisadvantages
Foreach statementFastest. Works best with static collections (stored in a variable).No pipeline input or output
ForEach() MethodSame scriptblock syntax as Foreach-Object, but faster. Works best with static collections (stored in a variable). Supports pipeline output.No support for pipeline input. Requires PowerShell 4.0 or greater
Foreach-Object (cmdlet)Supports pipeline input and output. Supports begin and end-scriptblocks for initialization and closing of connections etc. Most flexible solution.Slowest

Performance

$foreach = Measure-Command { foreach ($i in (1..1000000)) { $i * $i } }
$foreachmethod = Measure-Command { (1..1000000).ForEach{ $_ * $_ } }
$foreachobject = Measure-Command { (1..1000000) | ForEach-Object { $_ * $_ } }

"Foreach: $($foreach.TotalSeconds)"
"Foreach method: $($foreachmethod.TotalSeconds)"
"ForEach-Object: $($foreachobject.TotalSeconds)"

Example output:

Foreach: 1.9039875
Foreach method: 4.7559563
ForEach-Object: 10.7543821

While Foreach-Object is the slowest, it's pipeline-support might be useful as it lets you process items as they arrive (while reading a file, receiving data etc.). This can be very useful when working with big data and low memory as you don't need to load all the data to memory before processing.

Operators

Using ShouldProcess

$PSCmdlet.ShouldProcess() will also automatically write a message to the verbose output.

PS> Invoke-MyCmdlet -Verbose
VERBOSE: Performing the operation "Invoke-MyCmdlet" on target "Target of action"

PowerShell Classes

Switch statement

This topic is documenting the switch statement used for branching the flow of the script. Do not confuse it with switch parameters which are used in functions as boolean flags.

Working with Objects

Using existing static classes

Basic Set Operations

PowerShell Functions

Sending Email

Handling Secrets and Credentials

Powershell Remoting

PowerShell "Streams"; Debug, Verbose, Warning, Error, Output and Information

Variables in PowerShell

Communicating with RESTful APIs

Working with the PowerShell pipeline

PowerShell Background Jobs

PowerShell Jobs run in a new process. This has pros and cons which are related.

Pros:

  1. The job runs in a clean process, including environment.
  2. The job can run asynchronously to your main PowerShell process

Cons:

  1. Process environment changes will not be present in the job.
  2. Parameters pass to and returned results are serialized.
    • This means if you change a parameter object while the job is running it will not be reflected in the job.
    • This also means if an object cannot be serialized you cannot pass or return it (although PowerShell may Copy any parameters and pass/return a PSObject.)

Return behavior in PowerShell

You can read more about the return semantics on the about_Return page on TechNet, or by invoking get-help return from a PowerShell prompt.


Notable Q&A question(s) with more examples/explanation:


about_return on MSDN explains it succinctly:

The Return keyword exits a function, script, or script block. It can be used to exit a scope at a specific point, to return a value, or to indicate that the end of the scope has been reached.

Users who are familiar with languages like C or C# might want to use the Return keyword to make the logic of leaving a scope explicit.

In Windows PowerShell, the results of each statement are returned as output, even without a statement that contains the Return keyword. Languages like C or C# return only the value or values that are specified by the Return keyword.

Working with XML Files

Introduction to Psake

psake is a build automation tool written in PowerShell, and is inspired by Rake (Ruby make) and Bake (Boo make). It is used to create builds using dependency pattern. Documentation available here

Using the progress bar

Strings

Strings are objects representing text.

TCP Communication with PowerShell

SharePoint Module

Aliases

Powershell naming system has quite strict rules of naming cmdlets (Verb-Noun template; see [topic not yet created] for more information). But it is not really convenient to write Get-ChildItems every time you want to list files in directory interactively.
Therefore Powershell enables using shortcuts - aliases - instead of cmdlet names.

You can write ls, dir or gci instead of Get-ChildItem and get the same result. Alias is equivalent to its cmdlet.

Some of the common aliases are:

aliascmdlet
%, foreachFor-EachObject
?, whereWhere-Object
cat, gc, typeGet-Content
cd, chdir, slSet-Location
cls, clearClear-Host
cp, copy, cpiCopy-Item
dir/ls/gciGet-ChildItem
echo, writeWrite-Output
flFormat-List
ftFormat-Table
fwFormat-Wide
gc, pwdGet-Location
gmGet-Member
iexInvoke-Expression
iiInvoke-Item
mv, moveMove-Item
rm, rmdir, del, erase, rd, riRemove-Item
sleepStart-Sleep
start, sapsStart-Process

In the table above, you can see how aliases enabled simulating commands known from other environments (cmd, bash), hence increased discoverability.

Automatic Variables

Environment Variables

Powershell profiles

Profile file is a powershell script that will run while the powershell console is starting. This way we can have our environment prepared for us each time we start new powershell session.

Typical things we want to do on powershell start are:

  • importing modules we use often (ActiveDirectory, Exchange, some specific DLL)
  • logging
  • changing the prompt
  • diagnostics

There are several profile files and locations that have different uses and also hierarchy of start-up order:

HostUserPathStart orderVariable
AllAll%WINDIR%\System32\WindowsPowerShell\v1.0\profile.ps11$profile.AllUsersAllHosts
AllCurrent%USERPROFILE%\Documents\WindowsPowerShell\profile.ps13$profile.CurrentUserAllHosts
ConsoleAll%WINDIR%\System32\WindowsPowerShell\v1.0\Microsoft.PowerShell_profile.ps12$profile.AllUsersCurrentHost
ConsoleCurrent%USERPROFILE%\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps14$profile.CurrentUserCurrentHost
ISEAll%WINDIR%\System32\WindowsPowerShell\v1.0\Microsoft.PowerShellISE_profile.ps12$profile.AllUsersCurrentHost
ISECurrent%USERPROFILE%\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps14$profile.CurrentUserCurrentHost

Enforcing script prerequisites

Using the Help System

Splatting

Note: The Array expression operator or @() have very different behavior than the Splatting operator @.

Read more at about_Splatting @ TechNet

Desired State Configuration

Signing Scripts

Signing a script will make your scripts comply with all exeuction policies in PowerShell and ensure the integrity of a script. Signed scripts will fail to run if they have been modified after being signed.

Scripts signing requires a code signing certificate. Recommendations:

  • Personal scripts/testing (not shared): Certificate from trusted certifiate authority (internal or third-party) OR a self-signed certificate.
  • Shared inside organization: Certificate from trusted certifiate authority (internal or third-party)
  • Shared outside organization: Certificate from trusted third party certifiate authority

Read more at about_Signing @ TechNet

Execution policies

PowerShell has configurable execution policies that control which conditions are required for a script or configuration to be executed. An excecution policy can be set for multiple scopes; computer, current user and current process. Execution policies can easily be bypassed and is not designed to restrict users, but rather protect them from violating signing policies unintentionally.

The available policies are:

SettingDescription
RestrictedNo scripts allowed
AllSignedAll scripts need to be signed
RemoteSignedAll local scripts allowed; only signed remote scripts
UnrestrictedNo requirements. All scripts allowed, but will warn before running scripts downloaded from the internet
BypassAll scripts are allowed and no warnings are displayed
UndefinedRemove the current execution policy for the current scope. Uses the parent policy. If all policies are undefined, restricted will be used.

You can modify the current execution policies using Set-ExecutionPolicy-cmdlet, Group Policy or the -ExecutionPolicy parameter when launching a powershell.exe process.

Read more at about_Execution_Policies @ TechNet

Security and Cryptography

CSV parsing

Introduction to Pester

Modules, Scripts and Functions

PowerShell.exe Command-Line

Common parameters

Common parameters can be used with any cmdlet (that means as soon as you mark your function as cmdlet [see CmdletBinding()], you get all of these parameters for free).

Here is the list of all common parameters (alias is in parenthesis after corresponding parameter):

-Debug (db)
-ErrorAction (ea)
-ErrorVariable (ev)
-InformationAction (ia) # introduced in v5
-InformationVariable (iv) # introduced in v5
-OutVariable (ov)
-OutBuffer (ob)
-PipelineVariable (pv)
-Verbose (vb) 
-WarningAction (wa)
-WarningVariable (wv)
-WhatIf (wi)
-Confirm (cf)

Parameter sets

Regular Expressions

PowerShell Dynamic Parameters

WMI and CIM

CIM vs WMI

As of PowerShell 3.0, there are two ways to work with management classes in PowerShell, WMI and CIM. PowerShell 1.0 and 2.0 only supported the WMI-module which is now superseeded by the new and improved CIM-module. In a later release of PowerShell, the WMI-cmdlets will be removed.

Comparison of CIM and WMI-modules:

CIM-cmdletWMI-cmdletWhat it does
Get-CimInstanceGet-WmiObjectGets CIM/WMI-objects for a class
Invoke-CimMethodInvoke-WmiMethodInvokes a CIM/WMI-class method
Register-CimIndicationEventRegister-WmiEventRegisters event for a CIM/WMI-class
Remove-CimInstanceRemove-WmiObjectRemove CIM/WMI-object
Set-CimInstanceSet-WmiInstanceUpdates/Saves CIM/WMI-object
Get-CimAssociatedInstanceN/AGet associated instances (linked object/classes)
Get-CimClassGet-WmiObject -ListList CIM/WMI-classes
New-CimInstanceN/ACreate new CIM-object
Get-CimSessionN/ALists CIM-sessions
New-CimSessionN/ACreate new CIM-session
New-CimSessionOptionN/ACreates object with session options; protocol, encoding, disable encryption etc. (for use with New-CimSession)
Remove-CimSessionN/ARemoves/Stops CIM-session

Additional resources

Should I use CIM or WMI with Windows PowerShell? @ Hey, Scripting Guy! Blog

GUI in Powershell

Conditional logic

See also Comparison Operators, which can be used in conditional expressions.

URL Encode/Decode

The regular expression used in the Decode URL examples was taken from RFC 2396, Appendix B: Parsing a URI Reference with a Regular Expression; for posterity, here's a quote:

The following line is the regular expression for breaking-down a URI reference into its components.

^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
 12            3  4          5       6  7        8 9

The numbers in the second line above are only to assist readability; they indicate the reference points for each subexpression (i.e., each paired parenthesis). We refer to the value matched for subexpression as $. For example, matching the above expression to

http://www.ics.uci.edu/pub/ietf/uri/#Related

results in the following subexpression matches:

$1 = http:
$2 = http
$3 = //www.ics.uci.edu
$4 = www.ics.uci.edu
$5 = /pub/ietf/uri/
$6 = <undefined>
$7 = <undefined>
$8 = #Related
$9 = Related

MongoDB

The most hard part is to attach a subdocument into the document which hasn't created yet if we need the subdocument need to be in the expected looking we will need to iterate with a for loop the array into a variable and using $doc2.add("Key", "Value") instead using the foreach current array with index. This will make the subdocument in two lines as you can see in the "Tags" = [MongoDB.Bson.BsonDocument] $doc2.

Running Executables

Error handling

HashTables

An important concept which relies on Hash Tables is Splatting. It is very useful for making a large number of calls with repetitive parameters.

ActiveDirectory module

Please remember that PowerShell's Help System is one of the best resources you can possibly utilize.

Get-Help Get-ADUser -Full
Get-Help Get-ADGroup -Full
Get-Help Get-ADComputer -Full
Get-Help Get-ADObject -Full

All of the help documentation will provide examples, syntax and parameter help.

powershell sql queries

You can use the below function if in case you are not able to import SQLPS module

function Import-Xls 
{ 
 
    [CmdletBinding(SupportsShouldProcess=$true)] 
     
    Param( 
        [parameter( 
            mandatory=$true,  
            position=1,  
            ValueFromPipeline=$true,  
            ValueFromPipelineByPropertyName=$true)] 
        [String[]] 
        $Path, 
     
        [parameter(mandatory=$false)] 
        $Worksheet = 1, 
         
        [parameter(mandatory=$false)] 
        [switch] 
        $Force 
    ) 
 
    Begin 
    { 
        function GetTempFileName($extension) 
        { 
            $temp = [io.path]::GetTempFileName(); 
            $params = @{ 
                Path = $temp; 
                Destination = $temp + $extension; 
                Confirm = $false; 
                Verbose = $VerbosePreference; 
            } 
            Move-Item @params; 
            $temp += $extension; 
            return $temp; 
        } 
             
        # since an extension like .xls can have multiple formats, this 
        # will need to be changed 
        # 
        $xlFileFormats = @{ 
            # single worksheet formats 
            '.csv'  = 6;        # 6, 22, 23, 24 
            '.dbf'  = 11;       # 7, 8, 11 
            '.dif'  = 9;        #  
            '.prn'  = 36;       #  
            '.slk'  = 2;        # 2, 10 
            '.wk1'  = 31;       # 5, 30, 31 
            '.wk3'  = 32;       # 15, 32 
            '.wk4'  = 38;       #  
            '.wks'  = 4;        #  
            '.xlw'  = 35;       #  
             
            # multiple worksheet formats 
            '.xls'  = -4143;    # -4143, 1, 16, 18, 29, 33, 39, 43 
            '.xlsb' = 50;       # 
            '.xlsm' = 52;       # 
            '.xlsx' = 51;       # 
            '.xml'  = 46;       # 
            '.ods'  = 60;       # 
        } 
         
        $xl = New-Object -ComObject Excel.Application; 
        $xl.DisplayAlerts = $false; 
        $xl.Visible = $false; 
    } 
 
    Process 
    { 
        $Path | ForEach-Object { 
             
            if ($Force -or $psCmdlet.ShouldProcess($_)) { 
             
                $fileExist = Test-Path $_ 
 
                if (-not $fileExist) { 
                    Write-Error "Error: $_ does not exist" -Category ResourceUnavailable;             
                } else { 
                    # create temporary .csv file from excel file and import .csv 
                    # 
                    $_ = (Resolve-Path $_).toString(); 
                    $wb = $xl.Workbooks.Add($_); 
                    if ($?) { 
                        $csvTemp = GetTempFileName(".csv"); 
                        $ws = $wb.Worksheets.Item($Worksheet); 
                        $ws.SaveAs($csvTemp, $xlFileFormats[".csv"]); 
                        $wb.Close($false); 
                        Remove-Variable -Name ('ws', 'wb') -Confirm:$false; 
                        Import-Csv $csvTemp; 
                        Remove-Item $csvTemp -Confirm:$false -Verbose:$VerbosePreference; 
                    } 
                } 
            } 
        } 
    } 
    
    End 
    { 
        $xl.Quit(); 
        Remove-Variable -name xl -Confirm:$false; 
        [gc]::Collect(); 
    } 
} 

Automatic Variables - part 2

Not sure if this is the best way to handle documenting Automatic Variables, yet this is better than nothing. Please comment if you find a better way :)

Package management

Cmdlet Naming

Built-in variables

Creating DSC Class-Based Resources

A class-based DSC Resource must:

  • Be decorated with the [DscResource()] attribute
  • Define a Test() method that returns [bool]
  • Define a Get() method that returns its own object type (eg. [Ticket])
  • Define a Set() method that returns [void]
  • At least one Key DSC Property

After creating a class-based PowerShell DSC Resource, it must be "exported" from a module, using a module manifest (.psd1) file. Within the module manifest, the DscResourcesToExport hashtable key is used to declare an array of DSC Resources (class names) to "export" from the module. This enables consumers of the DSC module to "see" the class-based resources inside the module.

Powershell Modules

PowerShell Workflows

The PowerShell Workflow feature is exclusively supported on the Microsoft Windows platform, under PowerShell Desktop Edition. PowerShell Core Edition, which is supported on Linux, Mac, and Windows, does not support the PowerShell Workflow feature.

When authoring a PowerShell Workflow, keep in mind that workflows call activities, not cmdlets. You can still call cmdlets from a PowerShell Workflow, but the Workflow Engine will implicitly wrap the cmdlet invocation in an InlineScript activity. You can also explicitly wrap code inside of the InlineScript activity, which executes PowerShell code; by default the InlineScript activity runs in a separate process, and returns the result to the calling Workflow.

How to download latest artifact from Artifactory using Powershell script (v2.0 or below)?

Calculated Properties

Special Operators

Anonymize IP (v4 and v6) in text file with Powershell

Comment-based help

Amazon Web Services (AWS) Simple Storage Service (S3)

Amazon Web Services (AWS) Rekognition

PSScriptAnalyzer - PowerShell Script Analyzer

Naming Conventions

Embedding Managed Code (C# | VB)

Removing Added types

In later versions of PowerShell, Remove-TypeData has been added to the PowerShell cmdlet libraries which can allow for removal of a type within a session. For more details on this cmdlet, go here: https://msdn.microsoft.com/en-us/powershell/reference/4.0/microsoft.powershell.utility/remove-typedata

CSharp and .NET syntax

For those experience with .NET it goes without saying that the differing versions of C# can be quite radically different in their level of support for certain syntax.

If utilising Powershell 1.0 and/or -Language CSharp, the managed code will be utilising .NET 2.0 which is lacking in a number of features which C# developers typically use without a second thought these days, such as Generics, Linq and Lambda. On top of this is formal polymorphism, which is handled with defaulted parameters in later versions of C#/.NET.

Archive Module

Infrastructure Automation

Scheduled tasks module

ISE module