I'm trying to write a script that needs to be detect what the ArgumentList of a PowerShell module is. Is there any way of finding this out?
The end game is to be able to use this to create a simple DI container for loading modules.
I'm trying to write a script that needs to be detect what the ArgumentList of a PowerShell module is. Is there any way of finding this out?
The end game is to be able to use this to create a simple DI container for loading modules.
You can use the AST parser to show you the param() block of the module file. Maybe use Get-Module to find out information about where the module files are located, then parse those and walk the AST to get the information you're after. Does this seem like something that would be useful?
function Get-ModuleParameterList {
[CmdletBinding()]
param(
[string] $ModuleName
)
$GetModParams = @{
Name = $ModuleName
}
# Files need -ListAvailable
if (Test-Path $ModuleName -ErrorAction SilentlyContinue) {
$GetModParams.ListAvailable = $true
}
$ModuleInfo = Get-Module @GetModParams | select -First 1 # You'll have to work out what to do if more than one module is found
if ($null -eq $ModuleInfo) {
Write-Error "Unable to find information for '${ModuleName}' module"
return
}
$ParseErrors = $null
$Ast = if ($ModuleInfo.RootModule) {
$RootModule = '{0}\{1}' -f $ModuleInfo.ModuleBase, (Split-Path $ModuleInfo.RootModule -Leaf)
if (-not (Test-Path $RootModule)) {
Write-Error "Unable to determine RootModule for '${ModuleName}' module"
return
}
[System.Management.Automation.Language.Parser]::ParseFile($RootModule, [ref] $null, [ref] $ParseErrors)
}
elseif ($ModuleInfo.Definition) {
[System.Management.Automation.Language.Parser]::ParseInput($ModuleInfo.Definition, [ref] $null, [ref] $ParseErrors)
}
else {
Write-Error "Unable to figure out module source for '${ModuleName}' module"
return
}
if ($ParseErrors.Count -ne 0) {
Write-Error "Parsing errors detected when reading RootModule: ${RootModule}"
return
}
$ParamBlockAst = $Ast.Find({ $args[0] -is [System.Management.Automation.Language.ParamBlockAst] }, $false)
$ParamDictionary = [ordered] @{}
if ($ParamBlockAst) {
foreach ($CurrentParam in $ParamBlockAst.Parameters) {
$CurrentParamName = $CurrentParam.Name.VariablePath.UserPath
$ParamDictionary[$CurrentParamName] = New-Object System.Management.Automation.ParameterMetadata (
$CurrentParamName,
$CurrentParam.StaticType
)
# At this point, you can add attributes to the ParameterMetaData instance based on the Attribute
}
}
$ParamDictionary
}
You should be able to give that a module name or the path to a module. It's barely been tested, so there are probably some instances where it won't work. Right now, it returns a dictionary like viewing the 'Parameters' property returned from Get-Command. If you want the attribute information, you'd need to do a little work to build each one.