PowerShell Transcripts

PowerShell has an interesting cmdlet that lets you save a transcript of a PowerShell session. Every command you run and the resulting output can be recorded to a text file. This file can be used as a training aid, an audit trail, or as the source for rapid PowerShell script development.

To begin recording, use the Start-Transcript cmdlet simply by specifying a filename:

start-transcript c:\transcript.txt

From this point, every shell command and output will also be recorded in the transcript file. To stop recording run

stop-transcript

If you open the file in Notepad (or use Get-Content) you’ll see  header and footer sections plus every command you ran. You’ll see that each command includes the PowerShell prompt, which defaults to a directory path. Since a .ps1 file is really nothing more than a bunch of PowerShell expressions, you could take the transcript file, parse out the expressions and have the beginnings of a PowerShell script.

I’ve created a function, as demonstrated in this script, that takes a PowerShell transcript and creates a text file (presumably a ps1 file) with just the commands or expressions.

# ParseTranscript.ps1

Function Parse-Transcript {
# Take a PowerShell transcript and parse it for commands,
# sending each line to a new script file which can then
# be further edited.

# transcript source example
# $log=”c:\transcript.txt”

# filename for script to be created from transcript
# $script=”c:\TempScript.ps1″
Param ([string]$log=$(Throw “You need to specify a transcript file name”),[string]$script=$(Throw “You need to specify a filename for the output”))

if (! (test-path $log)) {
throw “$($log) can’t be found!”
}

#Create new file and overwrite any existing file
“# Script Created “+(Get-Date).ToString() | `
Out-File -filepath $script
“# Source file: “+$log |Out-File -filepath $script -append
“# Author: “+ ((get-childitem env:username).value).ToUpper() | `
Out-File -filepath $script -append

$filteredLog=Get-Content $log |Select-String “> “
# drop the last line which is likely a stop-transcript command
for ($i=0;$i -lt $filteredLog.length-1;$i++)
{
    $tmp=($filteredLog[$i].ToString()).split(“>”)
    ($tmp[1]).Trim() | Out-File -filepath $script -append
}

Write-Host “Finished parsing” $log”. See” $script “for your script.”

}

$source=Read-Host “What is the filename and path of your transcript file?”
$dest=Read-Host “What is the filename and path for the ps1 output file?”
Parse-transcript $source $dest

The function needs the filename and path of the transcript file and a filename for the output file.

The function uses Select-String to only pull the lines that have “> “, which should be the end of each prompt, and creates $filteredLog

$filteredLog=Get-Content $log |Select-String “> “

Normally you would use a ForEach expression to parse out $filteredLog. However, I’m assuming I won’t need the last expression entered which will be a Stop-Transcript command. Therefore, I’m using a For expression to get every line but the last one.

for ($i=0;$i -lt $filteredLog.length-1;$i++)

The real work is splitting the line at >. I create a second temporary array to hold the results of the Split method:

 $tmp=($filteredLog[$i].ToString()).split(“>”)

Finally I get the second element of the temporary array which should be a PowerShell command.  I use Trim to get rid of any leading or trailing spaces:

($tmp[1]).Trim() | Out-File -filepath $script -append

This process is repeated for every line in $filteredlog except the last one. That’s all there is to it. When I’m finished I have a .ps1 file that could be run as a script, or most likely edited and refined in PrimalScript.