0:00
What's up, everyone? Today we're going to talk about variable scope when it comes to Parishel
0:04
We'll talk about the difference between global and script scope and why you can't access variables in different scenarios all the time
0:12
My name is Jeff Brown. You're watching Jeff Brown Tech. Let's go ahead and get started
0:16
As always, this code is available down in my GitHub and I'll include a link to it down in the description below
0:22
To get started, I have just a couple of definitions of different scopes you can expect when working with Parishel
0:27
First, we have a global scope. This is available when you open a PowerShell console or you create a new run spacer session
0:34
It includes all of your automatic and preference variables inside of the scope
0:40
And then any variables, aliases functions you define in your PowerShell profile are included in your global scope
0:46
Then we also have ScriptScope. This is the scope created when you run a script or a function potentially
0:52
The variables defined in that script are only available to that script scope, and they are not available to
0:57
the global or parent scope. Local scope is very similar. This is the scope before a command or
1:03
script is currently running. And already mentioned there a little bit, scopes do work in a hierarchy
1:10
Global is the parent scope, so it, you know, overarches everything, and variables defined in the
1:16
global scope are available to child scopes. However, variables defined in child scopes, like your
1:21
scripts are not automatically available to the parent scope. And you cannot change variable values
1:27
outside with their scope. Let's see an example of our scope hierarchy in action
1:34
We'll start with Global Scope versus ScriptScope. Let's take a look at a PS1 file I have here called ScriptScope
1:42
We have a variable name greeting. It's just Hello World and it outputs the greeting to the console
1:49
So we will go ahead and run this script here real quick. And we see that
1:54
It outputs Hello World. Now, our greeting variable only exists within that script scope
2:00
If I were to come back here inside of our global scope, inside of our console, and I tried to output greeting
2:06
it's not going to output anything because our global scope, our parent scope here, does not have access to variables defined within our script that we just ran
2:14
However, if we define a variable inside of our global scope, we can't access it within a script if we run it within that same scope
2:23
Here we have variable name greeting 2. This is Hello from the Global Scope
2:27
We'll run that and output it to make sure we have that there. And then I have another script here called ScriptScope with variable
2:36
All it does is output the value of greeting 2. So we should see the exact same thing when we run it
2:44
Hello from the Global Scope. In this case, we had a variable defined in our local console and we were able to access it within our script
2:51
I bring this up because maybe you're troubleshooting an issue or you're trying to figure out where is this value coming from or why is my script not working as expected
3:00
You might have a variable value defined or set in your global scope and it affecting the script that you trying to run As we already seen variables defined inside of our script scope are not accessible in the global scope but you can change that behavior
3:14
Let's go take a look at this other script here called Global Variable Defined
3:19
Scoot this over here. It's going to output item inside the script
3:23
And when we define our variable here called Greening Global, we're going to prepend it with Global and a colon
3:29
basically saying we're defining this variable and we want to make it available to our global scope
3:36
And it just has the message hello from the globally defined variable inside the script
3:41
Let's go ahead and go this over here. We will run our global variable defined script here and we see that outputed to the screen
3:51
Now if I try to output greeting global, which was defined inside the script, we'll see the exact same thing
3:57
but you can take a variable inside of a script and change its scope when you define it
4:03
Probably not a best practice, but just letting you know that option is available
4:09
In addition to changing the scope, when you define a variable, you can also bring a script or functions variables into your global scope
4:17
Right now, if we look at the greeting variable, it should be blank
4:22
All right, we just output it. There's nothing there. However, if we go back to our script scope
4:27
we do define greeting and a value for it. And if I use dot sourcing, I can bring that value into my current scope
4:36
You can do this exact same thing. If you have a PS1 file with a bunch of functions define
4:40
you can dot source it to bring those functions into your current session
4:45
In this case, we're going to dot source our scriptscope. Now, if you look at line 57, that is a dot
4:52
and there is a space in between this next dot and the name of our file
4:57
that you're wanting to dot source. So let me go ahead and bring that in here
5:02
And it did go ahead and run the script. Now, if I tried to output greeting again
5:08
it should bring us our value of Hello World. If you're ever needing to bring the values that you define inside of a script
5:15
into your current session, you could do something like dot sourcing it like this
5:20
Now, something that affects PowerShell, but it is available in other language
5:24
is something called Block Scope or Variable Scope. I've learned this in other languages, and it always threw me off that it wasn't available inside a PowerShell
5:32
What this means is in other languages, if you define a variable inside of something like an if-then statement or some other block of code
5:41
that variable only exists inside of that block. However, that's not true when you do it in PowerShell
5:47
Let's take a look at to see what I mean here. On line 5, we're running a for-each command
5:52
We're just running through the numbers 1 through 5. and on line six, we're defining a variable called inside array, and it just equals the current item
6:01
So if we run the four each at the end of it inside array should equal five and we going to output it to see if it does still exist outside of the four each scope And then we also have an if statement just says if true We saying inside if and assign it to a string and then outputting that value outside of the if
6:20
What I'm testing here is if I define a variable inside of one of these two code blocks here
6:26
does it still exist outside of that scope? Let's go ahead and run block scope test
6:33
And we can see that they actually do. It outputs five here because that's the last item inside of our array
6:38
and then we can see our string inside if. As I mentioned, that is not true in all programming or scripting languages
6:44
And some of them, I think like Java or JavaScript potentially, that inside if variable or inside array variable would not be available outside of our smaller code blocks there
6:55
Let's see how we can use these different scopes when working with our custom-defined functions
7:00
that we might have inside of a module or a PS1 script. Here we have two functions, get greeting and set greeting
7:08
Get greeting checks to see if name has a value. If it does, we set the greeting to hello and dollar sign name
7:15
Else where you're just going to set it to hello world and then output the value of that greeting
7:21
We then have another function called set a greeting name. It accepts a parameter of a string called greedy name, and it just sets name equal to greeting name
7:30
Now notice inside of each of these functions, we have a variable named dollar sign name
7:35
and what we're going to test here is if we set dollar sign name using set greedy name
7:40
does that go over to get greeting? It's actually what I'll do here is dot source our file here
7:49
And then first let's just do get greeting. And it outputs hello world because we haven't defined anything with name
7:58
Let's set a greeting name. We'll set our parameter to Jeff. Now, right now, inside of that function of set greeting name, we set dollar sign name to my name, but let's go back and run get greeting
8:14
And as you can see, it still outputs Hello World because Git greeting is not aware of a setting the variable dollar sign name
8:22
It still thinks it's blank or null, so it just bypasses it, gives us our default message
8:27
If you want to change that behavior, we can use the script modifier like we did earlier
8:32
with the global modifier to make that variable available to a higher scope basically
8:39
These are the exact same two functions. However, if you notice, on line 5, we're referencing our name variable
8:46
with dollar science script in front of it. And then if you notice on line 21, we're pre-pending our variable name with script
8:52
to change the scope of where that variable value exists. So let me highlight these to bring them into my current session
9:00
Again, let's just do some quick testing here. We'll do get greeting
9:06
Outputs hello world as expected because we haven't set anything yet. This time we'll do set greeting name and put in Jeff again
9:14
And then if we go back and run get greeting it comes back and then it outputs hello Jeff because our name variable now has a value that we able to share in between each of our functions there Not sure if this would
9:27
really be a best practice. I've kind of dealt with this before and this was the solution I had to come
9:32
up with. In fact, let's jump over to my other GitHub repository and take a look at how I've implemented
9:37
this before inside of a module. Here's a module I wrote a few years ago using PowerShell and the Twilio API. This is when
9:44
I was first learning how to interact and work with APIs. So I wrote a PowerShell module around it
9:50
In order to interact with this API service, you needed an account ID and a token to
9:55
authenticate to your account, be able to use their services. So within this module, I wrote a function called Connect Twilio service
10:03
And what you can do is input a credential object with your account SID or SID and your
10:08
auth token for your Twilio account. And it would store that and be able to use it inside of
10:14
other functions inside of this module. If we scroll down a little bit more, you can see on lines 51 and 54
10:22
I'm checking to see if it passed in credentials or if we need to prompt form
10:26
But notice I'm setting Twilio Creds with dollar sign script, meaning I want to make this Twilio Creds variable available to a higher scope in other functions
10:38
And if we scroll down a little bit more, let's actually find a command that uses it
10:43
Here we have Send Twilio SMS. Basically, you can use their service to send a text message
10:49
And if we scroll down a little bit, first online 302, we have a credential parameter
10:55
I do set a default value of dollar sign script, Twilio, Cred
10:59
So hopefully you've set your credentials before using the Connect Twilio service
11:05
And then we do some checks. If you don't pass in credentials, it's going to ask you to run that command again, etc
11:11
but this is how I was able to set my credentials using one command and be able to use those credentials and other commands with inside of this module
11:21
It's been a few years since I wrote this and I think at the time I researched and maybe even asked around on some forums if this was the best way to do this
11:28
And general consensus is that it was. Maybe some other options would be setting environmental variables to your values and pulling those in from your scripts
11:37
Because those environmental variables would be in your global scope and then the year
11:41
PowerShell module, the functions inside of it, should be able to use those. And then when you close out that session, those variables would disappear and would not be
11:49
available anymore and you'd have to set them again next time you ran it. If you have any thoughts on the best way to do something like this, if you want to share
11:57
credentials, please leave a comment below. That'd be awesome discussion. That does it for this video. Hopefully you see that there are different scopes that you
12:05
might run into with your variables and how maybe having something set in your global scope
12:10
is affecting something you have in your script scope or why variables you set inside of your script
12:16
aren't available in your global scope because they are just not available
12:20
They're only available there, not inside of the parent scope. Anyway, hope you learned something new
12:25
Thank you for watching. We'll see you next time