Skip to content

Instantly share code, notes, and snippets.

@blakedrumm
Last active August 2, 2024 17:23
Show Gist options
  • Save blakedrumm/369a040c2b7edf753b37d35f89093967 to your computer and use it in GitHub Desktop.
Save blakedrumm/369a040c2b7edf753b37d35f89093967 to your computer and use it in GitHub Desktop.
Identifies the required modules for a given PowerShell script by analyzing the cmdlets used within the script.
<#
.SYNOPSIS
Identifies the required modules for a given PowerShell script by analyzing the cmdlets used within the script.
.DESCRIPTION
The Get-RequiredModules function takes a script as input, extracts all the cmdlets used in the script, and determines which modules
these cmdlets belong to. It then returns a unique list of required modules.
.PARAMETER Script
The content of the PowerShell script to analyze for required modules.
.NOTES
Ensure that all necessary modules are installed and available in the environment where the script will be run.
Author:
Blake Drumm ([email protected])
Created:
May 21st, 2024
Modified:
August 2nd, 2024
.LINK
Azure Automation Personal Blog: https://blakedrumm.com/
#>
param (
[string]$Script
)
function Get-RequiredModules {
param (
[Parameter(Mandatory = $true)]
[string]$Script
)
# List of known Azure Automation internal commands
$azureAutomationInternalCommands = @(
"Get-AutomationConnection",
"Get-AutomationCertificate",
"Get-AutomationPSCredential"
)
# Parse the script to get the AST
$ast = [System.Management.Automation.Language.Parser]::ParseInput($Script, [ref]$null, [ref]$null)
# Find all functions defined in the script
$definedFunctions = $ast.FindAll({ $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }, $true)
$functionNames = $definedFunctions | ForEach-Object { $_.Name }
# Extract unique cmdlets used in the script
$uniqueCmdlets = $ast.FindAll({ $args[0] -is [System.Management.Automation.Language.CommandAst] }, $true) |
ForEach-Object { $_.GetCommandName() } |
Select-Object -Unique
# Initialize a hash table to store cmdlet to module mapping
$cmdletModuleMap = @{}
foreach ($cmdlet in $uniqueCmdlets) {
if ($functionNames -contains $cmdlet) {
$cmdletModuleMap[$cmdlet] = "InternalFunction"
} elseif ($azureAutomationInternalCommands -contains $cmdlet) {
$cmdletModuleMap[$cmdlet] = "AzureAutomationInternal"
} else {
try {
$command = Get-Command -Name $cmdlet -ErrorAction Stop
if ($command -and $command.Module -and $command.Module.Name) {
$cmdletModuleMap[$cmdlet] = $command.Module.Name
} elseif ($command -and $command.Module.Name -eq $null) {
# This handles built-in commands
$cmdletModuleMap[$cmdlet] = "Microsoft.PowerShell.Core"
} else {
Write-Verbose "Cmdlet '$cmdlet' not found or has no associated module."
$cmdletModuleMap[$cmdlet] = "{Unknown}"
}
} catch {
Write-Verbose "Cmdlet '$cmdlet' not found."
$cmdletModuleMap[$cmdlet] = "{Unknown}"
}
}
}
# Get the unique list of required modules
$requiredModules = $cmdletModuleMap.Values | Where-Object { $_ -ne "{Unknown}" -and $_ -ne "InternalFunction" -and $_ -ne "AzureAutomationInternal" } | Select-Object -Unique
return $requiredModules, $cmdletModuleMap
}
# Example ScriptBlock
$scriptblock = {
# Example Script to show required PowerShell modules
#
# Connect to Azure
Connect-AzAccount
# Get the list of Maintenance Configurations
$maintenanceConfigs = Get-AzMaintenanceConfiguration
# Function to get update management status
function Get-AzVMUpdateManagementStatus {
param (
[string]$ResourceGroupName,
[string]$VMName
)
# Get the VM
$vm = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName
if ($vm -ne $null) {
# Check the Update Management status
$status = Get-AzUpdateManagement -ResourceGroupName $ResourceGroupName -VMName $VMName
return $status
} else {
Write-Output "VM $VMName not found in resource group $ResourceGroupName"
return $null
}
}
# Loop through each Maintenance Configuration to get the resource status
foreach ($config in $maintenanceConfigs) {
Write-Output "Checking Maintenance Configuration: $($config.Name)"
# Get the resources linked to the Maintenance Configuration
$resources = Get-AzMaintenanceConfigurationAssignment -ResourceGroupName $config.ResourceGroupName -ConfigurationName $config.Name
foreach ($resource in $resources) {
Write-Output "Checking Resource: $($resource.Name)"
# Get the update management status for each resource
$updateStatus = Get-AzVMUpdateManagementStatus -ResourceGroupName $resource.ResourceGroupName -VMName $resource.Name
if ($updateStatus.Status -eq 'Succeeded') {
Write-Output "Updates installed successfully on $($resource.Name)"
} else {
Write-Output "Updates not installed on $($resource.Name)"
}
}
}
} #End ScriptBlock
# Convert the scriptblock to string for analysis
$scriptContent = $scriptblock.ToString()
# Analyze the script content to determine required modules
$requiredModules, $cmdletModuleMap = Get-RequiredModules -Script $scriptContent -Verbose
Write-Output "Required Modules: $($requiredModules -join ', ')"
# Display the command and their sources
$cmdletModuleMap.GetEnumerator() | Sort-Object Name | Format-Table Name, Value -AutoSize
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment