Sorting PowerShell Transcript Files


Summary: Ed Wilson, Microsoft Scripting Guy, talks about creating a sortable transcript name.

Microsoft Scripting Guy, Ed Wilson, is here. One of the great things about Windows PowerShell is that if there is something that annoys you, you can generally fix it. Don’t get me wrong, Windows PowerShell is great, but like any program, there are things that annoy me. It is partly because I have different needs than a typical user—I have never been typical in my life.

For example, I think that all of the defaults in Windows Explorer are wrong for me. For example, I want to see file extensions, I want to see hidden and system files, and I really want to know by looking at the name, if the file is encrypted or compressed—and all of these settings are exactly the opposite.

But with a billion users worldwide, I can imagine that we have done extensive research, and that the settings are exactly right for the vast majority of those billion users. And I know that by using Windows PowerShell, I can fix my Windows issues pretty easily.

If it is easy to fix many of my Windows issues, it is really easy to fix my Windows PowerShell issues. What am I talking about today?

Well, I am talking about the Windows PowerShell transcript feature. I love the Windows PowerShell transcript feature, but what I don’t like is the name generates automatically by the Windows PowerShell transcript feature. Oh, it is great, and the fact that we throw in a random number means I can start the transcript many times per second, and never get a file name conflict.

But dude, that is just it. At least on my laptop, I can barely start the Windows PowerShell transcript tool every two or three seconds, so I don’t need that level of precision in the file name. In fact, with the name as it stands, I cannot sort by file name. It comes out, well, rather random. So I decided to change that with my own function that I will place in my Windows PowerShell profile.

The problem with the default name

The default Windows PowerShell transcript name includes the words PowerShell_Transcript (which is cool), the name of the computer (which is also cool), then a random number, and finally the date string. It is the random number that is a bit of a problem. In addition, the date string is all one number, and it is a bit cumbersome to read. Here is a typical default transcript name:

PowerShell_transcript.EDLT.Dz6sxz6B.20150720151906.txt

When I look at the transcripts in the Windows Explorer, the files are somewhat jumbled. Of course, I can click and sort by date, but that is an extra click that I don’t want to do. Also, if I am sorting in Windows PowerShell, it is also another step to sort by date. Here is a screenshot of the default transcripts.

Image of menu

A better file name

I like having PowerShell_Transcript in the file name, and I prefer the capital T in the name. I also like the idea of having the computer name in the file so it is easy to find related transcripts if I happen to copy them to a file share. The random number needs to go, and then I want a sortable date-time string. I can easily get a sortable date-time string from Get-Date by using Format s from the .NET DateTime object. This is shown here:

PS C:\> Get-Date -format s

2015-07-21T12:35:37

The problem with this is that I cannot use a colon in a file name—it is invalid. How do I remember this? Well, as shown here, there is a static method from the System.Io.Path .NET framework class:

[io.path]::GetInvalidFileNamechars()

So once I know all of the invalid file name characters, I can easily replace them by using the –Replace operator and supplying a replacement value, such as an underscore. And that is what I do. I store my sortable date in a variable, I store my disallowed file name characters in a variable, and I then call the –Replace operator to fix the sortable time into something I can use.

Because I need something I can replace and I cannot do a replacement operation on a DateTime object, I convert my date to string by calling the ToString method. I then use the –f format specifier, and do a substitution to create my new file name. The entire function is shown here:

Function Get-TranscriptName

{

 $invalidChars = [io.path]::GetInvalidFileNamechars()

 $date = Get-Date -format s

  "{0}.{1}.{2}.txt" -f "PowerShell_Transcript", $env:COMPUTERNAME,

  ($date.ToString() -replace "[$invalidChars]","-") }

Now, I simply add it to my Windows PowerShell profile.

But I still need to fix my call to Start-Transcript. Start-Transcript has a –path parameter, which is the path to the folder and the file name. So I need to create a path. I do this by using the $doc variable that I previously defined as pointing to the document folder in my profile:

New-Variable -Name doc -Value "$home\documents"

I call my function to create the file name. To do this, I need a subexpression (which means to run the function), get the output, and THEN use it in my path. The command is shown here:

Start-Transcript -Path (Join-Path –Path $doc -ChildPath $(Get-TranscriptName))

In my profile, I use the function to determine if I am running in a Windows PowerShell console:

Function Test-ConsoleHost

{

 if(($host.Name -match 'consolehost')) {$true}

 Else {$false}  

}

I also created an alias to the function:

Set-Alias -Name tch -Value Test-ConsoleHost | out-null

When I call the command to start the transcript, I first check to see if I am running in the Windows PowerShell console:

If(tch) {Start-Transcript -Path (Join-Path -Path `

 $doc -ChildPath $(Get-TranscriptName))}

When I check for Windows PowerShell transcripts, the files appear in order:

Image of menu

Here is the complete Windows PowerShell profile:

#------------------------------------------------------------------------------

#

# PowerShell console profile

# ed wilson, msft

#

# NOTES: contains five types of things: aliases, functions, psdrives,

# variables and commands.

# version 1.1

# 7/20/2015

# HSG 7-23-2015

#------------------------------------------------------------------------------

#Aliases

Set-Alias -Name ep -Value edit-profile | out-null

Set-Alias -Name tch -Value Test-ConsoleHost | out-null

#Functions

Function Edit-Profile

{ ISE $profile }

Function Test-ConsoleHost

{

 if(($host.Name -match 'consolehost')) {$true}

 Else {$false}  

}

Function Get-TranscriptName

{

 $invalidChars = [io.path]::GetInvalidFileNamechars()

 $date = Get-Date -format s

  "{0}.{1}.{2}.txt" -f "PowerShell_Transcript", $env:COMPUTERNAME,

  ($date.ToString() -replace "[$invalidChars]","-") }

#Variables

New-Variable -Name doc -Value "$home\documents"

#PS_Drives

New-PSDrive -Name Mod -Root ($env:PSModulePath -split ';')[0] `

 -PSProvider FileSystem | out-null

#Commands

Set-Location c:\

If(tch) {Start-Transcript -Path (Join-Path -Path `

 $doc -ChildPath $(Get-TranscriptName))}

That is all there is to using Windows PowerShell to create a sortable file name. Profile Week will continue tomorrow when I will talk about more cool stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

Comments (4)

  1. ISO 8601 guy says:

    An alternative approach to a sortable filename that does not require the extraction and replacement of invalid characters would be to create the string in the desired format, along the following lines:

    Get-Date -Format "yyyy-MM-ddTHH-mm-ss"

    Information on the date formatting patterns is available at
    https://msdn.microsoft.com/en-us/library/system.globalization.datetimeformatinfo%28VS.85%29.aspx .

  2. Larry Weiss says:

    You need to also apply the invalid character replacement on the value of $env:COMPUTERNAME

  3. Tommy Becker says:

    It looks like when you are in an elevated session, you don’t get a $home …

  4. Florian Frank1991 says:

    @Tommy

    I tested it in a elevated console:

    PS C:WINDOWSsystem32> $home
    C:UsersFlorian

Skip to main content