Tag Archives: PSMonday

PSMonday #18: Monday, August 29, 2016

Topic: Get-Member

Notice: This post is a part of the PowerShell Monday series — a group of quick and easy to read mini lessons that briefly cover beginning and intermediate PowerShell topics. As a PowerShell enthusiast, this seemed like a beneficial way to ensure those around me at work were consistently learning new things about Windows PowerShell. At some point, I decided I would share these posts here, as well. Here’s the PowerShell Monday Table of Contents.

In a previous PowerShell Monday — before the seven consecutive weeks of PowerShell remoting — we concatenated the strings ‘5’ and ‘5’ (as ‘5’ + ‘5’) to return ’55’. Additionally, we added the numeric values 5 and 5 (as 5 + 5) to return 10. The problem is that without the command that created the result, we don’t know which result is a string, and which is a numeric value.

55

10

If you’re not using the Get-Member cmdlet, then it’s time you start. The Get-Member cmdlet returns the members of an object. It’s important to know that nearly everything in PowerShell is an object. It’s not terribly difficult to understand, and it’s my belief that Get-Member is one of the three most important, introductory PowerShell cmdlets.

Here’s the thing about objects: They have members. Two of the most common members are properties and methods. Properties are attributes, or things that describe the object. If a person was an object, then the properties might be height, hair color, and toe count. Methods are things the object can do. If a person was an object, then the methods might be jump, run, sleep, and swim. I’ve read about a bicycle being used to explain an object’s properties and methods, too. A bike’s properties might be the chain, the handle bar, and tires. The methods might be brake (or stop), bunny hop, and turn.

Keep this in mind as we further explore objects and the Get-Member cmdlet next week.

PSMonday #17: Monday, August 22, 2016

 Topic: PowerShell Remoting Continued VI

Notice: This post is a part of the PowerShell Monday series — a group of quick and easy to read mini lessons that briefly cover beginning and intermediate PowerShell topics. As a PowerShell enthusiast, this seemed like a beneficial way to ensure those around me at work were consistently learning new things about Windows PowerShell. At some point, I decided I would share these posts here, as well. Here’s the PowerShell Monday Table of Contents.

If you’re done reading about PowerShell Remoting, then you’ll be glad to know that we’re wrapping it up this week with one final conversation. Today we’ll discuss implicit remoting. I recently read some Microsoft written, PowerShell documentation where they indicated this was an advanced topic. If you’ve been following along over the last several weeks, then as far as I’m concerned, you’re ready. You ought to know a good deal about PS Remoting by now.

Let’s start by considering that we have a PowerShell module called Test on a remote computer called SERVER01. Inside the module are three functions: Write-One, Write-Two, and Write-Three. When invoked, each function will echo the name of the computer where the function is running and then echo either “One!,” “Two!,” or “Three!” Here’s a quick look at the module.

psmonday-17-monday-august-22-2016-01

As we’ve seen before, we can use Enter-PSSession to interactively connect and run any of the functions. We can also use Invoke-Command to run the functions on the remote computer and then return the results. In the implicit remoting option, we’ll create a new PSSession to a remote computer, such as we did last week, and then bring the functions to our local computer.

$Session = New-PSSession -ComputerName SERVER01
Import-PSSession -Session $Session -Module Test

ModuleType Version Name             ExportedCommands
---------- ------- ----             ----------------
Script     1.0     tmp_jfhp0hhd.hk5 {Write-One, Write-Three, Write-Two}

By default, Import-PSSession will return output to include the ModuleType, the version, the local, temporary name it’s using for the module, and the exported commands as seen in the above results. These exported commands are the functions in the module, as you can easily tell. To hide this output, you can pipe the Import-PSSession command to Out-Null, as seen in the below example. It’ll do the same work, but without the output.

Import-PSSession -Session $Session -Module Test | Out-Null

While the temporary module now resides on our computer, it still runs the functions on the remote computer.

Write-One
Write-Two
Write-Three

SERVER01
One!
SERVER01
Two!
SERVER01
Three!

Well, there we go. I think we’ve covered a fair amount of information on PowerShell Remoting. We’ll pick up with something new next week, but don’t be surprised if upcoming topics include PS Remoting in one way, or another. It’s a widely used option, when using PowerShell for remote management.

PSMonday #16: Monday, August 15, 2016

Topic: PowerShell Remoting Continued V

Notice: This post is a part of the PowerShell Monday series — a group of quick and easy to read mini lessons that briefly cover beginning and intermediate PowerShell topics. As a PowerShell enthusiast, this seemed like a beneficial way to ensure those around me at work were consistently learning new things about Windows PowerShell. At some point, I decided I would share these posts here, as well. Here’s the PowerShell Monday Table of Contents.

I think back on the last few weeks and there’s a few things we haven’t covered. Let’s say we have four servers and we want to run the same command on each one. We know we can use Invoke-Command and supply four names as the value to the -ComputerName parameter. Jump back to PSMonday #11 on July 11, 2016, for an example.

In today’s PSMonday, we’ll see how to do this another way. We’ll start by creating four PS Remoting sessions. Each session object will hold the session information for an opened session with a remote computer. Displaying the value stored in the variable $Session includes the ConfigurationName property. In the below example, you can see it’s the default endpoint — Microsoft.PowerShell — we discussed last week.

$Session = New-PSSession -Computer DC01,DC02,DC03,DC04
$Session

Id Name           ComputerName    State         ConfigurationName     Availability
-- ----           ------------    -----         -----------------     ------------
4 Session4        DC04            Opened        Microsoft.PowerShell     Available
3 Session3        DC03            Opened        Microsoft.PowerShell     Available
2 Session2        DC02            Opened        Microsoft.PowerShell     Available
1 Session1        DC01            Opened        Microsoft.PowerShell     Available

With these sessions stored in the variable $Session, we can use Invoke-Command and the -Session parameter to run commands against each computer. Here’s a slightly modify version from that previous PSMonday.

Invoke-Command -Session $Session -ScriptBlock {"**** $env:COMPUTERNAME ****"}

**** DC02 ****
**** DC04 ****
**** DC01 ****
**** DC03 ****

One benefit of using sessions is speed while running the commands against the remote computer. It’ll be marginable, until you have a good number of computers as a part of your session variable. The reason there’s a boost in speed is because you already have currently existing sessions to use. Invoke-Command doesn’t have to create sessions, and then destroy them, when it’s done. I should note that it still takes time to create the sessions prior to using them.

Another benefit is when you need to run multiple commands against the same computers, but don’t want to do it at the same time. You can connect and collect some data and then connect again later without the need to create a new connection. Think about it, you can create a variable in the session and it will continue to exist. This means your second Invoke-Command can use the variable you created with the first Invoke-Command, command. See the below example.

$Session = New-PSSession -ComputerName DC05
Invoke-Command -Session $Session -ScriptBlock {$Var = $env:COMPUTERNAME}
Start-Sleep -Seconds 5
Invoke-Command -Session $Session -ScriptBlock {$Var}

DC05

I think we may be done with PowerShell Remoting. We’ll see.

PSMonday #15: Monday, August 8, 2016

Topic: PowerShell Remoting Continued IV

Notice: This post is a part of the PowerShell Monday series — a group of quick and easy to read mini lessons that briefly cover beginning and intermediate PowerShell topics. As a PowerShell enthusiast, this seemed like a beneficial way to ensure those around me at work were consistently learning new things about Windows PowerShell. At some point, I decided I would share these posts here, as well. Here’s the PowerShell Monday Table of Contents.

When we use PowerShell Remoting, as we have for the last few weeks, we connect to an endpoint, or a session configuration, on a remote computer. It doesn’t matter whether we use Enter-PSSession or Invoke-Command, an endpoint is still required. So it’s been said, the term endpoint and session configuration can be used interchangeably. The Get-PSSessionConfiguration cmdlet allows you to view the endpoints on a computer, as is displayed in the below example.

Get-PSSessionConfiguration

Name          : microsoft.powershell
PSVersion     : 4.0
StartupScript :
RunAsUser     :
Permission    : BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed

Name          : microsoft.powershell.workflow
PSVersion     : 4.0
StartupScript :
RunAsUser     :
Permission    : BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed

Name          : microsoft.powershell32
PSVersion     : 4.0
StartupScript :
RunAsUser     :
Permission    : BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed

Name          : microsoft.windows.servermanagerworkflows
PSVersion     : 3.0
StartupScript :
RunAsUser     :
Permission    : NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed

The default endpoint’s name is Microsoft.PowerShell. This is to say, that if you don’t indicate which endpoint to use when you remotely connect to another computer — and we haven’t in any of these PowerShell Remoting PSMondays — then you’re connecting to this endpoint.

Notice the Permission property on the Microsoft.PowerShell endpoint. This indicates, that by default, a user must have a membership in the local administrators group, or in the Remote Management Users group, to use this endpoint. Simply put, you must have specific permissions to use a PS Remoting endpoint. It’s not something that just anyone can use on your servers by default.

The idea behind constrained endpoints, or JEA (Just Enough Administration) endpoints, as they’re now called, is that you can create your own endpoint, give regular users access to it, have it run as an elevated user (using the RunAsUser property), and limit the cmdlets and functions available in the endpoint. That’s right, we can allow non-administrators the ability to perform tasks as an administrator, without the need to ever elevate the account used to connect to the JEA endpoint. While we won’t go into this any further in a PSMonday — at least I can’t imagine we will — this information may be beneficial to know.

See you next week.

PSMonday #14: Monday, August 1, 2016

Topic: PowerShell Remoting Continued III

Notice: This post is a part of the PowerShell Monday series — a group of quick and easy to read mini lessons that briefly cover beginning and intermediate PowerShell topics. As a PowerShell enthusiast, this seemed like a beneficial way to ensure those around me at work were consistently learning new things about Windows PowerShell. At some point, I decided I would share these posts here, as well. Here’s the PowerShell Monday Table of Contents.

Last week, we discussed how to get a locally created variable into a PS Remoting session, by taking advantage of the Using scope modifier — a feature that was added in Windows PowerShell 3.0. Today, we’ll go over how we did it in earlier versions.

In PowerShell 2.0 the Using scope modifier didn’t yet exist. To get locally declared variables into a PS Remoting session took a bit more work. Below are two examples, beginning with the most preferred, first.

The first below example requires the use of the Param block inside the value provided to Invoke-Command’s -ScriptBlock parameter. It also requires the use of Invoke-Command’s -ArgumentList parameter. The $LocalVariable was set last week with the name of the local computer. This time, we’ll take two variables into the PS Remoting session, right after we define the $Date variable. I’ve added a couple blank lines inside the script block, to make things a bit easier to read.

$Date = Get-Date

Invoke-Command -ComputerName MEMSRV01 -ScriptBlock {
    Param($String1,$String2)

    "The local computer is $String1."
    "The local recorded date and time is $String2."
    "The remote computer is $env:COMPUTERNAME."

} -ArgumentList $LocalVariable,$Date

The local computer is TOMMYSPC.
The local recorded date and time is 07/30/2016 09:30:50.
The remote computer is MEMSRV01.

So we’re sure we know what happened here, $LocalVariable went to the remote session and became the value provided to $String1, and $Date was the value provided to $String2.

Our final example uses the $args variable without the need for the Param block. It still requires the -ArgumentList parameter, however. Although this method requires a little less work, using the $args variable can become confusing and so this option should be saved for last. Realistically, it should never be used, as you can always use the above example when you’re working with PowerShell 2.0.

Invoke-Command -ComputerName MEMSRV01 -ScriptBlock {

    "The local computer is $($args[0])."
    "The local recorded date and time is $($args[1])."
    "The remote computer is $env:COMPUTERNAME."

} -ArgumentList $LocalVariable,$Date

The local computer is TOMMYSPC.
The local recorded date and time is 07/30/2016 09:30:50.
The remote computer is MEMSRV01.

And that’s how we get our local variables into our PS Remoting sessions, if the Using scope modifier isn’t an option.

PSMonday #13: Monday, July 25, 2016

Topic: PowerShell Remoting Continued II

Notice: This post is a part of the PowerShell Monday series — a group of quick and easy to read mini lessons that briefly cover beginning and intermediate PowerShell topics. As a PowerShell enthusiast, this seemed like a beneficial way to ensure those around me at work were consistently learning new things about Windows PowerShell. At some point, I decided I would share these posts here, as well. Here’s the PowerShell Monday Table of Contents.

We’re not done yet; there’s more to discuss about PowerShell Remoting and specifically the Invoke-Command cmdlet. Again, this is the cmdlet that allows us to run a command, or a series of commands, against a remote computer, or group of remote computers. It does all this without the need for us to interactively type commands on the remote computer(s).

One of the things you may eventually need to accomplish is to get a local variable from your local computer, into a PS Remoting session. Let’s start by creating a local variable. In the below example, we create and assign $LocalVariable and echo its value.

PS > $LocalVariable = $env:COMPUTERNAME
PS > $LocalVariable

TOMMYSPC

We’re going to utilize the Using scope modifier to get this variable to the remote computer. The Using scope modifier was introduced in PowerShell 3.0, and it is the preferred and easiest way to accomplish this task. That version of PowerShell shipped inbox with Windows 8 and Server 2012; however, it could be installed on some down-level versions of Windows (2008 R2 and Windows 7).

Now that we have our local variable set, let’s take it to our remote computer. We reference the local variable in the PS Remoting session, by inserting “Using:” in-between the dollar sign and the variable name.

PS > Invoke-Command -ComputerName MEMSRV01 -ScriptBlock {
    "The local computer is $Using:LocalVariable."
    "The remote computer is $env:COMPUTERNAME."
}

The local computer is TOMMYSPC.
The remote computer is MEMSRV01.

That’s it for now. We’ll continue with this topic next week where we’ll discuss how this was completed prior to PowerShell 3.0, and the Using scope modifier.

PSMonday #12: Monday, July 18, 2016

Topic: PowerShell Remoting Continued

Notice: This post is a part of the PowerShell Monday series — a group of quick and easy to read mini lessons that briefly cover beginning and intermediate PowerShell topics. As a PowerShell enthusiast, this seemed like a beneficial way to ensure those around me at work were consistently learning new things about Windows PowerShell. At some point, I decided I would share these posts here, as well. Here’s the PowerShell Monday Table of Contents.

Last week was our initial discussion of PowerShell Remoting (PS Remoting). As it’s so necessary, I figured we’d keep with it for at least another week. Previously we used Invoke-Command to run a single command on a few remote computers. Let’s start today, by switching this around and sending a few commands, to a single, remote computer.

In this example, we start in section 1 (listed as <#1#>), by echoing the computer’s name, just as we did in last week’s PSMonday. In section 2, we assign the results of two mildly different commands to the $Folders and $FolderCount variables. $Folders will store the names of the directories on the current root drive, separated by commas. $FolderCount will store the number of directories on the current root drive. Once those variables are populated, we then echo their values, as part of two separate strings, in section 3.

Invoke-Command -ComputerName MEMSRV01 -ScriptBlock {
    <#1#>"**** $env:COMPUTERNAME ****"

    <#2#>$Folders = (Get-ChildItem -Path \ -Directory) -join ', '
    $FolderCount = (Get-ChildItem -Path \ -Directory).Count

    <#3#>"Root Drive Folders : $Folders"
    "Root Drive Folder Count : $FolderCount"
}

**** MEMSRV01 ****
Root Drive Folders : inetpub, PerfLogs, Program Files, Program Files (x86), support, Users, Windows
Root Drive Folder Count : 7

There is an option to assign the script block to a variable, and then use the variable as part of the Invoke-Command command. This might make the code a bit more readable. Here’s an example.

$ScriptBlock = {
    "**** $env:COMPUTERNAME ****"

    $Folders = (Get-ChildItem -Path \ -Directory) -join ', '
    $FolderCount = (Get-ChildItem -Path \ -Directory).Count

    "Root Drive Folders : $Folders"
    "Root Drive Folder Count : $FolderCount"
}

Invoke-Command -ComputerName MEMSRV01 -ScriptBlock $ScriptBlock

Either way you do it, these script blocks still have the potential to become rather lengthy. In this case, we might consider the -FilePath parameter. Instead of the -ScriptBlock parameter and a script block, Invoke-Command will read in the contents of a .ps1 file and run that against the remote computer.  Here’s the same code as above, that’s been saved as C:\ICMTestFile.ps1.

psmonday-12-monday-july-18-2016-01

With this file in place, we’ll rerun the previous commands using the -FilePath parameter and the path to the file as the parameter value.

Invoke-Command -ComputerName MEMSRV01 -FilePath C:\ICMTestFile.ps1

**** MEMSRV01 ****
Root Drive Folders : inetpub, PerfLogs, Program Files, Program Files (x86), support, Users, Windows
Root Drive Folder Count : 7

As you begin to use Invoke-Command and want to run more and more commands, keep this option in mind. Now, with that said, I think it’s important to know that I don’t personally see the -FilePath option used much. Consider why. When writing your own scripts and functions, or reading someone else’s, you’ll have to go outside of the script or function file to view what Invoke-Command is doing, and that could become tiresome, and difficult when troubleshooting.

PSMonday #11: Monday, July 11, 2016

Topic: PowerShell Remoting

Notice: This post is a part of the PowerShell Monday series — a group of quick and easy to read mini lessons that briefly cover beginning and intermediate PowerShell topics. As a PowerShell enthusiast, this seemed like a beneficial way to ensure those around me at work were consistently learning new things about Windows PowerShell. At some point, I decided I would share these posts here, as well. Here’s the PowerShell Monday Table of Contents.

When Windows PowerShell 2.0 was released, it came with some welcoming new features. One of the biggest, was PowerShell Remoting. Let’s discuss PS Remoting in regard to two cmdlets: Enter-PSSession and Invoke-Command.

Enter-PSSession allows for a fully interactive PowerShell remoting session. It’s as though you’re sitting at the PowerShell prompt on the remote computer, with the ability to interactively enter commands and immediately see those results. Using Enter-PSSession is considered one-to-one PS Remoting. Here’s an example of using Enter-PSSession with the explanation beneath that.

Enter-PSSession -ComputerName DC01

[DC01]: PS C:\Users\tommymaynard\Documents> Set-Location -Path \
[DC01]: PS C:\> "**** $env:COMPUTERNAME ****"
**** DC01 ****
[DC01]: PS C:\> Exit-PSSession
PS C:>

Let’s discuss each of the above lines in this example. The first line is the command we used to connect to the DC01 computer. Once connected, we move to the root of the drive using the Set-Location cmdlet. This isn’t a requirement, but a shorter path will offer more area in which to type. Then, we instructed the computer to echo four asterisks, a space, the value stored in the computer name environmental variable, another space, and another four asterisks. This is proof, outside the computer’s name in square brackets at the left of the prompt, that we really are on the remote computer. Finally, we run Exit-PSSession to exit the PS Remoting session on DC01, and return to the local computer.

Invoke-Command allows you to send a command to a remote computer, have it run, and have the results sent back and displayed in your console, on the local computer. While you can do this against a single computer, this is considered one-to-many PS Remoting, and you’ll see why momentarily. The next example does the same thing as we did in the above, Enter-PSSession example.

Invoke-Command -ComputerName DC01 -ScriptBlock {"**** $env:COMPUTERNAME ****"}

**** DC01 ****

Invoke-Command has some great features: One, it can run against multiple computers, as you may have already picked up on, or simply knew, and two, it can do this at the same time. Now, there is a built-in limitation of 32 computers that it will run against at once; however, that can be changed with the -ThrottleLimit parameter and a parameter value of something other than 32.

Invoke-Command -ComputerName DC01,DC02,DC03,DC04 -ScriptBlock {"**** $env:COMPUTERNAME ****"}

**** DC01 ****
**** DC04 ****
**** DC02 ****
**** DC03 ****

Because this last example ran against multiple computers at once, you won’t always get the results back in the order you might expect. This is because it’s up to how quickly each computer can be reached, how quickly each command(s) can be run, and how quickly each computer can send the results back to the local computer. This command above could’ve been written as is shown below.

Invoke-Command -ComputerName (Get-ADDomainController -Filter *) -ScriptBlock {"**** $env:COMPUTERNAME ****"}

**** DC01 ****
**** DC02 ****
**** DC04 ****
**** DC03 ****

Start to consider all those times you use Remote Desktop. Are there times you can skip that somewhat lengthy process, and instead return the results you’re after, using PowerShell Remoting?

PSMonday #10: Monday, July 4, 2016

Topic: Less Used Variable Properties Continued II

Notice: This post is a part of the PowerShell Monday series — a group of quick and easy to read mini lessons that briefly cover beginning and intermediate PowerShell topics. As a PowerShell enthusiast, this seemed like a beneficial way to ensure those around me at work were consistently learning new things about Windows PowerShell. At some point, I decided I would share these posts here, as well. Here’s the PowerShell Monday Table of Contents.

Last week we discussed the option of making our variables read-only. This means that without the -Force parameter, read-only variables cannot be overwritten, cleared, or deleted. This level of protection for our variable’s values is good, but it might not be the best option in some cases. Today we’ll focus on the constant option for the Options property. Let’s first create a new variable, verify it’s a constant, and then try to change its value.

New-Variable -Name String6 -Value "Here’s a new Monday variable." -Option Constant

(Get-Variable -Name String6).Options
Constant

Set-Variable -Name String6 -Value 'Can we change it?'

Set-Variable : Cannot overwrite variable String6 because it is read-only or constant.

As mentioned, with a read-only variable, we used the -Force parameter to overwrite, clear, and delete, and it worked. Let’s try that with our constant variable.

Set-Variable -Name String6 -Value ‘Can we change it?' -Force

Set-Variable : Cannot overwrite variable String6 because it is read-only or constant.

Even with the -Force parameter we can’t change the variable’s value. Let’s attempt to clear it (remove its value), with the -Force parameter.

Clear-Variable -Name String6 -Force

Clear-Variable : Cannot overwrite variable String6 because it is read-only or constant.

No luck. In both cases we get the same error. Let’s try to remove the variable in its entirety.

Remove-Variable -Name String6 -Force

Remove-Variable : Cannot remove variable String6 because it is constant or read-only. If the variable is read-only, try the operation again specifying the Force option.

Still no luck, although we did get a mildly different message. If you create a variable that’s a constant, you can’t get rid of it, or modify it, until you end the PowerShell session; however, if it’s read-only, you’ll have some protection, and still be able to modify things, if necessary. Keep these options in mind, as you may find yourself wanting to add some protection, to your otherwise do-anything-you-want-to-them-at-any-time variables.

Bonus: Last week we saw that we were able to create a variable and then make it read-only. When we create a constant variable, the option has to be applied when the variable is first created. If you create a variable and then try to make it constant, you’ll receive the below error.

Set-Variable : Existing variable String7 cannot be made constant. Variables can be made constant only at creation time.

PSMonday #9: Monday, June 27, 2016

Topic: Less Used Variable Properties Continued I

Notice: This post is a part of the PowerShell Monday series — a group of quick and easy to read mini lessons that briefly cover beginning and intermediate PowerShell topics. As a PowerShell enthusiast, this seemed like a beneficial way to ensure those around me at work were consistently learning new things about Windows PowerShell. At some point, I decided I would share these posts here, as well. Here’s the PowerShell Monday Table of Contents.

As was mentioned last week, variables have some properties we don’t often use, and many of us, may not even know about them. Last week we briefly learned about the Description property of a variable, and today, we’ll start to learn about the Options property.

While a variable’s Options property is set to None by default, there’s at least two other possibilities, and one of them, is ReadOnly. The first example uses New-Variable to create a new, read-only variable named String3, and Get-Variable and Select-Object to return all the variable’s properties.

New-Variable -Name String3 -Value 'A new week; another Monday.' -Option ReadOnly

Get-Variable -Name String3 | Select-Object *

Name        : String3
Description :
Value       : A new week; another Monday.
Visibility  : Public
Module      :
ModuleName  :
Options     : ReadOnly
Attributes  : {}

Now, what does it mean that it’s read-only? It means that we can’t change the value that’s stored by the variable, as is indicated below.

Set-Variable -Name String3 -Value 'A new week; another Friday!'

Set-Variable : Cannot overwrite variable String3 because it is read-only or constant.

Notice in the error message that it indicates we can’t overwrite the variable because the variable is read-only or constant. It turns out that we actually can change the value stored in a read-only variable, if we use the -Force parameter.

Set-Variable -Name String3 -Value 'We Want Friday!' -Force

Get-Variable -Name String3 | Select-Object *

Name        : String3
Description :
Value       : We Want Friday!
Visibility  : Public
Module      :
ModuleName  :
Options     : ReadOnly
Attributes  : {}

So, in the end, a read-only variable can be overwritten if absolutely necessary. Keep this read-only option in mind as you create variables in Windows PowerShell. There may be times you create variables and want to mostly protect the original, stored value. In that case, you can choose to make them read-only.

If we already have a variable created, how do we then make it read-only? We have to use Set-Variable, whether we created the variable with New-Variable, or the standard way, as is used below.

$String4 = 'Last variable for today.'
$String4

Last variable for today.

(Get-Variable -Name String4).Options
None

Get-Variable -Name String4 | Set-Variable -Option ReadOnly

(Get-Variable -Name String4).Options
ReadOnly

To clear a variable’s value (to continue to allow a variable to exist, but to remove the value it stored), we have to use the -Force parameter. Same goes for removing the entire variable; that will also require the -Force parameter if it’s a read-only variable.

Clear-Variable -Name String3 -Force

Remove-Variable -Name String4 -Force