Dot Sourcing in PowerShell: How to Simplify Large ScriptsDot Sourcing in PowerShell: How to Simplify Large Scripts
This video tutorial explains how to use dot sourcing in PowerShell to break large scripts into smaller, modular files, improving readability, debugging, and maintainability.
March 17, 2025
This tutorial by Brien Posey demonstrates how to break large PowerShell scripts into smaller, more manageable pieces using dot sourcing. He demonstrates splitting a script for a PowerShell-based text editor into modular files, aiming for improved readability, debugging, and maintainability. Posey compares different methods, such as Invoke-Expression and modules, but highlights dot sourcing as a practical approach for structuring complex scripts.
Subscribe to ITPro Today’s YouTube channel for PowerShell tutorials and more.
The following transcript has been edited for length and clarity.
Transcript:
Brien Posey: Hello, greetings and welcome. I'm Brien Posey. In this video, I want to show you something I've been working on lately: splitting PowerShell scripts into smaller pieces.
Example: A PowerShell-Based Text Editor Script
Let me begin by showing you a script I wrote a few months ago. This script is a PowerShell-based editor. I'll go ahead and run the script now. On the editor's interface, you'll notice that we have a menu at the top with File, Edit, and Format menu options.
If I click on "File," we have options for "Open," "Save," and "Exit."
Under "Edit," we have "Undo," "Cut," "Copy," "Paste," and "Find."
Under "Format," we have "Font."
If I type a bit of text, I could select some of the text, go to Format, and change the font. When I'm done, I could save this. Documents are saved in RTF format by default, but that's not the only option. I could also save this as a Word document or text file.
So, that's a quick overview of what my PowerShell editor does.
As you can imagine, it took quite a bit of code to create the script I just showed you. Let's look at the script's code for just a moment. I'm not going to go through the entire script. It's simply to show you that this is a relatively lengthy script—about 216 lines in length.
Recently, I created a much more advanced PowerShell script, and that script was 820 lines in length. You can imagine what it was like trying to create and edit 820 lines of code in one big file. The debugging process took forever because I constantly had to move up and down the script and locate blocks of code. The length of the script just made it difficult to find what I was looking for. Sure, I could use the Find function within my editor to make finding what I was looking for easier, but the editing process would have been much easier if the script was shorter.
With that in mind, I've been working on a much longer script recently. I'm building a full-blown application, and this application contains dozens of features and lots and lots of moving parts. One of the things I've been working on is a method for breaking that application into smaller, more manageable pieces. That way, if I run into a problem debugging the script, it's much easier to find the section of code containing the problem.
Methods for Splitting PowerShell Scripts
I've been experimenting with a few different methods.
Invoke-Expression:
Modules:
Dot sourcing:
Implementing Dot Sourcing
I've created a dot-sourced version of my PowerShell editor script that I just showed you for demonstration. The only difference is that I use dot sourcing to make the script modular. Looking at the script now, we can see it is much shorter.
The ModuleEditor.ps1 script:
Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing # Create Form $Form = New-Object System.Windows.Forms.Form $Form. Text = "Briens Powershell Editor" $Form.Width = 1920 $Form.Height = 1080 # Create TextBox for the editor $TextBox = New-Object System.Windows.Forms.RichTextBox $TextBox.Multiline = $True $TextBox.WordWrap = $True $TextBox.Dock = 'Fill' $TextBox.ScrollBars = "Both' $TextBox.Font = New-Object System.Drawing.Font("Consolas", 12) # Default font # Add the Text Box to the form $Form.Controls.Add($TextBox) Out-Null # Load the Menus using dot sourcing . . \Menu.ps1 . . \Shortcut.ps1 # Show the Form $Form.Add_Shown({ $form.Activate() }) [Void]$Form.ShowDialog()
So, where did the rest of the code go? I stored it in modular blocks outside the script.
The script begins by adding the necessary assemblies.
Next, I create a Form. When building a GUI in PowerShell, a Form is just a window. So, we're making the window used by the editor.
Following that, the script creates a text box. You saw this just a moment ago, where I could change the font, etc. A line of code adds that text box to the form.
Then, we have this section labeled "Load the menus using dot sourcing." The first thing you'll see in this section is . ./ and Menu.ps1. Menu.ps1 is an external PowerShell script that we are loading and executing as a part of this script. As the name suggests, this is the section of code that creates the menus used by the script.
The script uses another menu: a context menu (or shortcut menu, as it's sometimes called). You access the context menu by right-clicking within the editor. The menu has options for Copy and Paste.
The Menu.ps1 File
With that said, let me go back to the Menu.ps1 file.
Here's the script:
# Create MenuStrip $Menu = New-Object System.Windows.Forms.MenuStrip # File Menu §FileMenu = New-Object System. Windows.Forms.ToolStripMenuItem"File") # Dot Sourcing . . \Open.ps1 . . \Save.ps1 . .\Exit.ps1 $FileMenu.DropDownItems.Add($0penMenuItem) Out-Null §FileMenu.DropDownItems.Add($SaveMenuItem) | Out-Null $FileMenu. DropDownItems.Add($ExitMenuItem) Out-Null $Menu.Items.Add($FileMenu) | Out-Null # Edit Menu $EditMenu = New-Object System.Windows.Forms.ToolStripMenuItem("Edit") # Dot Sourcing . . \Undo.ps1 . .Cut.ps1 . . \Copy.ps1 . . Paste.ps1 . .\Find.ps1 $EditMenu.DropDownItems.Add($UndoMenuItem) | Out-Null $EditMenu.DropDownItems.Add($CutMenuItem) | Out-Null
You can see that the first thing that this block of code does is create a MenuStripObject. From there, we create the object that defines the File menu.
After we create the File menu, we need some menu items that can appear on it. Those items are Open, Save, and Exit. Rather than embedding those options directly in this file, I've again used dot sourcing. We have dot sourcing for Open.ps1, Save.ps1, and Exit.ps1.
What I've done is create a separate file for each one of these menu options. So, we have files for the Open, Save, and Exit options. And then, if I scroll down more in the script, we also have dot sourcing for the Edit menu. Here we have Undo.ps1, Cut.ps1, Copy.ps1, Paste.ps1, and Find.ps1.
We do the same thing for the Format menu. We define it and then use dot sourcing to load Font.ps1 because the Font option appears on the Format menu.
Now, why am I using dot sourcing in this way? Some of these areas of functionality are big, and some are small. So, rather than including all these different options within the Menu code, breaking them into separate files might be more manageable.
The Exit vs. Find menu options
Let's look at an example of a small menu option. The smallest one is the Exit menu option. It has two lines of code:
$ExitMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Exit")
$ExitMenuItem.Add_Click({ $Form.Close() })
In the first line of code, we create a New-Object of type System.Windows.Forms.ToolStripMenuItem. This creates the menu item, which is called "Exit."
The next line defines a click action—i.e., what happens if somebody clicks on the Exit menu item. In this case, the click action is just to close the form. Form.Close terminates the program.
This is an example of a menu item that didn't require much code. I wouldn't have used dot sourcing if all my menu items were like this.
However, some of the menu items require a bit more code. For example, the Find menu item contains quite a bit more code. Like before, we begin by creating a ToolStripMenuItem, and we're calling it "Find."
The next thing we must do is define a click action. However, whereas the Exit menu item's click action involves a single command, the Find menu option's click action involves many commands. It made sense to break this one out into a separate file just to isolate the code related to the Find menu item. That way, we don't have to deal with the File menu code in the main body of our script or within the menu itself.
Dot Sourcing Pros and Cons
One of the big questions that I'm sure comes to mind is why I might do something like this instead of just exporting all the various functionality into a PowerShell module. Well, there are a couple of different reasons.
Advantages of dot sourcing
Eliminates the need to load a module manually:
Modules require all code to be inside functions.
Dot sourcing lets you use functions without passing parameters:
Variables defined through dot sourcing are global and accessible throughout the entire script:
Disadvantages of dot sourcing
Now, before I wrap up this video, I want to address whether there are any disadvantages associated with using dot sourcing.
Variable assignments are considered global, which may not be desired:
You must approve each file before running the script:
In PowerShell, I get a security warning when I run the ModuleEditor.ps1 script. After hitting R for run, the warning appears again for each file the script uses. This happens because I wrote the PowerShell script on another computer and copied it to the one I used to record this video.
To fix this, right-click the script, go to Properties, check Unblock under Security, and click OK. The warning disappears. Repeat this for all related files. After unblocking them, the script runs without interruptions.
About the Author
You May Also Like