Weekend Scripter: Replace One PowerShell Function with Another


Summary: Ed Wilson, Microsoft Scripting Guy, talks about replacing one Windows PowerShell function with a different one.

Microsoft Scripting Guy, Ed Wilson, is here. One of the problems with writing Windows PowerShell code every day is that you eventually…

No, it’s not what you think.

I am often asked if I run out of ideas, and the answer is, "No, I don’t."

There is so much I can do with Windows PowerShell that, in fact, a new version of Windows PowerShell will be out before I ever run out of ideas of what to do with the last version. No, the problem is not that I run out of ideas, but it is that I often forget what I have written. In fact, this week is a case in point.

Code cleanup

I wrote a cool function that creates a Windows PowerShell transcript log file name from the date. In it, I replace invalid file-name characters. Here is the function:

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]","-") }

There is absolutely nothing in the world wrong with it. It works fine (that is, if I don’t start Windows PowerShell twice in the same second, which on my laptop is virtually impossible to do).

The problem is that I have already written a cool Windows PowerShell function that will remove invalid characters from the file name. So THAT is why I knew about [io.path]::GetInvalidFileNameChars. I didn’t even have to look it up—I remembered it because I have used it before. Here is that function:

Function Replace-InvalidFileCharacters

{

 Param ($stringIn,

        $replacementChar)

 # Replace-InvalidFileCharacters "my?string"

 # Replace-InvalidFileCharacters (get-date).tostring()

 $stringIN -replace "[$( [System.IO.Path]::GetInvalidFileNameChars() )]", $replacementChar

}

It is obvious, that the code is essentially the same, but it has the added advantage that I can use it for any string, not just for the date. So, I decided that I want to add this function to my Windows PowerShell profile and cleanup the Windows PowerShell transcript name function a bit. But how?

How do I bring in this function and cleanup the other function, when the Get-TranscriptName function has the functionality embedded into a rather complex line of Windows PowerShell code?

Add them to a blank page in the ISE

The answer is pretty simple:

I open a new tab in the Windows PowerShell ISE, and I test it out. First I open my Windows PowerShell profile from the Windows PowerShell console by using my function Edit-Profile Windows PowerShell.

Then I add a new blank page to the Windows PowerShell ISE, and I copy the Get-TranscriptName and the Replace-InvalidFileCharacters functions to it. This is shown here:

Image of code

Reduce duplication

Now I need to look at what the Replace-InvalidFileCharacters function does and what I need to have in the Get-TranscriptName function. It is obvious that the key to both functions is the call to GetInvalidFileNameChars static method. So, I can comment out the first line in the Get-TranscriptName function:

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]","-") }

The next thing that the Replace-InvalidFileCharacters function does is call the –Replace operator to replace the invalid characters with the character supplied when the function is called. So I can also replace that line in my Get-TranscriptName function:

Image of code

In the previous image, you can see that the two commands are essentially the same:

-Replace (characters to replace), (character to replace with)

Because the Replace-InvalidFileCharacters function performs the same thing as the code highlighted in the Get-TranscriptName, I can substitute the code in the Get-TranscriptName function with a call to the Replace-InvalidFileCharacters function.

I need to first load the Replace-InvalidFileCharacters function into memory in my Windows PowerShell ISE so I can test it to make sure everything works properly.

The other thing I need to realize is that the (Get-Date).tostring() portion in my Get-TranscriptFileName function will need to be supplied as input to the Replace-InvalidFileCharacters function. So, here is the replacement:

Function Get-TranscriptName

{

 $date = Get-Date -format s

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

  (Replace-InvalidFileCharacters -stringIn $date.ToString() -replacementChar "-") }

Now, in keeping with my tenant that I like to create aliases for my functions, I create a new alias for Replace-InvalidFileCharacters that will be easier to type. I decide to see if RIFC is taken. I test it with Get-Alias:

PS C:\> Get-Alias rifc

Get-Alias : This command cannot find a matching alias because an alias with the name 'rifc' does not exist.

At line:1 char:1

+ Get-Alias rifc

+ ~~~~~~~~~~~~~~

    + CategoryInfo          : ObjectNotFound: (rifc:String) [Get-Alias], ItemNotFoundException

    + FullyQualifiedErrorId : ItemNotFoundException,Microsoft.PowerShell.Commands.GetAliasCommand

It appears to be available, so I add this alias:

Set-Alias -Name rifc -Value Replace-InvalidFileCharacters | out-null

Then I copy the two functions to my Windows PowerShell profile after I replace the long command name. The complete profile is shown here:

#——————————————————————————

#

# 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

Set-Alias -Name gfl -Value Get-ForwardLink | out-null

Set-Alias -Name gwp -Value Get-WebPage | out-null

Set-Alias -Name rifc -Value Replace-InvalidFileCharacters | out-null

#Functions

Function Edit-Profile

{ ISE $profile }

Function Test-ConsoleHost

{

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

 Else {$false}  

}

Function Replace-InvalidFileCharacters

{

 Param ($stringIn,

        $replacementChar)

 # Replace-InvalidFileCharacters "my?string"

 # Replace-InvalidFileCharacters (get-date).tostring()

 $stringIN -replace "[$( [System.IO.Path]::GetInvalidFileNameChars() )]", $replacementChar

}

Function Get-TranscriptName

{

 $date = Get-Date -format s

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

  (rifc -stringIn $date.ToString() -replacementChar "-") }

Function Get-WebPage

{

 Param($url)

 # Get-WebPage -url (Get-CmdletFwLink get-process)

 (New-Object -ComObject shell.application).open($url)

}

Function Get-ForwardLink

{

 Param($cmdletName)

 # Get-WebPage -url (Get-CmdletFwLink get-process)

 (Get-Command $cmdletName).helpuri

}

#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))}

On Monday, I'll wrap up Profile Week, and I'll be talking about adding variable descriptions to my profile. 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 (0)

Skip to main content