Weekend Scripter: Replace One PowerShell Function with Another

Doctor Scripto

Dr Scripto

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

Doctor Scripto
Dr Scripto

Scripter, PowerShell, vbScript, BAT, CMD

Follow Dr Scripto   

0 comments

    Leave a comment