3 min read
Designing PowerShell GUIs with Windows Forms for Interactive Scripts
PowerShell has full access to the .NET Framework and can therefore utilize all the graphical functions available in...
Unlocking the Power of PowerShell: Tips for Success
In the previous parts, we explored the PowerShell parser and how it can be used to analyze script content.
Today, let’s look at more advanced insights that could even help address security issues. PowerShell scripts can use native .NET methods, and it can be highly useful to identify the methods used by scripts:
.NET methods are represented by the token type 'Member'. Here’s a script to list all .NET methods used by a PowerShell script:
function Get-ScriptNetMethod
{
param
(
[String]
[Parameter(Mandatory,ValueFromPipeline)]
[Alias('FullName')]
$Path
)
begin
{
$fileCount = 0
}
process
{
$fileCount++
Write-Progress -Activity 'Analyzing PowerShell Scripts' -Status $fileCount
$syntaxErrors = $null
$code = Get-Content -Path $Path -Raw -Encoding Default
$tokens = [Management.Automation.PSParser]::Tokenize($code, [ref]$syntaxErrors)
if (!$syntaxErrors)
{
# get .NET methods
$methods = $Tokens |
Where-Object Type -eq Member |
Sort-Object -Property Content -Unique |
Select-Object -ExpandProperty Content
if ($methods)
{
[PSCustomObject]@{
Name = Split-Path -Path $Path -Leaf
NetMethods = $methods -join ','
Path = $Path
}
}
}
}
}
# check all PowerShell scripts located anywhere in your Documents folder
$myDocuments = [Environment]::GetFolderPath('myDocuments')
Get-ChildItem -Path $myDocuments -File -Filter *.ps1 -Include *.ps1 -Recurse |
Get-ScriptNetMethod
The result may look like this:
Compact-Path.ps1 Mandatory,new,PathCompactPathEx,ToString,ValueFromPipeline,ValueF...
Get-SpecialFolderPath.ps1 GetFolderPath,Mandatory,ValueFromPipeline
Test-Online.ps1 Add,AddArgument,AddScript,AsyncWaitHandle,BeginConnect,BeginInvok...
Test-Ping.ps1 Address,Dispose,E,Mandatory,N,new,Send,Status,ValueFromPipeline
Test-Port.ps1 Address,Client,Close,ConnectAsync,Connected,Dispose,HostName,IP,I...
Compact-Path.ps1 Mandatory,new,PathCompactPathEx,ToString,ValueFromPipeline,ValueF...
Get-SpecialFolderPath.ps1 GetFolderPath,Mandatory,ValueFromPipeline
This result may help roughly identify the focus of a script, but upon reflection, listing .NET methods without knowing their type and origin is of limited use.
This illustrates the limitation of the tokenizer: it can tell you the meaning of a given word in code, but it cannot provide context.
For more advanced analysis, you can access the Abstract Syntax Tree (AST). Before diving into what an AST is, here’s how to access it:
# path to a PowerShell script to analyze (make sure it exists!)
$path = "C:\test\some_file.ps1"
# empty variables, these must exist. The method returns syntax errors and
# tokens in these variables (by reference) after the call
$syntaxErrors = $null
$tokens = $null
# parse the file
$ast = [System.Management.Automation.Language.Parser]::ParseFile($Path, [ref] $tokens, [ref]$syntaxErrors)
When you run this code, you get three pieces of information about your script:
At first glance, though, the information returned in $AST may seem disappointing. Where are all the contextual insights?
The AST describes relationships in your script using various types. Once you understand these, you can better appreciate its tremendous value.
Add this line to the code above to reveal all AST node types:
$ast.FindAll({$true}, $true) | ForEach-Object { $_.GetType().Name }
It returns the type names of all AST components found in the script specified by $path. To gain meaningful insights, make sure to specify a PowerShell script with a substantial amount of code
This is what the output could look like:
ScriptBlockAst
NamedBlockAst
FunctionDefinitionAst
ScriptBlockAst
ParamBlockAst
AttributeAst
ParameterAst
AttributeAst
NamedAttributeArgumentAst
ConstantExpressionAst
NamedAttributeArgumentAst
ConstantExpressionAst
NamedAttributeArgumentAst
ConstantExpressionAst
TypeConstraintAst
VariableExpressionAst
ParameterAst
AttributeAst
NamedAttributeArgumentAst
ConstantExpressionAst
NamedAttributeArgumentAst
ConstantExpressionAst
TypeConstraintAst
VariableExpressionAst
ParameterAst
AttributeAst
NamedAttributeArgumentAst
ConstantExpressionAst
TypeConstraintAst
VariableExpressionAst
ConstantExpressionAst
NamedBlockAst
TryStatementAst
StatementBlockAst
AssignmentStatementAst
VariableExpressionAst
CommandExpressionAst
InvokeMemberExpressionAst
The AST begins at the top of your script with a ScriptBlockAst, followed by more specific types that describe the code in detail. For example, a ParameterAst describes a param() block, and a VariableExpressionAst describes a variable assignment.
Upon closer inspection, you'll see an InvokeMemberExpressionAst() because the script in the example calls a .NET method. While the simple tokenizer can only return the names of methods used in your script, the AST provides much more detail, which we will explore in Part 4.
Unleash the full potential of PowerShell with our handy poster. Whether you're a beginner or a seasoned pro, this cheat sheet is designed to be your go-to resource for the most important and commonly used cmdlets.
The poster is available for download and in paper form.
May 14, 2025 by Aleksandar Nikolić and Dr. Tobias Weltner
PowerShell has full access to the .NET Framework and can therefore utilize all the graphical functions available in...
May 9, 2025 by Aleksandar Nikolić and Dr. Tobias Weltner
Scripts that run unattended in the background do not need user interfaces. However, scripts can also serve as tools for...
Apr 30, 2025 by Aleksandar Nikolić and Dr. Tobias Weltner
In the previous part, we attempted to create a tool that lists all .NET methods used in a script. While this worked...
Tobias Weltner and Aleksandar Nikolić joinly wrote the blog post series 'Tobias&Aleksandar's PowerShell tips'. So we introduce both of them here:
----------------------------
Aleksandar Nikolić is a Microsoft Azure MVP and co-founder of PowerShellMagazine.com, the ultimate online source for PowerShell enthusiasts. With over 18 years of experience in system administration, he is a respected trainer and speaker who travels the globe to share his knowledge and skills on Azure, Entra, and PowerShell. He has spoken at IT events such as Microsoft Ignite, ESPC, NIC, CloudBrew, NTK, and PowerShell Conference Europe.
----------------------------
Tobias is a long-time Microsoft MVP and has been involved with the development of PowerShell since its early days. He invented the PowerShell IDE "ISESteroids", has written numerous books on PowerShell for Microsoft Press and O'Reilly, founded the PowerShell Conference EU (psconf.eu), and is currently contributing to the advancement of PowerShell as member in the "Microsoft Cmdlet Working Group". Tobias shares his expertise as a consultant in projects and as a trainer in in-house trainings for numerous companies and agencies across Europe.