Posey's Tips & Tricks

Best Practices for PowerShell Dot Sourcing, Part 1

Dot sourcing can simplify large PowerShell scripts -- but without a clear structure, it can quickly lead to chaos.

Over the last seven months, I have been hard at work building a line of business application that is designed to manage all of my writing, speaking and other projects. As crazy as it may sound, I wrote the entire application in PowerShell. The resulting script consisted of over 50,000 lines of code. Needless to say, one of the biggest challenges that I faced throughout the development process was that of keeping the code manageable.

As I’m sure you can imagine, putting all of the code into one massive script wasn’t an option. I can’t even imagine trying to scroll through that much code, trying to locate the source of a problem. Fortunately, PowerShell offers a few different options for breaking a large script into multiple files.

Modules seem to be the most widely used option, but modules are basically just collections of functions and not all of the code that I wanted to separate from the main script would fit neatly into functions. That being the case, I decided to use a technique called dot sourcing.

For those who might not be familiar with dot sourcing, it is a technique that involves using one PowerShell script to open another. You can even perform nested dot sourcing in which one script opens another script, which opens yet another script. To call a PowerShell script through dot sourcing, just enter a period, a space, another period, a slash and then the filename. If for example, you wanted to use dot sourcing to open a script called Backup.ps1, then the command would be:  . ./Backup.ps1

Dot sourcing is as convenient as it is powerful. If left unchecked however, things can quickly get messy. My new PowerShell application consists of 196 separate PowerShell files. If these scripts were haphazardly linked to one another, the development process would have been just as messy and problematic as it would have been had I tried to place all of the code into one massive script. Fortunately, I have figured out some best practices that I want to pass along.

Before I do, there is one extremely important thing that you need to know about dot sourcing. When you open a script using dot sourcing, that script runs in the current scope (the same scope as the code that was used to call the script) rather than running in a separate scope. This means that dot sourcing has its advantages and its disadvantages.

The main advantage is that you don’t have to worry about passing parameters like you do with a function. If you define a variable in your main script and then use dot sourcing to call another script, your variable will be recognized within that secondary script. Similarly, if your secondary script were to modify a variable, then that variable modification will affect the main script too.

The primary disadvantage to using dot sourcing is that because your main script and any secondary scripts that you might have opened all share the same scope, it can be easy to accidentally overwrite variables that are needed by the main script. You can also, in certain circumstances, cause problems if you open the same dot sourced script over and over.

So let’s talk about some best practices for dot sourcing. My number one best practice is to make sure that you have a plan for what your file hierarchy is going to look like. Remember what I said earlier about my application consisting of 196 separate PowerShell files? I avoided the temptation to just create a new script every time a script started to feel as though it were getting to be too lengthy. Instead, I planned the code hierarchy first and then wrote my scripts based on that hierarchy. Let me give you an example.

My line of business application consists of several different tabs, some of which contain sub-tabs. Therefore, I created a main script at the top of my hierarchy that, among other things, creates the GUI interface and all of the various tabs. This top level script also contains several functions that are widely used by nearly all of the parts of my script. For example, all of my SQL Server queries leverage a function called Perform-Query. I also wrote some functions that were designed to validate user input and remove characters that might be problematic. These functions have names such as Clean-Date and Clean-Integer and they all reside in my top level script.

Not surprisingly, each of the main script’s tabs uses dot sourcing to call a child script. In turn, the child scripts each call a minimum of two additional scripts. One of these scripts contains the basic GUI objects used by the tab. I’m talking about things like buttons or labels. The other script that is called aligns with the tab’s database schema. Suppose for instance that a particular tab contains a database column called Assignments. The schema script would include the labels, text boxes, or other GUI elements that are associated with the Assignments column. In contrast, the basic GUI object script contains objects that are more generic in nature and not aligned directly with any particular database column.

Some of the tabs within my application also call scripts that provide certain functionality. The Assignments tab for example, contains buttons (defined by the generic GUI items script) that can open scripts used to create, edit, view, or delete assignments. Because the create, edit, view and delete scripts are closely related to one another, they all share the same basic GUI items and schema related GUI items.

Obviously, the way that I structured my script’s hierarchy is not the only option. There are plenty of other ways that I could have structured the code. The important thing is that a scripting hierarchy existed long before I ever wrote the first line of code.

So now that I have talked about dot sourcing hierarchies, I want to share some other best practices with you. I will continue the discussion in Part 2.

About the Author

Brien Posey is a 22-time Microsoft MVP with decades of IT experience. As a freelance writer, Posey has written thousands of articles and contributed to several dozen books on a wide variety of IT topics. Prior to going freelance, Posey was a CIO for a national chain of hospitals and health care facilities. He has also served as a network administrator for some of the country's largest insurance companies and for the Department of Defense at Fort Knox. In addition to his continued work in IT, Posey has spent the last several years actively training as a commercial scientist-astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space. You can follow his spaceflight training on his Web site.

Featured

comments powered by Disqus

Subscribe on YouTube