PowerShell Tokenizer more Accurate than AST in Certain Scenarios

As many of you know, I’ve been working on some module building tools. One of the things I needed was to retrieve a list of PowerShell modules that each function required (a list of dependencies). This seemed simple enough through PowerShell’s AST (Abstract Syntax Tree) as shown in the following example.

The modules that are retrieved by the AST are simply the ones specified in a functions Requires statement. What if someone forgot to add a required module to the Requires statement? How could this be validated?

Light bulb moment: I’ll retrieve a list of all the commands used in a PowerShell function using the AST and then determine the module they exist in using Get-Command. Sounds simple enough, right? Well, not so fast.

While I’ve written functions on top of the functionality shown in this blog article, I wanted to keep this as simple as possible and eliminate those functions as the source of problems.

First, I’ve set a variable named File to the path of a function of mine named Start-MrAutoStoppedService which is contained in a PS1 file by the same name. It can be found in my PowerShell GitHub repo.

Now I’ll retrieve a list of all the commands used in the specified function with the AST.

As you can see in the previous set of results, the AST thinks there’s a command named “State“, but that’s actually part of a WMI filter.

Using the tokenizer instead of the AST returns more accurate results excluding “State” as shown in the following example.

While I’ll clean this up and turn it into a function, the following example shows the basic functionality to retrieve a list of required modules from a function based on the commands used within it instead of relying on someone to remember to add them to the Requires statement.

Maybe I’m missing something as far as the AST goes and maybe there’s a way to retrieve an accurate list using it? Please post your questions, comments, and/or suggestions as a comment to this blog article.

µ

1 Comment

  1. a reader

    Hi,
    Filter parameter is a string not a script block :

    $filter= “State != ‘Running’ and StartMode = ‘Auto'”
    $Services = Get-WmiObject -Class Win32_Service -Filter $filter

    Get-Command work only with the loaded modules.
    Powershell being dynamic it is sometimes difficult to find information with the AST

    Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: