Category Archives: Quick Learn

Practical examples of PowerShell concepts gathered from specific projects, forum replies, or general PowerShell use.

PSMonday #21: Monday, September 19, 2016

Topic: Get-Member Continued III (and Arrays)

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.

At this point, we’ve only ever piped to the Get-Member cmdlet, but there’s times we might want to use the cmdlet differently. Before we continue, we need to understand arrays, and so we’re going to break off from Get-Member this week.

In our previous examples, we’ve typically only assigned a single value to a variable.

$a = 'dog'
$a

dog

Using an array allows us to assign multiple values to a single variable. Here’s how we do that, and how it appears when we return the variable’s newly assigned values.

$b = 'dog','cat','bird','frog'
$b

dog
cat
bird
frog

You may see arrays created using the array operator syntax, as well: @().

$b = @('dog','cat','bird','frog')

We can access each of the values in the array variable using an index. This is the position of a value within the array. Arrays are always zero-based, so the first value in the array is always at index 0.

$b[0]

dog

Now let’s return all four values. We’ll do them out of order, so you can see that the indexes really do, return the proper value in the array.

$b[3] # 4th value.
$b[0] # 1st value.
$b[2] # 3rd value.
$b[1] # 2nd value.

frog
dog
bird
cat

We’ve learned that the array index 0 and then higher, each represent the next value in the array. We can also move backwards through an array, using negative indexes. Here’s both.

$b[0]
$b[1]
$b[2]
$b[3]
'--------'
$b[-1]
$b[-2]
$b[-3]
$b[-4]

dog
cat
bird
frog
--------
frog
bird
cat
dog

This means that index [-1] is always the last value in an array, just like index [0] will always be the first. Knowing this may come in handy one day; it was for me. Next Monday, we’ll actually get back to Get-Member, now that we have some basic understanding of arrays, if you didn’t have them already.

PSMonday #20: Monday, September 12, 2016

Topic: Get-Member 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.

Back to Get-Member and some experimentation with a few methods. We’ll start by using a method that I didn’t include in my shortened results last week: PadLeft. The PadLeft method will add spaces, by default, to the left side of a string. Remember, “methods are things the object can do.”

$x = '5' + '5'
$x

55

$x.PadLeft(5)

   55

A little boring, so let’s pad it with asterisks instead.

$x.PadLeft(5,'*')

***55

You might have expected to see five asterisks. Nope. The PadLeft method indicates that any space to the left of the existing string be padded up to five total spaces, to include the string itself. So, how might we ensure there’s five asterisks before the string, if that’s what we had really wanted? Think back to the string’s length from last week. Here’s that example again.

$x.Length

2

In the next example, we’ll add five to the length (two), in order to ensure we end up with five, actual asterisks.

$x.PadLeft(5 + $x.Length,'*')

*****55

Here’s another example with a different string and method. This uses the Split method to split a string on the space between each word.

"Today is everyone's favorite day!".Split(' ')

Today
is
everyone's
favorite
day!

I should mention that the above, split example should’ve been written like it is below. The default split character is the space; it doesn’t need to be included. Now, if we had opted to split on a different character, word, or combination thereof, that would’ve needed to be included inside the single quotes.

"Today is everyone's favorite day!".Split()

We’ll stop here for now and pick it up next Monday.

PSMonday #19: Monday, September 5, 2016

Topic: Get-Member 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.

If nearly everything in PowerShell is an object, then let’s look at two of the members — properties and methods — of our two results, ’55’ and 10. Typically, we pipe to Get-Member. In the first example, we’ll recreate our string value of ’55’ and see what we can learn about it.

$x = '5' + '5'
$x

55

$x | Get-Member

  TypeName: System.String

In the above results, I’ve included only the TypeName of the object for now, and haven’t yet included all the properties and methods returned by Get-Member, that we’ll see momentarily. The TypeName indicates that the object is a string object.

In the more complete, Get-Member results, I’ve included the first several methods and the one and only property. As the value in $x is a string, there’s not much to it, property wise. In this case, there’s just a length property. In the below results, I haven’t include the Definition property. If you run these commands yourself, don’t be surprised to see a third property, or column, included.

  TypeName: System.String

Name             MemberType
----             ----------
Clone            Method
CompareTo        Method
Contains         Method
CopyTo           Method
EndsWith         Method
Equals           Method
GetEnumerator    Method
GetHashCode      Method
...
Length           Property

Let’s return the length property to see the length of the string stored in the variable $x. The value is ’55’, so a length of two would make sense. Let’s double-check.

$x.Length

2

Let’s recreate our numeric value of 55, as well, and pipe it to Get-Member.

$y = 5 + 5
$y

10

$y | Get-Member

  TypeName: System.Int32

Name           MemberType
----           ----------
CompareTo      Method
Equals         Method
GetHashCode    Method
GetType        Method
GetTypeCode    Method
ToBoolean      Method
ToByte         Method
ToChar         Method
ToDateTime     Method
ToDecimal      Method
ToDouble       Method
ToInt16        Method
ToInt32        Method
ToInt64        Method
ToSByte        Method
ToSingle       Method
ToString       Method
ToType         Method
ToUInt16       Method
ToUInt32       Method
ToUInt64       Method

The variable $y is storing an integer object, and according to Get-Member, doesn’t include any properties. That’s a good start for this holiday Monday. Next week, we’ll start working with some of the different methods.

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.

Handle a Parameter Whether it’s Included or Not

I’m in the process of writing a new tool. It’s basically a wrapper function for Get-ADObject that only returns Active Directory (AD) contact objects. While there’s a Get-ADComputer cmdlet to get AD computer objects, and a Get-ADUser cmdlet to get AD user objects, there’s no specific cmdlet for contacts. There’s no surprise here really, and that’s likely why we have a Get-ADObject cmdlet. It’s for those AD objects that didn’t make the cut and get their own.

I’ve seen some discussion on this in the past: How do I handle running a cmdlet within a function when I don’t know if a parameter and parameter value will be included, or not? Let’s consider that my Get-ADContact function will run the Get-ADObject cmdlet, as seen below. In the Begin block, we create a $Parameter variable that will hold a hash table. We’ll populate it in such a way that the key Filter will have a corresponding value of {ObjectClass -eq ‘contact’}. In the Process block, we splat this hash table, currently with a single parameter and parameter value, to the Get-ADObject cmdlet.

Function Get-ADContact {
    [CmdletBinding()]
    Param (
    )

    Begin {
        # Create parameter hash table; add Filter parameter.
        $Parameters = @{Filter = {ObjectClass -eq 'contact'}}
    } # End Begin.

    Process {
        Get-ADObject @Parameters
    } # End Process.

    End {
    } # End End.
} # End Function: Get-ADContact.

There’s two other parameters included in Get-ADObject that I want to allow my users the ability to include. That’s the -SearchBase and -SearchScope parameters. You can read more by checking the help for Get-ADObject: Get-Help -Name Get-ADObject. There’s actually several AD cmdlets that also include these parameters. They can be quite helpful, so that’s why I’ve decided to include them.

Before we continue, I want to let the audience know that I am familiar with creating proxy functions, and I understand it might’ve been a better option. Maybe I’ll circle back sometime and see about replicating the functionality I’ve created here, in that manner. It might turn out this wasn’t worth writing and posting. No guarantee, but it’s possible.

Okay, back on track. Let’s add the additional lines inside the Param block, that make accepting a -SearchBase and -SearchScope parameter value possible.

Function Get-ADContact {
    [CmdletBinding()]
    Param (
        [Parameter()]
        [string]$SearchBase,

        [Parameter()]
        [ValidateSet(0,'Base',1,'OneLevel',2,'SubTree')]
        $SearchScope
    )

    Begin {
        # Create parameter hash table; add Filter parameter.
        $Parameters = @{Filter = {ObjectClass -eq 'contact'}}
    } # End Begin.

    Process {
        Get-ADObject @Parameters
    } # End Process.

    End {
    } # End End.
} # End Function: Get-ADContact.

Now, our Get-ADContact function will include the two additional parameters. Neither parameter is mandatory, but the -SearchScope parameter does include a ValidateSet parameter attribute to ensure it’ll only accept the values 0, 1, 2, Base, OneLevel, or SubTree. Base and 0 are equivalent, as are 1 and OneLevel, and 2 and SubTree.

The next thing I need to do is include the parameter values assigned to the -SearchBase and -SearchScope parameters to our $Parameters hash table when those are included. I decided to do this using the $PSBoundParameters variable, the ForEach-Object cmdlet, and the switch language construct.

Function Get-ADContact {
    [CmdletBinding()]
    Param (
        [Parameter()]
        [string]$SearchBase,

        [Parameter()]
        [ValidateSet(0,'Base',1,'OneLevel',2,'SubTree')]
        $SearchScope
    )

    Begin {
        # Create parameter hash table; add Filter parameter.
        $Parameters = @{Filter = {ObjectClass -eq 'contact'}}

        $PSBoundParameters.Keys | ForEach-Object {
            Switch ($_) {
                'SearchBase' {$Parameters += @{SearchBase = $SearchBase}; break}
                'SearchScope' {$Parameters += @{SearchScope = $SearchScope}}
            }
        }
    } # End Begin.

    Process {
        Get-ADObject @Parameters
    } # End Process.

    End {
    } # End End.
} # End Function: Get-ADContact.

All done. Now, we have function that only returns AD contact objects. Additionally, we have the option of narrowing down our search by including the often used -SearchBase and -SearchScope parameters. While I don’t doubt there’s a better way, I think this one will work for now.

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.

Format PowerShell Results for Outside of PowerShell

There are times I use PowerShell to help format information I need to send along to others in an email. What I mean is that I return results from PowerShell commands, and format it using PowerShell, so that I can simply send it to the clipboard and paste it into an email.

The below example gathers all the computer-related details about my Lync servers each time I open a new Windows PowerShell session. The time to complete is minimal, so I’m perfectly okay with returning all the properties on each of the servers. The extra milliseconds are worth having the most current information on these servers inside my $Lync variable. By the way, you don’t need to know anything about Lync (or Skype) to make use of the post; it’s not the point.

PS > $Lync = Get-ADComputer -Filter * -SearchBase "OU=Lync,DC=MyDomain,DC=com" -Properties *

With the variable set and assigned, I can do things like the next two, combined examples. This comes in handy all the time, and without the need to think about rewriting the command whenever it’s needed again.

PS > $Lync.Name
L-FE01
L-PC02
L-PC01
L-FE02
L-Ed01
L-FE04
L-FE03
L-Ed02

PS > $Lync | Select-Object Name,Description

Name              Description
----              ----------- 
L-FE01            Lync 2013 Front End
L-PC02            Lync 2013 Persistent Chat
L-PC01            Lync 2013 Persistent Chat
L-FE02            Lync 2013 Front End
L-Ed01            Lync 2013 Edge
L-FE04            Lync 2013 Front End
L-FE03            Lync 2013 Front End
L-Ed02            Lync 2013 Edge

Let’s consider that I need to enter the names of the servers into an email and I want them to be comma separated. Easy, we’ll the use the -join operator to complete this task

PS > $Lync.Name -join ','
L-FE01,L-PC02,L-PC01,L-FE02,L-Ed01,L-FE04,L-FE03,L-Ed02
PS >
PS > # Humm... let's add spaces, too.
PS >
PS > $Lync.Name -join ', ' # <-- Notice the trailing space.
L-FE01, L-PC02, L-PC01, L-FE02, L-Ed01, L-FE04, L-FE03, L-Ed02

Because I’m sold on PowerShell, I’ll always take extra time to use it to its full potential. What I wanted to do was add the word “and” after the last comma and a space, and before the name of the final Lync server. This will make the most sense when my text is dropped into an email and used as, or part of, a sentence. We’ll start this example by determining the location of the last comma by using the .LastIndexOf() method. This returns the location within the string.

PS > $index = (($Lync.Name) -join ', ').LastIndexOf(',')
PS > $index
54

Now that we know the location of the last comma, we can remove it and then insert what we want. The next example uses two methods. First the .Remove() method removes the comma, and then the .Insert() method adds everything the way we want it.

PS > (($Lync.Name) -join ', ').Remove($index,1).Insert($index,', and')
L-FE01, L-PC02, L-PC01, L-FE02, L-Ed01, L-FE04, L-FE03, and L-Ed02
PS >
PS > (($Lync.Name) -join ', ').Remove($index,1).Insert($index,', and') | clip.exe

In the last above line, we reran the command and piped it to clip, so that it’s ready to be pasted into my email. After you do this awhile, you find little ways in PowerShell to handle the exact formatting you want. It’s these little tasks, that will give you an opportunity to continue to practice your PowerShell. And finally, here’s the email where I entered the information I had collected and formatted in PowerShell.

format-powershell-results-for-outside-of-powershell-01

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.