Skip to main content

Useful Powershell stuff

Group objects into batches of X items with a constructed property, credit to Dave Wyatt:

$bigList = 1..1000
$counter = [pscustomobject] @{ Value = 0 }
$groupSize = 100
$groups = $bigList | Group-Object -Property { [math]::Floor($counter.Value++ / $groupSize) }

Use "PipelineVariable" to pass data down the pipeline rather than using a foreach:

Get-ADUser <username> -PipelineVariable user -Properties memberof |
    Select-Object -ExpandProperty memberof |
        Select-Object @{ n = 'Name'; e = { $user.Name }}, @{ n = 'MemberOf' ; e = { $PSItem -replace 'CN=|,(OU|CN)=.+' }}

Also if a cmdlet does not support -pipelineVariable you can pass it to Where-Object

Get-Mailbox -ResultSize Unlimited | Where-Object {$true} -PipelineVariable mbx | whatever

Convert a list of strings into a single line string delimited by quotes and separated by commas, suitable for using in a "IN" statement in SQL/SOQL

$ids is a list of ID strings
$idsString = $ids -replace "(\w+)",'''$1'''  -join ','
or if it's one large string separated by line breaks (e.g. copied from a spreadsheet):
$idsString = ($ids -replace "(\w+)",'''$1''').Split("`n") -join ','

Print a line
'_' * 100

Prevent null references, incorrect syntax usage, unnamed variables:
Set-StrictMode -Version Latest

Creating a new instance of a .net framework object
New-Object TypeName "System.Diagnostics.Stopwatch"
Or more simply, New-Object System.Diagnostics.Stopwatch
Because it's a string, don't use the type name in angle brackets like PS normally would

To view absolutely everything that's happening internally in the powershell pipeline for a particular scriptblock:
Trace-Command -Name * -Expression {Get-Service winrm | Restart-Service} -PSHost

Add a calculated property to a list of objects, along with all the other properties:
    Select *,@{Name="ExtraField"; Expression={$_.SomeValue+1}}, @{Name="Whatever"; Expression={"Some string"}}

Get a list of drives, including network drives and their UNC paths (like with "net use"):
    Get-WmiObject -Class win32_logicaldisk

Get previous session history with "get-history"
Run a previous command without pushing up 1000 times with "invoke-history"

csi = C# interactive (custom alias)

get a list of every property and value for an object:
    $whatever | Format-List
Prevent output from truncating:
    Format-Table -AutoSize -Wrap

& { blah } 1 > $null    - suppress standard output from executing "blah". More info
$var = & Do-Stuff *>&1  - redirect all output to standard output and store that in $var
& { whatever } 2>$null 3>$null - redirect error and warning streams

get-content .\somefile -Wait  - tail-like behaviour, displays additions to the file
get-content | more  - allows paging of output

Getting a count of duplicated things:
$whatever | group FieldToGroup | where Count -gt 1 | sort Count -Descending | select Name, Count

set-clipboard (scb) - sets the contents of the clipboard to whatever is pasted in.  Useful with sls for non-powershell commands that output text that you have to use in another command

`t - tab

When using delimiters with "Import-Csv -Delimiter", make sure not to surround them with quotes

cd env:    gets environment vars
get-psprovider    lists providers
get-psdrive    lists drives
get-module -listavailable    lists all available modules

hashtable of variables for passing in parameters
$parameters = @{
    'param1' = $value1
    'param2' = $value2

Run-SomeCmdlet @parameters     <- notice the @ symbol, not $

write-verbose lines in a function only write if a -verbose flag was provided to the function

@($a) forces $a to be in an array

use regexes with "where" with the "match" operator:
    gci | where name -match '\d{2}'

rename properties for a select:
        ps | select @{Name='Title';Exp={$_.ProcessName}}

select-string (alias: sls)
    very useful for selecting strings from a whole bunch of string-based output
    works like grep in linux
        ipconfig | sls subnet

To use IIS stuff:
    Import-Module WebAdministration
open IIS drive and navigate to a website:
    cd IIS:\
    cd sites\sitename

Get a list of every module
    Get-Module -ListAvailable
Find a module based on name
    Get-Module *web*
Find all commands in a module
    Get-Command -Module WebAdministration

get current item members:
    gi . | gm
recycle an app pool by navigating to it
    cd IIS:\AppPools\somewebsite
    (gi .).Recycle()
or also in one line:
    (gi IIS:\AppPools\somewebsite).Recycle()

ii (invoke-item)
    performs the default action on an item, e.g. opens a file using a program

-join operator, joins strings together
    when used first (unary), joins without delimiting
        -join ("asdf", "qwer") #outputs asdfqwer
    when used as a binary operator, allows a delimiter
        ("asdf", "qwer") -join '-' #outputs asdf-qwer

-replace operator, using regex to replace strings
    replace pairs of html tags with <small>:
        $foo = $foo -replace '<(\/)?\w+>', '<$1small>'

searching application event log for a particular guid:
    Get-EventLog -logname application | where {$_.Message -ilike "*6CD27361-D038-E611-9B7F-005056956605*") } | select message


Popular posts from this blog

'A section using configSource may contain no other attributes or elements' error after installing Application Insights

After installing the Application Insights nuget package to an Umbraco solution, you'll get this error:

A section using 'configSource' may contain no other attributes or elements

<ExamineLuceneIndexSets configSource="config\ExamineIndex.config" />
     <log4net configSource="config\log4net.config">
             <level value="ALL" />
             <appender-ref ref="aiAppender" />
Source File: \project\web.config

This happens because part of the Application Insights installation process adds a <log4net> section to web.config.  Which would make sense, except Umbraco already has a <log4net> section in /config/log4net.config.  So as you can imagine, the solution is to manually move everything its added into that file. Unfortunately you can't just copy/paste the whole lot, but it's not particularly complicated:

Move <appender-ref ref="aiAppender" /> into the lo…

Handling double-quoted CSVs in Azure Data Factory Pipelines

Azure Data Factory by default uses a backslash as the escape character for CSVs, but we ran into an issue with this today processing one of the CSV files from  As with most CSVs they use quotes around values as normal and with double-quotes for empty values, but they also use double-quotes to escape quotes within non-empty values. This probably sounds confusing, so here's an example:

"column 1","column 2","","column 4 value is ""sort of"" like this"

The ADF pipeline failed because the double-quotes don't get escaped correctly:
ErrorCode=UserErrorSourceDataContainsMoreColumnsThanDefined, found more columns than expected column count.

The solution was to change the "Escape character" property on the dataset, by clicking the "Edit" button beneath it and manually entering "", since "" isn't in the list of escape characters.  I didn't think this would work at fir…

How to make yourself a Dynamics CRM 2011 Deployment Administrator

Today I needed to deactivate one of our Dynamics organisations, but when I opened the Dynamics Deployment Manager, I received the following error:

"Only the Deployment Administrators are able to use Deployment Manager. You are not a Deployment Administrator."
Bummer. I did a bit of Googling and found this post by Ronald Lemmen (thanks for pointing me in the right direction!).  Since the Dynamics Deployment Manager is obviously checking the MSCRM_CONFIG database for this information I attached a database trace to it and found that it's executing these queries (among many others):

exec sp_executesql N'SELECT  Id, [DefaultOrganizationId], [IsDisabled], [Name]   FROM [SystemUser]   WHERE ((([Name] = @Name0)) ) AND (IsDeleted = 0) ', N'@Name0 nvarchar(41)',@Name0=N'{My windows domain account}'
exec sp_executesql N'SELECT  Id, [Name], [UniqueifierId]   FROM [SecurityRole]   WHERE ((([Name] = @Name0)) ) AND (IsDeleted = 0) ', N'@Name0 nvarchar…