Tag Archives: Write-Warning

To Rename a PowerShell Variable

I had one of those thoughts…  you know, a dumb one. As dumb as it might be, it gave some brief inspiration to try something new. It seemed possible and easy enough and so I set out to prove, that as dumb (and useless), as it is, that it could be mine.

First off, on my machine, as it sits here today, I have 40 commands that include the “rename” verb. Additionally, I have five commands that include the “Variable” noun. Do you know what I do not have, though? I will tell you in a second if you have not figured it out yet. If you have figured it out, I will also tell you.

[PS7.2.1][C:\] Get-Command -Verb Rename | Measure-Object | Select-Object -Property Count

Count
-----
   40

[PS7.2.1][C:\] Get-Command -Noun Variable | Measure-Object | Select-Object -Property Count

Count
-----
    5

A Rename-Variable command. And you know why!? Because it is dumb and mostly useless. Regardless, I made it a thing and we will discuss it during this post. In the end, I think it turned out to be a success even though I will never use it again after today. That is what I say now, anyway.

Let’s do this in reverse. We will start with the commands I will invoke and then we will look at my function. My first below command Rename-Variable will send in the variable named TestVariableZero and the name to which we want to rename it, TestVariableZeroZero. This will not work, as we cannot rename a variable that does not yet exist. The function will use Write-Warning to inform us that it cannot be renamed. I could have used this section of the if-else to create the variable, but that is not today’s assignment. The next two lines will one, create the variable TestVariableOne with the value ValueOne and two, return information about the variable, so we know it has been created.

We are using the Force parameter in the first of these two commands in case the variable already exists. New-Variable cannot create a variable that already exists by default.

Rename-Variable -Name TestVariableZero -NewName TestVariableZeroZero

New-Variable -Name TestVariableOne -Value ValueOne -Force
Get-Variable -Name TestVariableOne

Rename-Variable -Name TestVariableOne -NewName TestVariableTwo

Get-Variable -Name TestVariableTwo
Get-Variable -Name TestVariableOne

Looking upward, we have three more commands to discuss. This Rename-Variable command will attempt to rename the TestVariableOne variable to TestVariableTwo. After that operation, we have two Get-Variable commands. The first will prove that we now have a TestVariableTwo variable and the second, that we no longer have a TestVariableOne variable. How fun right,… even though renaming a variable should not require its own command. With that, let’s take a look at the function.

function Rename-Variable {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory)]
        $Name,
        [Parameter(Mandatory)]
        $NewName
    )

    if (Get-Variable -Name $Name -Scope Global -ErrorAction SilentlyContinue) {
        Set-Variable -Name $NewName -Value (Get-Variable -Name $Name -ValueOnly -Scope Global) -Scope Global
        Remove-Variable -Name $Name -Scope Global
    }
    else {
        Write-Warning -Message "Unable to locate a variable with the name of $Name."
    }
}

You will be glad to know that not a lot of work went into writing this; it is very simple and very straightforward. Our function accepts two parameters: Name and NewName. Simple. We use Name to search for our existing variable and NewName to change its name. Notice the use of the -Scope Global parameter and parameter value. Without it, the variables that we would be working with inside the function would only be scoped to the function; they would not exist outside of the function. Providing the variable exists, we use Set-Variable inside the function to create a new/set an existing variable with the new name and take the value from the old variable and assign it as the value to the new variable. Once the new variable has been created and the old value assigned to it, we remove the previously named variable. Let’s try out the commands we saw at the beginning of this post.

Here is what happens when we try and rename a variable that does not exist.

[PS7.2.1][C:\] Rename-Variable -Name TestVariableZero -NewName TestVariableZeroZero
WARNING: Unable to locate a variable with the name of TestVariableZero.

So we can test out our function, let’s create our TestVariableOne variable and prove to ourselves that it has been created and that it now exists.

[PS7.2.1][C:\] New-Variable -Name TestVariableOne -Value ValueOne -Force
[PS7.2.1][C:\] Get-Variable -Name TestVariableOne

Name                           Value
----                           -----
TestVariableOne                ValueOne

Now, it is time to rename our variable from TestVariableOne to TestVariableTwo. The first command does just that. The next couple of commands proves that TestVariableTwo now exists with the proper value and TestVariableOne does not exist.

[PS7.2.1][C:\] Rename-Variable -Name TestVariableOne -NewName TestVariableTwo
[PS7.2.1][C:\] Get-Variable -Name TestVariableTwo

Name                           Value   
----                           -----   
TestVariableTwo                ValueOne

[PS7.2.1][C:\] Get-Variable -Name TestVariableOne
Get-Variable: Cannot find a variable with the name 'TestVariableOne'.

And that is it. If you are ever looking to rename a variable, using a built-in -Variable command, you are not going to find it. You can roll your own, however, if you really want to do that.

Copy the Last Command to the Clipboard

As a PowerShell blogger, I’ll often write a command in the PowerShell ConsoleHost and then, after it’s been executed, want to copy it out and paste it into a post. What this typically means is that I’ll press the up arrow to recall the last command — the one I want — and then selectively highlight the code I want and right-click to copy. Inevitably, I’ll end up copying my prompt and other unwanted lines, or parts of lines, and have to clean that up once it’s been pasted elsewhere.

Well, with a quick minute, those days are over. Type the function name Copy-LastCommand (once the function is in your PowerShell session), press Enter, and boom, the last command you entered is on the clipboard and ready to go elsewhere. Simple. Now all I do, is paste it where I want it and save myself some seconds. They add up.

Function Copy-LastCommand {
    (Get-History (Get-History | Select-Object -Last 1).Id).CommandLine | clip
}

Update: I made some changes to this little function and need to share those. Something I didn’t consider right away, was what happens if there isn’t a last command to copy? This is to say, what if the Copy-LastCommand is the first command entered into someone’s PowerShell session? Well, it won’t have anything to copy. I’ve added a fix for those times — a simple Write-Warning command. I also edited this to work using the newer, Set-Clipboard, cmdlet that was introduced in PowerShell 5.1 (I believe).

Function Copy-LastCommand {
    If (Get-History) {
        If ($PSVersionTable.PSVersion.ToString() -match '5.1') {
            Set-Clipboard -Value (Get-History (Get-History | Select-Object -Last 1).Id -ErrorAction SilentlyContinue).CommandLine
        } Else {
            (Get-History (Get-History | Select-Object -Last 1).Id).CommandLine | clip
        }
    } Else {
        Write-Warning -Message 'No command history to copy.'
    }
}