Building PowerShell Applications: A Step-by-Step Guide
In this series, you’ll learn how to build practical, data-intensive, and interactive PowerShell applications. Part 1 discusses scripting techniques and strategies.
October 3, 2023
In a recent article, I discussed the process of making a RESTful API call from PowerShell and displaying the retrieved data (Getting Started With RESTful APIs in PowerShell). As useful as that technique might be, there is a big difference between making an API call and building an application.
With that in mind, I’d like to explore what it takes to build a full-blown application in PowerShell.
My primary goal in writing this article series is to teach advanced PowerShell coding techniques. I also wanted the app I developed to meet several criteria:
Practical Utility: The app must serve a practical purpose in real-world scenarios.
Data Integration: The app must use data from multiple external sources.
Graphical Interface: Since most real-world apps are graphical in nature, the app must have a graphical user interface (GUI).
Interactivity: The app must be interactive, providing functionality beyond merely displaying static information.
Needless to say, achieving these goals using PowerShell requires a lot of work, but it is indeed possible.
My Plan for This Series
In this article series, I plan to follow a structured approach:
Part 1: In this initial article, I will delve into the resources used by the app that I have created. Additionally, I will discuss strategies for developing complex PowerShell scripts.
Part 2: The second article will focus on the script’s logic, with an emphasis on acquiring and parsing the necessary data.
Part 3: The series will conclude with a third article, where I will address some of the trickier aspects of the GUI. While space limitations prevent me from turning this into a comprehensive discussion of PowerShell GUI environments, I will highlight key elements related to GUI development.
Finally, I will provide my app’s full source code at the end of Part 3.
Data Sources
Most modern applications share a common characteristic: They rely on multiple data sources. While designing a PowerShell script capable of making API calls is nice, custom applications often require data from diverse origins. The odds are that you aren’t going to be able to find a single API that does everything you need.
As such, I aimed to build a script that uses multiple public data sources. Specifically, the script incorporates an API (requiring multiple API calls) and a local data repository.
Before delving into the specifics of the data sources, let me first explain what the script does. The script I have created serves as a weather forecast application.
Here’s an overview of what the script accomplishes:
Entering Location: Upon launching the script, it prompts the user to input their zip code (you will need to use an American zip code for the script to work). You can see what this looks like in Figure 1 below.
Data Retrieval: After entering the zip code, there is a brief pause during which the script gathers and processes the necessary data.
Weather Forecast: Following data processing, the script presents a three-day weather forecast for the location you have entered. In Figure 2, you will notice that even though you have entered a zip code, the app lists the name of the city associated with that zip code. Additionally, a drop-down menu at the bottom of the screen allows users to view a more detailed forecast for a specific day.
Complex PowerShell 1-1
Figure 1. The script prompts you to enter your zip code.
Complex PowerShell 1-2
Figure 2. The script provides a graphical weather forecast for the location that you have specified.
As noted earlier, this script relies on multiple external data sources:
CSV File: The first external data source is a CSV file containing zip code data for the entire United States. As you can imagine, this file contains tens of thousands of rows of data. You can download the file for free here: https://simplemaps.com/data/us-zips. The only requirement is that anything you create for production use must acknowledge the source site of the downloaded data. Due to the script’s complexity and my time limitations, I opted to use the CSV file as-is, rather than use the data to build a SQL Server database. If you are interested in using PowerShell to access SQL Server data, check out my recent article on the subject.
National Weather Service API: The second data source is a RESTful API provided by the National Weather Service (https://www.weather.gov/documentation/services-web-api). This API returns weather data based on location information. While it may sound simple, the process is relatively complex. I will explain how the API process works in Part 2 of this series.
Icons: The third data source is a collection of icons that I downloaded from this website: https://www.alessioatzeni.com/meteocons/. Although these icons are free to use, they are bundled as a single graphical image. To use them, you must use a graphics editor to extract individual icons. In case you are curious, the icons I created are 80 x 80 pixels in size.
Strategies for Writing Complex PowerShell Scripts
As you begin to develop advanced PowerShell scripts, you may discover that the sheer complexity of the task becomes overwhelming. Fortunately, there are several strategies to make the process more manageable.
One commonly used technique for handling complex PowerShell development tasks is to break the script into modules. A module is essentially a standalone function or component of a script. Using modules makes it easier to focus on building and debugging one part of the script at a time. I didn’t use modules for the script I am presenting in this series, but I may revisit this topic in the future.
Even if you choose not to use modules, you can still develop a complex script by breaking it into separate parts and then merging them when complete. For example, when creating the script I am going to be discussing, I initially built a bare-bones version with no regard for aesthetics. My primary objective was to validate the API calls and establish the fundamental script logic.
I also developed a separate script that contained a user interface but with no logic or real-world data (although I created some placeholder data). This approach allowed me to concentrate on individual aspects of the script (interface and functionality) separately, without needlessly complicating the development process.
Additionally, it is also worth noting that I built the user interface before writing any functional code. This choice was deliberate. By creating the user interface first, I could make decisions as to exactly which data elements the script would expose (the API returns far more data than what the script uses). Knowing exactly what data would be displayed and which elements were present within the user interface made it much easier to write the functional portion of the script.
So, with that said, let’s begin dissecting the script’s logic. I will show you how the data portion of the script works in Part 2.
About the Author(s)
You May Also Like