using powershell’s help system to stash your tips and tricks in ‘about_’ topics

There are a bunch of bits of syntax which I struggle to remember.

I’m not always online when I’m using my laptop, but I always have a Powershell window open.

This is a possibly not-best-practice way of using Powershell’s wonderful help system to store bits of reference material.

The problem

I’m moving a WordPress blog to Hugo, which uses Markdown, but I’m struggling to remember the Markdown syntax. It’s not difficult, but I’m getting old and I get confused with Twiki syntax.

In any case this ‘technique’ could be used for anything.

I could equally well just store the content in a big text file, and select-string it….but this is more fun 🙂

The content

In this instance I only need a few lines as an aide-memoire:

    ## The second largest heading (an <h2> tag)
    > Blockquotes
    *italic* or _italic_
    **bold** or __bold__
    * Item (no spaces before the *) or
    - Item (no spaces before the -)
    1. Item 1
      1. Furthermore, ...
    2. Item 2
    `monospace` (backticks)
    ```` begin/end code block
    [A link!](http://mattypenny.net).

create a module

The module path is given by:

$env:PSModulePath

Mine is:

C:\Users\matty\Documents\WindowsPowerShell\Modules;C:\Program Files\WindowsPowerShell\Modules;C:\Windows\system32\WindowsPowerShell\v1.0\Modules\;C:\Program Files (x86)\Microsoft SQL Server\110\Tools\PowerShell\Modules\

Pick one of this folders to create your module in and do this:

mkdir C:\Users\matty\Documents\WindowsPowerShell\Modules\QuickReference

Then create a dummy Powershell module file in the folder

notepad C:\Users\matty\Documents\WindowsPowerShell\Modules\QuickReference\QuickReference.psm1

The content of the module file is throwaway:

function dummy {write-output "This is a dummy"}

create the help file(s)

Create a language-specific folder for the help files

mkdir C:\Users\matty\Documents\WindowsPowerShell\Modules\QuickReference\en-US\

Edit a file called about_.help.txt

notepad C:\Users\mpenny2\Documents\WindowsPowerShell\Modules\QuickReference\en-US\about_Markdown.help.txt

My content looked like this:

TOPIC
    about_Markdown

SHORT DESCRIPTION
    Syntax for Markdown 

LONG DESCRIPTION

    ## The second largest heading (an <h2> tag)
    > Blockquotes
    *italic* or _italic_
    **bold** or __bold__
    * Item (no spaces before the *) or
    - Item (no spaces before the -)
    1. Item 1
      1. Furthermore, ...
    2. Item 2
    `monospace` (backticks)
    ```` begin/end code block
    [A link!](http://mattypenny.net).

Use the help

I can now do this (I’ll import the module in my $profile):

PS C:\Windows> import-module QuickReference

Then I can access my Markdown help from within Powershelll

PS C:\Windows> help Markdown
TOPIC
    about_Markdown

SHORT DESCRIPTION
    Syntax for Markdown 

LONG DESCRIPTION

    ## The second largest heading (an <h2> tag)
    > Blockquotes
    *italic* or _italic_
    **bold** or __bold__
    * Item (no spaces before the *) or
    - Item (no spaces before the -)
    1. Item 1
      1. Furthermore, ...
    2. Item 2
    `monospace` (backticks)
    ```` begin/end code block
    [A link!](http://mattypenny.net).

extracting post details from wordpress xml dump with powershell

Get the xml into a variable

[xml]$xmla = get-content D:\repair_websites\salisburywiltshireandstonehenge.wordpress.2015-10-03.xml                       

Extract the details

select-xml -xml $xmla -xpath "//channel/item" | select -expandproperty node | ? post_type -ne "attachment" | select title  

gives the following:

title                        
-----                        
Road names beginning with 'N'
Road names beginning with 'O'
Road names beginning with 'P'
Road names beginning with 'Q'
Road names beginning with 'R'
Road names beginning with 'S'
Road names beginning with 'T'
Road names beginning with 'U'
Road names beginning with 'V'
Road names beginning with 'W'

The properties of the expanded node are:
wordpress-xml-powershell-properties

For example:

select-xml -xml $xmla -xpath "//channel/item" | select -expandproperty node | ? post_type -ne "attachment" | ? title -like "*Ramone*"

outputs:

title          : 3rd June 1977 - the Ramones visit Stonehenge. Johnny stays on the bus
link           : http://salisburyandstonehenge.net/on-this-day/june/3rd-june-1977-the-ramones-visit-stonehenge-johnny-stays-on-the-bus
pubDate        : Tue, 04 Nov 2014 12:33:09 +0000
creator        : creator
guid           : guid
description    : 
encoded        : {content:encoded, excerpt:encoded}
post_id        : 9267
post_date      : 2014-11-04 12:33:09
post_date_gmt  : 2014-11-04 12:33:09
comment_status : open
ping_status    : closed
post_name      : 3rd-june-1977-the-ramones-visit-stonehenge-johnny-stays-on-the-bus
status         : publish
post_parent    : 6624
menu_order     : 3
post_type      : page
post_password  : 
is_sticky      : 0
postmeta       : {wp:postmeta, wp:postmeta, wp:postmeta, wp:postmeta}

To get the actual content of the post:

select-xml -xml $xmla -xpath "//channel/item" | select -expandproperty node | ? post_type -ne "attachment" | ? title -like "*Ramone*" | select -ExpandProperty encoded | fl

…gives:

#cdata-section : <a href="http://salisburyandstonehenge.net/images/Joey-Ramone-visited-Stonehenge.jpg"><img src="http://salisburyandstonehenge.net/images/Joey-Ramone-visited-Stonehenge.jpg" alt="Joey Ramone - 'visited' 
                 Stonehenge" width="320" height="455" class="alignright size-full wp-image-9702" /></a>On either the 3rdIn 'On the Road with 
                 the Ramones', Monte A. Melnick says that the visit occurred 

                 <blockquote>'On the '77 tour we had a day off and noticed Stonehenge was on the way'[URL <a href="http://books.google.co.uk/books?
                 id=N7m8AwAAQBAJ&lpg=RA1-PR24&dq=ramones%20stonehenge&pg=RA1-PR25#v=onepage&q=ramones%20stonehenge&f=false">'On the Road with the 
                 Ramones', by By Monte A. Melnick, Frank Meyer</a>].</blockquote>

                 This would have been when the Ramones were travelling back from Penzance to Canterbury - the free day being June 3rd [<a href="http://en.wikipedia.org/wiki/List_of_Ramones_concerts#1977">Wikipedia List Of Ramones Concerts</a>] or possibly the 
                 4th June 1977, the Ramones visited Stonehenge.

                 Pic: By en:User:Dawkeye [<a href="http://www.gnu.org/copyleft/fdl.html">GFDL</a>, <a href="http://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA-3.0</a> or <a href="http://creativecommons.org/licenses/by-sa/2.5">CC-BY-SA-2.5</a>], <a href="http://commons.wikimedia.org/wiki/File%3AJoeyramone.jpg">via Wikimedia Commons</a>

                 More:

                 <a href="http://books.google.co.uk/books?id=c7lgKVmD0yMC&lpg=PA170&dq=ramones%20stonehenge&pg=PA171#v=onepage&q=ramones%20stonehen
                 ge&f=false" title="http://books.google.co.uk/books?id=c7lgKVmD0yMC&lpg=PA170&dq=ramones%20stonehenge&pg=PA171#v=onepage&q=ramones%
                 20stonehenge&f=false">I Slept with Joey Ramone: A Family Memoir By Mickey Leigh</a>

                 <a href="http://books.google.co.uk/books?id=N7m8AwAAQBAJ&lpg=RA1-PR24&dq=ramones%20stonehenge&pg=RA1-PR25#v=onepage&q=ramones%20st
                 onehenge&f=false" title="http://books.google.co.uk/books?id=N7m8AwAAQBAJ&lpg=RA1-PR24&dq=ramones%20stonehenge&pg=RA1-PR25#v=onepag
                 e&q=ramones%20stonehenge&f=false">On the Road with the Ramones By Monte A. Melnick, Frank Meyer</a>

                 <a href="http://books.google.co.uk/books?ei=AxPJU5u3Jae60QXB1ICQBQ&id=QTjaAAAAMAAJ&dq=ramones+stonehenge&focus=searchwithinvolume&
                 q=+stonehenge" title="http://books.google.co.uk/books?ei=AxPJU5u3Jae60QXB1ICQBQ&id=QTjaAAAAMAAJ&dq=ramones+stonehenge&focus=search
                 withinvolume&q=+stonehenge">A Time to Rock: A Social History of Rock and Roll by David P. Szatmary</a>


#cdata-section : 

powershell to recursively spool out code in markdown format

A one-liner to recursively gather code from sub-folders and then output it in a Markdown-style

$Text = foreach ($file in $(dir .\themes\hyde -recurse -exclude "*.png" | ? attributes -ne 'Directory' | select fullname)) 
{
    [string]$filename = $file.fullname
    write-output "`#`#`# $filename"
    write-output "````````"
    get-content $filename
    write-output "````````" 
}

$Text > x.txt

Produces output a like this:

D:\hugo\sites\example.com\themes\hyde\archetypes\default.md

+++
Description = ""
Tags = ["Development", "golang"]
Categories = ["Development", "GoLang"]
menu = "main"
+++

D:\hugo\sites\example.com\themes\hyde\layouts_default\list.html

{{ partial "head.html" . }}
<body class="{{ .Site.Params.themeColor }}">

{{ partial "sidebar.html" . }}

<div class="content container">
<ul class="posts">
{{ range .Data.Pages }}

error 740 running DISM

As the error message says, if you get Error 740

PS C:\Users\matty> DISM /Online /Enable-Feature /FeatureName:NetFx3 /All /LimitAccess /Source:z:\sources\sxs

Error: 740

Elevated permissions are required to run DISM.
Use an elevated command prompt to complete these tasks.

…you just have to run your Command Prompt or Powershell window ‘as Administrator’. i.e. right-click on the icon and select ‘Run as administrator’

PS C:\Windows\system32> DISM /Online /Enable-Feature /FeatureName:NetFx3 /All /LimitAccess /Source:z:\sources\sxs

Deployment Image Servicing and Management tool
Version: 6.3.9600.17031

Image Version: 6.3.9600.17031

Enabling feature(s)
[==========================100.0%==========================]
The operation completed successfully.
PS C:\Windows\system32>

how I sketchnote

wsd-logo-600pxJanuary 11th has been designated as World Sketchnote Day. Out of sheer perversity. I thought rather than doing a sketchnote, I thought I’d type something in plain text!

A couple of people have asked about the way I do sketchnotes, so this seems like a good day to post it.

I read the book – reading Mike Rohde’s ‘The Sketchnote Handbook’ is a big jump-start. It’s quick and fun to read and it’s a lovely book. I read it in a couple of hours. Any other words of wisdom I might have pale into insignificance besides ‘go and read Mike’s book‘.

A4 paper – I now do all my Sketchnoting on plain A4 paper. It’s a good size for an hour’s talk, it’s cheap, it’s easy to scan and I don’t often run out of it.

Squared paper – I created an A4 grid in Word and put the blank sheet on top of that. This makes the notes a bit less scruffy.

Erasable ink – I use Uniball Frixion pens. I don’t rub much out, but it’s handy to be able to do so. Pencil doesn’t scan as well as ink.

Agendas are useful – if I can find the slides for a talk I’ve found it useful to have the agenda handy, so that I know when the speaker has moved on to a new topic.

No overdubs – I do 99% of the sketchnote-ing of talks live, in real-time. This is partly because I’m lazy, but it also means that any benefits I get from sketchnoting are essentially free. Apart from the time it takes to scan and post, the sketchnoting doesn’t take any extra time beyond the time I’m spending attending the talk.

Visual vocabulary – Mike Rohde uses the phrase ‘visual vocabulary’ for the collection of things you can draw fairly quickly when you need to. Because I’m a bit of a nerd, I’m collecting these on a visual vocabulary page. The page is useful to remind myself how I’ve drawn things in the past…but I’m thinking I’m might convert it to something I can print on a couple of pieces of paper.

‘Learning’ from others – I’ve copied some ways of drawing things from other sketchnoters. I sometimes copy clip-art or icons or logos too.

Webcasts are great – I do sometimes feel self-conscious sketchnoting at a conference. Webcasts avoid this issue!

Tedtalks aren’t great – a lot of people practice sketchnoting Tedtalks with very good results. This doesn’t work so well for me. I’ve tried it a couple of times, but found I was continually re-winding the talk and hunting down stuff to sketch. A 20-minute talk took me getting on for two hours to sketchnote. And it still wasn’t finished.

Not drawing the presenter – early on I used to do a sketch of the person who was doing the talk. This probably isn’t a good idea unless you’re a good artist and can make it flattering… or unless you know the presenter and know they won’t mind their appearance being reduced to, say, a bald head and glasses.

Publishing – I started putting the sketchnotes on twitter as soon as I’d read the book. It didn’t seem good enough to publish, but if I’d waited until it did I’d have never shown it to anyone. I would do sketchnotes anyway, but I’ve gained a lot through putting them out there.

I’m not very good at – color, drawing, different formats, not trying to capture everything.

Practice – I do practice some of the drawings in odd moments when I have a pen and paper to hand. A lot of doodling is done in meetings! Also, sometimes while I’m sketchnoting I’ll try out, say, drawing a pig on a bit of scrap paper, before putting it into the sketchnote.

powershell equivalent of linux ‘ps -aux | sort -k3n’

I’m not entirely sure how I managed to not find out about Win32_PerfFormattedData_PerfProc_Process before now. I think the ‘sort -k3n’ does a sort by CPU-usage, but I’m sure there’s a better way of doing it than that.

gwmi Win32_PerfFormattedData_PerfProc_Process -ComputerName $ComputerName | 
  Sort-Object -Property PercentProcessorTime -desc | 
  select idprocess, name, IODataBytesPersec, PercentPrivilegedTime,PercentProcessorTime, PercentUserTime, workingset | 
  Select-Object -first 11 | 
  ft -AutoSize

gives:

idprocess name      IODataBytesPersec PercentPrivilegedTime PercentProcessorTime PercentUserTime workingset
--------- ----      ----------------- --------------------- -------------------- --------------- ----------
        0 _Total               849620                   100                  100              18 5667786752
        0 Idle                      0                   100                  100               0       4096
     5552 sqlservr             236135                     0                   18              18 3040718848
     3680 TmListen             344690                     6                    6               0   10211328
    10012 PccNTMon               7574                     6                    6               0    4706304
      496 services                  0                     0                    0               0   11198464
      744 svchost#3                 0                     0                    0               0   69857280
      568 svchost#2                 0                     0                    0               0   14368768
      792 svchost#1                 0                     0                    0               0   24203264
     2132 svchost                   0                     0                    0               0    5054464
     5888 Ssms#1                    0                     0                    0               0  190734336

‘unable to find type [date]’ and other date-related powershell errors

This post just goes through a bunch of errors I got while trying to subtract one date from another. A lot of stuff on the internet quite rightly focuses on ‘how to’ do things in Powershell. I thought it might be useful to post up some examples of ‘how not to’.

I’ve got a tendency to just start trying things out rather than reading the help text. This isn’t typically a good idea, but it does have the advantage of meaning that you do find out what the error message are 🙂

Unable to find type [date]

Error: “String was not recognized as a valid DateTime.”

the right way – $(get-date) – $PaulsDateOfBirth

Exception setting “End”: “Cannot convert null to type “System.DateTime”.”

Error: “String was not recognized as a valid DateTime.”

the solution – use get-date

Unable to find type [date]

First:

PS> [date]$PaulsDateOfBirth = '18 June 1942'

returned this:

Unable to find type [date].
At line:1 char:1
+ [date]$PaulsDateOfBirth = '18 June 1942'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (date:TypeName) [], RuntimeException
    + FullyQualifiedErrorId : TypeNotFound

This is fairly simple. The type I was thinking of is called =datetime=, not =date=, so the following ‘works’ in that it returns no errors

PS > [datetime]$PaulsDateOfBirth = '18 June 1942'

Error: “String was not recognized as a valid DateTime.”

So next I did this

get-date - $PaulsDateOfBirth

which is rubbish. I got this:

Get-Date : Cannot bind parameter 'Date'. Cannot convert value "-" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."

At line:3 char:10

+ get-date - $PaulsDateOfBirth

+          ~
    + CategoryInfo          : InvalidArgument: (:) [Get-Date], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetDateCommand

the right way – $(get-date) – $PaulsDateOfBirth

This is much better:

$(get-date) - $PaulsDateOfBirth

which I think is actually returning the right result.

Days              : 26818
Hours             : 17
Minutes           : 53
Seconds           : 44
Milliseconds      : 346
Ticks             : 23171396243469845
TotalDays         : 26818.7456521642
TotalHours        : 643649.89565194
TotalMinutes      : 38618993.7391164
TotalSeconds      : 2317139624.34698
TotalMilliseconds : 2317139624346.98

Exception setting “End”: “Cannot convert null to type “System.DateTime”.”

Having got that far I wanted to turn the one-liner into a function that would return Paul’s age on any given day. I’ve just pasted in the lines which are relevant to the error here:

$DateOfAllbumRelease = $(get-date))
$PaulsDateOfBirth = [datetime]"1942-06-18"
$PaulsAge = new-timespan $PaulsDateOfBirth $DateOFAlbumRelease
$PaulsAge

The code looks reasonable…but I got this

get-PaulsAge
New-TimeSpan : Cannot bind parameter 'End' to the target. Exception setting "End": "Cannot convert null to type "System.DateTime"."
At line:6 char:44
+ $PaulsAge = new-timespan $PaulsDateOfBirth $DateOFAlbumRelease
+                                            ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : WriteError: (:) [New-TimeSpan], ParameterBindingException
    + FullyQualifiedErrorId : ParameterBindingFailed,Microsoft.PowerShell.Commands.NewTimeSpanCommand

0

This is a simple one…especially so given the knowledge that I often mis-spell ‘Album’ as ‘Allbum’. Correcting the type, the function then worked:

get-PaulsAge
73.4739726027397

Error: “String was not recognized as a valid DateTime.”

What I actually wanted to do was call the function several times for different dates. I had this list:

22/03/63
26/04/63
22/11/63
19/06/64
10/07/64
4/12/64
6/08/65
3/12/65
5/08/66
10/12/66
1/06/67
22/11/68
17/01/69
26/09/69
8/05/70

…but you cant just put [datetime] in front of it

PS > [datetime]"22/03/63"
Cannot convert value "22/03/63" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."
At line:1 char:1
+ [datetime]"22/03/63"
+ ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvalidCastParseTargetInvocationWithFormatProvider


Incidentally it still doesn’t work if you try using the string as the value for a typed variable

[datetime]$X="22/03/63"
Cannot convert value "22/03/63" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."
At line:1 char:1
+ [datetime]$X="22/03/63"
+ ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException

the solution – use get-date

However, get-date does happily convert the same string to a date, and return it as such to standard output

PS > get-date "22/03/63"
22 March 1963 00:00:00

…and

PS > get-date "1/03/63"
01 March 1963 00:00:00

So with my function defined as:

PS > Function get-PaulsAge {
param ($DateOfAlbumRelease = $(get-date))
$PaulsDateOfBirth = [datetime]"1942-06-18"
$PaulsAge = new-timespan $PaulsDateOfBirth $DateOFAlbumRelease
$PaulsAgeInDays = $PaulsAge.days 
$PaulsAgeInYears = $PaulsAge.days / 365
$PaulsAgeInYears
}

… I could do this

get-PaulsAge $(get-date "22/03/63")
get-PaulsAge $(get-date "26/04/63")
get-PaulsAge $(get-date "22/11/63")
get-PaulsAge $(get-date "19/06/64")
get-PaulsAge $(get-date "10/07/64")
get-PaulsAge $(get-date "4/12/64")
get-PaulsAge $(get-date "6/08/65")
get-PaulsAge $(get-date "3/12/65")
get-PaulsAge $(get-date "5/08/66")
get-PaulsAge $(get-date "10/12/66")
get-PaulsAge $(get-date "1/06/67")
get-PaulsAge $(get-date "22/11/68")
get-PaulsAge $(get-date "17/01/69")
get-PaulsAge $(get-date "26/09/69")
get-PaulsAge $(get-date "8/05/70")

and get the following, which as any fule kno, is Paul McCartney’s age, in years, when each of the Beatles’ LPs came out

20.772602739726
20.8684931506849
21.4438356164384
22.0191780821918
22.0767123287671
22.4794520547945
23.1506849315068
23.4767123287671
24.1479452054795
24.4958904109589
24.9698630136986
26.4493150684931
26.6027397260274
27.2931506849315
27.9068493150685