Coding Session: Enhancing PowerShell Scripts with Parameters and Error Handling
15K views
Apr 3, 2024
This coding session goes through adding PowerShell parameters and error handling to make your script more better-er! foreach and CSV File Tutorial: https://youtu.be/fMrRosJYuXs?si=Vp237hVDz6chRvMH Master PowerShell Errors with Try Catch Blocks https://youtu.be/KVwMajS1sSc?si=3w8liRvDWvJpdABs 00:00 Introduction 00:28 Connection Check 03:00 File Input Parameter 06:46 Error Handling 11:48 Summary
View Video Transcript
0:00
What's up, everyone
0:00
Today, I want to go over PowerShell script that I featured in a previous video
0:04
when I talked about 4-Reach and CSV files and see how we can make some improvements to it
0:09
to make it more PowerShell-y, if that's a word. What we'll do is go through and make three changes to it
0:16
including parameters, some error catching, and then modifying how we're making sure we're connected out
0:22
to Microsoft Graph in order to create our users out in Active Directory
0:27
Let's go ahead and get started. First, in the script on lines one and three
0:32
and then down here at the very end is where I'm managing a connection out to Microsoft Graph
0:36
which is the PowerShell module I'm using to create users out in Enter ID
0:42
Instead of force creating the connection like this and then disconnecting at the end
0:46
I'm going to change this just to where it checks to see if a connection exists
0:51
and if it doesn't, just exit the script or something like that and prompt the user
0:56
to create a connection before they run the script. So first, let's go ahead and get rid
1:01
of these first couple of lines, and we'll go ahead and get rid of disconnect graph here
1:07
And then at the very top, let's create a variable called connection
1:13
And there is a command called get-mg-context. This is going to show your current connection
1:18
out to Microsoft Graph. It'll show you what scopes, what user account
1:23
you're connected to and everything like that. In fact, let's just go ahead and run this down here
1:28
in my PowerShell window, and you can see nothing comes back. What I like to do is if there's a command like this
1:34
to see if you have a current connection to something, maybe it's Microsoft Teams or Exchange Online, SharePoint
1:40
I'll save the output of that command to a variable. And then we can just check to see
1:45
if that variable has a value. So in this case, I'm going to say null equals connection
1:52
basically meaning does the connection have any value into it, and if that is true
1:57
that means we don't have a connection. Let's do a write warning message
2:03
and let's say you must run connect-mg-graph before running this script
2:13
And then we will do, let's do an exit. This should be a very minor change of just saying
2:20
if you're not connected out to Microsoft Graph, you don't have that connection details
2:25
we are going to exit the script. Okay, let's go ahead and give this a try real quick
2:29
We'll say new entry user, and there it goes. Perfect, you must run connect-mg-graph
2:36
before running the script. Let's go ahead and do that, and then offscreen, I'm authenticating here
2:43
We'll finish that up. We come back, welcome to Microsoft Graph, and just to show you, let's go back and run get-mg-context
2:51
and you can see all my context here, the account I'm connected with, what scopes I'm connected under, and so on
2:58
So, perfect. The next part of the script we want to improve is line eight here
3:03
We're importing the user data that we want to run through in the form of a CSV file
3:09
I still have that example CSV file over here on the right, just has first name, last name, department
3:14
and some information in it. What we have right now is the path to the CSV file
3:21
is hard-coded, so if you ever wanted to use a different file, you'd have to come in here
3:25
and modify the script to point to that, and that's not very PowerShell-like
3:30
What we want to do is have a parameter where we can pass in different files
3:35
and not have this hard-coded. In order to pass in the file that we want to use
3:40
in the script, we need to define a parameter that includes the, it could just be the file name
3:45
or the full path, depending on the location where you're running the script from
3:49
And to get started, we need to define a parameter, so we're going to use the param keyword
3:54
and some open and close parentheses. Then we need to give our parameter a name
4:00
I usually like to do, let's say, user data file. Now, at this point, this parameter is valid
4:07
We should be able to use it. We would run new entry user dash user data file
4:14
and give the path to the file name. We do want to be a little more specific
4:19
in our parameters here and define what type of data we're expecting to come into this
4:25
Is it going to be a number, an object, a string, or anything like that
4:28
In this case, it's going to be a string. Some people will put the data type definition
4:33
right in front of the variable name here or the parameter name here
4:38
I like to just put it on a separate line like this. That's just my preference
4:44
This or this are both valid. I think I like seeing the parameter name there
4:50
on the far left, just so I can visually see it a little bit better for me
4:55
In its current state, user data file is not mandatory or we don't need it to run the script
5:02
But in our case, it is the most important part of the script that we have here
5:06
So we want to make sure that when people run this, that they use this parameter and provide a value
5:14
What we can do is then add a parameter definition here, a parameter attribute
5:19
Now, at a minimum, you could just leave it like this. It just says parameter. We don't have any other attributes in it right now
5:25
But we want to make sure this is a required parameter. So as you can see, you start typing
5:30
and we now make it mandatory. So now, if I were to try to run this again
5:38
it is going to prompt and say you need to provide the path to the user data file and it won't let me run it
5:43
So let me Control-C out of here and clear the screen. Now that we've got our parameter
5:49
we need to actually use it. So here, we're going to replace our path
5:54
and we will just say user data file. There are some additional checks we could do
5:59
within the parameter definition itself. We could have a validate script that will test the path
6:05
of the user data file that we pass into it and make sure it exists
6:09
Or we could do something similar down here. We could try to do the import
6:13
In fact, what does that look like real quick? If we do csv path C does not exist
6:22
some file.csv, that does error out like that. There is some built-in error catching there maybe
6:30
If it tries to import and it doesn't exist, hopefully it's bad enough for a terminating error
6:35
that the script would then exit out. Right now I'm fine with this
6:39
If it doesn't keep going, then the foreach is not going to iterate through any data
6:45
So we're good to go there. All right, so far we have our parameter definition
6:49
We changed up how we're making sure we're connected out to Microsoft Graph. Before we continue, we've got our foreach
6:55
Everything is good there. The last thing I want to take a look at is our command here on line 37
7:02
to actually go and create the user. Generally creating users should be pretty straightforward
7:07
Hopefully you don't run into any issues. When I was recording the last video
7:11
where I first featured this script, I did run into an error because all the users
7:16
I was trying to create already existed and the errors it threw out weren't very intuitive
7:20
for anything like that. What I want to do here is just add a try catch block
7:24
on line 37 to make running into errors just a little more visually good in our script here
7:32
I do have another video on the channel going over try catch blocks
7:35
I'll include a link to it down in the description. Let's put in our basic try catch block
7:41
and we'll start building this out. And then I'm going to add error action stop
7:51
Just in case this is not a terminating error, I do want it to stop and go into my catch block
7:58
Let's create a variable here. I'm going to call it error message
8:01
I'm going to use get error newest one. So this I'm just saving the error message out to a variable
8:12
and then we'll do write warning message. And let's just do error message right now
8:21
Let me go ahead and save that. Okay, so basic try catch block
8:25
We're just going to output a warning message here of what the exception was
8:31
Clean up our spacing a little bit. Now, for looking over at our CSV file
8:37
we see the Jeff Brown account is the first account it's going to try and create
8:41
I do know that account already exists and I want to test my error catching here a little bit
8:47
So let's add just the first index in our imported data here in our array
8:53
Adding the index like this will just limit to the first item in our user data variable
8:58
which is all the data inside our CSV file. So I know this is going to error out
9:05
Let's do new entry user. User data file example. Let's see CSV
9:13
So this should error out. Perfect. So this is the message that I got the other day
9:18
but it says another object with the same value for property user principal name already exist
9:23
That's a really fancy way of saying this user already exists. What I wanted to do in this case is just try
9:31
and clean this message up a little bit and give me a custom message
9:35
that maybe makes a little more sense within the script. So I'm going to highlight our message here
9:42
And inside the catch, you can do any number of things that you want to
9:46
in order to handle the error. So what I'm going to do is say if error message
9:55
we'll say I like, put some wild cards around it. Here, all I'm doing is if the error message
10:05
is like this string phrase here, another object with the same value
10:10
I'm going to change my warning message here. What I'm going to do is output that
10:18
this specific user already exist. Fix up my quotes here. Already exist
10:27
Now, if our error message isn't like that, we'll just output the warning message here as usual
10:37
Okay, so just go back through, try it. We're going to get our latest error message
10:42
If the error message is like this phrase here, we're just going to output a different message
10:48
We'll put in the name. We'll just say it already exists. We'll just say it already exists
10:53
else write out whatever warning message we have. So let's go ahead and try to run this again
11:00
So it's a little more useful. Normally, if this ran through, we wouldn't know what user existed
11:06
but now we know Jeff.Brown at this address already exist. But for the rest of our users
11:12
it should be able to go through and create them just fine. This is also helpful if you're outputting to a log file
11:18
if you're creating a whole bunch of users, or if you need to log what users it's creating and everything
11:25
Okay, so with our updated script file here, let me get rid of our zero index
11:30
I want it to run through the rest of my users here as it runs
11:35
Pull this up here. Perfect, yeah. Did those last three really quick
11:42
and we saw Jeff.Brown already exist, but the rest of our users were created successfully
11:48
That does it for this video. Let's go back through real quick what we did. First, we added a parameter
11:53
so we could import different CSV files that we needed for our user data
11:58
It wasn't hard-coded. We changed how we checked for connections. We weren't forcing to connect out and then disconnecting
12:05
because maybe you're already connected to Microsoft Graph in your current PowerShell session
12:09
And then we added just a little bit of error handling here
12:13
We put it in a try-catch block. I had a specific error
12:16
that I wanted to handle a little bit differently and just output that this user already exists
12:21
Otherwise, we just output the error message and go on from there
12:25
The error catching here can evolve as you run through and try the script more often
12:30
You can continue to modify the catch block here or find a specific exception type
12:35
that you maybe want to handle, but otherwise I think the script is in a lot better shape
12:41
One other improvement might be not passing any file with the user information
12:45
but maybe you want to run new entry user and then provide the first name, last name department
12:51
That would definitely be another way to make the script more dynamic
12:55
and maybe we could save that for another video. Otherwise, I think coming up next
12:59
we'll take a deeper dive into parameters and maybe take a look at hash tables as well
13:05
So stick around for that. Thank you for watching and we'll see you next time
#Computers & Electronics
#Programming
#Scripting Languages