How To Create Your Own PowerShell Cmdlets (Video Tutorial)

Ever want to make your own PowerShell cmdlets? Watch this video to learn how to achieve this by using modules.

Brien Posey

May 24, 2024

In this video tutorial, PowerShell expert Brien Posey shows you that creating your own cmdlets is simpler than you might think.

By following along, you’ll learn how to transform your PowerShell scripts into standalone cmdlets using modules. Posey covers the entire process,  from creating the module to importing and testing the custom cmdlet.  

The transcript has been lightly edited for clarity and length.

Transcript:

Brien Posey: Hello, greetings, and welcome. I’m Brien Posey. In this video, I want to show you how to make your own custom PowerShell cmdlets by using modules.

The idea of creating a custom PowerShell cmdlet probably sounds complicated and the sort of thing that only a developer would be able to do. But that's not the case at all. Microsoft makes it easy to create your own PowerShell cmdlets. In this video, I'll show you how that's done.

Using functions

If you look at the screen right now, you can see a PowerShell script that I've created. The contents of the script are kind of irrelevant, but that's okay. I just want to look at the script.

At the very beginning, you'll notice that we have a function, and that function is called Generate-Password. If I scroll down to the end of the script, you can see that the function is right here. There's nothing else in the script, so we don't have a script body. What that means is that this script isn't going to do anything by itself, because there's no code in here to call the function. For example, if I were to minimize this window and then try to run the script, you can see that absolutely nothing happens.

To make that script do something, we need to add a function call to it. So, I'm going to go ahead and do that now.

Calling a function in PowerShell is a simple process. All we do is type the name of the function, which in this case is just Generate-Password. So, I'll type Generate-Password. If I scroll up to the top, you can see that Generate-Password is the name of the function.

Now, if we look just below that, you can see that we have a params section. The params section dictates the parameters that get passed to the function. In this case, we have one parameter that gets passed: It's an integer, hence the [Int]. The variable associated with this integer is $Length. So, we're passing the desired password length to this function, and then the function will return a password. Let's go ahead and add that in. I'm going to add -Length. I'll enter 12 as the password length.

One more thing that I'm going to do here is create a variable. I'll call this $PasswordOut. I'll set that equal to the name of the function and the parameter that we're passing to the function. Then I'm going to add one more line of code: $PasswordOut. This line of code is simply going to display the PasswordOut variable’s contents. The contents of that variable should be the password that was generated by the function.

Let me go ahead and save this, and then I'm going to switch back over to PowerShell.

So, let's try running the script again. I'll press Enter. And what we get this time is a 12-character password that was generated by the function within our script. Easy enough.

Now, in this case, that function does exactly what it's supposed to do, but it's not the sort of thing that we can use as a standalone cmdlet. Remember, that function is embedded within a script. That function’s name is Generate-Password. If I were to try to call that function directly, you can see that I get an error. The reason for that is that PowerShell doesn't know that that function even exists because the function is embedded in a script. So, the only way that PowerShell would know that that function exists is if we were to run the script containing the function and have a line of code within that script to call the function just like what I showed you a moment ago.

Cmdlet Naming Conventions

With that said, let me switch back to the script. If I scroll up to the top, you'll notice that the function name is Generate-Password. One of the things about this function name is that I've formatted it in the typical PowerShell cmdlet convention. PowerShell cmdlets are typically Verb-Noun. In this case, we have a verb (“generate”), a dash, and then a noun (“password”). So, this is structured just like a PowerShell cmdlet.

Let's go ahead and turn Generate-Password into a standalone cmdlet. Now, before I do that, I just want to mention that I named this function in a way that would adhere to the normal PowerShell cmdlet structure, but you don't necessarily have to do that. As a best practice, it's a good idea to name your functions in a way that mimics PowerShell cmdlets. But you don't have to. If I were to simply give this function a different name, it would work just as well.

Creating and Saving a Module

The first thing that I want to do is just save a separate copy of this file. I'll go to File and Save As. Let's just call this GeneratePassword. I'm going to set the encoding to ANSY. You'll notice that when we save this, the extension is .ps1. That's the extension that's typically used by PowerShell scripts. To create a standalone cmdlet, we need to create a module, and modules use a different file extension. Modules use .psm1. I'm just going to modify the extension from .ps1 to .psm1. Then, I'll save my changes. We've created a PowerShell module file.

But this module file is incomplete. If I were to try to enter Generate-Password as a cmdlet, it still wouldn't work at this point. There are a couple of reasons for that. If you think about it, all we've done is we've taken a PowerShell script and renamed it. That's it. So, we need to do just a little bit more work. But having said that, the process is super simple.

Let me scroll down to the bottom of this file. I'm going to get rid of those two lines of code that we created earlier. Now, as you'll recall, those two lines of code were designed to call the function and then display the output. We don't have to worry about any of that, because remember, we're taking the function and turning it into a standalone cmdlet. So, we don't have to have a command embedded in our script to call the function, because once this is turned into a standalone cmdlet, we'll be able to call it anytime we want from outside of the script.

What we do need, however, is a command that tells PowerShell that we're creating a module. What I'm going to do is go down to the very bottom of the script and then type:


Export-ModuleMember -Function

Then, I need to specify the name of the function. Again, my function is called Generate-Password.


Export-ModuleMember -Function Generate-Password

So, what I've done is I've created a PowerShell module file, and that module file contains a function. We have a line at the end of the file saying: Export-ModuleMember -Function GeneratePassword. Now, in this particular case, we're creating one standalone cmdlet, and that cmdlet is going to be Generate-Password.

Typically, a module will contain numerous cmdlets. The way that that's done is by creating multiple functions within a single file. If you do that, you'll need a separate Export-ModuleMember statement for every function that you create.

Let me go ahead and save this. I'm going to close out Notepad. Now, if I were to try to call the Generate-Password cmdlet right now and press Enter, we'd get an error. The reason for that is that even though we've created a module and put the module in the correct format, there are still two things that we need to do: We need to save the module to the correct location, and then the other thing that we have to do is import the module.

Importing the Module

Let's start by moving the module to the correct location. Here's the module file that I created. I'm just going to Right-Click on this file and choose Copy from the menu. Then I'm going to go to the Program Files folder. Next, I'll go to Windows PowerShell. And then Modules.

The next thing that we have to do is create a folder that corresponds to the name of the module file that we've created. The module file was called GeneratePassword without the dash, so I'm going to create a folder called GeneratePassword.

The reason why I didn't use the dash is that the module file that we created doesn't use a dash in the file name. The file name is GeneratePassword.psm1.

Let me go ahead and create the folder. I'll go into the folder. Then we need to paste that module file. So, we've now put the module file into the correct location.

I'll switch back over to PowerShell. I'm going to repeat the Generate-Password command once again. I'll press Enter, and this time I get a password. Now, why did that happen? I mentioned a moment ago that you have to import the module. Well, some of the newer versions of PowerShell are smart enough that they can import a module automatically if you try to enter an unrecognized command. Older versions of PowerShell don't do that. So, if I were running an older version of PowerShell, then what I would have to do is type:


Import-Module GeneratePassword

Then I would press Enter, and PowerShell would go ahead and import that module.

You often find that the process of importing a module will generate a warning message, particularly in Windows 11. You don't have to worry about this warning message. This is just there for informational purposes.

Testing the Cmdlet

Once the module has been imported, you can use the name of that function that exists within the module file that you've created as a standalone PowerShell cmdlet. In this case, I type:


Generate-Password -Length 12

But what if I just typed Generate-Password? It sure looks like a PowerShell cmdlet. If I press Enter, I get a bunch of error messages. The reason why I get those error messages is twofold. The main reason is I didn't pass a required parameter to the function. In this case, the required parameter is the password length. I have -Length 12. I could change this to something else. I could type -Length 20.

The other reason why I got all the error messages is simply because the function was created quickly and doesn't have any error handling built into it. If I were building this for production use, then yes, I would probably go ahead and build something in there to handle any errors that occur.

Now, one more thing that I want to quickly show you is that in this case, I've typed Generate-Password -Length 20 and got a password on the screen. That's great. But what if I wanted to use this within the context of a PowerShell script? Well, what we could do in a situation like that is simply map a variable to the function that we're calling. For example, I could type:


$Password=Generate-Password -Length 20

Now if I type $Password, you can see that the password that was generated by the function is mapped to that variable.

At any rate, that's how you turn a PowerShell function into a standalone PowerShell cmdlet by creating a module file. I'm Brien Posey. Thanks for watching.

About the author

Brien Posey headshotBrien Posey is a bestselling technology author, speaker, and 21x Microsoft MVP. In addition to his ongoing work in IT, Posey has trained as a commercial astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space.>em>

About the Author

Brien Posey

Brien Posey is a bestselling technology author, a speaker, and a 20X Microsoft MVP. In addition to his ongoing work in IT, Posey has spent the last several years training as a commercial astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space.

http://brienposey.com/

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like