Our first iteration – setupapi_parser_v1.py
The goal of our first iteration is to develop a functional prototype that we will improve upon in later iterations. We will continue to see the following code block in all our scripts, which provides basic documentation about the script and support for printing information (line 2) and opening files (line 3) in both version 2 and 3 of Python. The following is the licensing information and basic script descriptors that can be found in all of our scripts:
001 """First iteration of the setupapi.dev.log parser."""
002 from __future__ import print_function
003 from io import open
...
033 __authors__ = ["Chapin Bryce", "Preston Miller"]
034 __date__ = 20181027
035 __description__ = """This scripts reads a Windows 7 Setup API
036 log and prints USB Devices to the user"""
Our script involves three functions, which are outlined as follows. The main() function kicks off the script by calling the parse_setupapi() function. This function reads the setupapi.dev.log file and extracts the USB device and first installation date information. After processing, the print_output() function is called with the extracted information. The print_output() function takes the extracted information and prints it to the user in the console. These three functions work together to allow us to segment our code based on operations:
039 def main():
...
054 def parse_setupapi():
...
071 def print_output():
To run this script, we need to provide some code that calls the main() function. The following code block shows a Python feature that we will use in almost every one of our scripts throughout this book. This section of code will become more complex throughout this chapter, as we will be adding the ability to allow users to control input, output, and provide optional arguments.
Line 82 is simply an if statement that checks to see if this script is called from the command line. In more detail, the __name__ attribute allows Python to tell us what function called the code. When __name__ is equivalent to the __main__ string, it indicates that it is the top-level script, and is therefore likely to be executed at the command line. This feature is especially important when designing code that may be called by another script. Someone else may import your functions into their code, and without this condition, it will likely result in our script immediately running when imported. We have the following code:
082 if __name__ == '__main__':
083 # Run the program
084 main()
As we can see in the following flowchart, the trunk function (our script as a whole) calls the main() function, which in turn calls parse_setupapi(), which finally calls the print_output() function: