Fajela Tajkiya
Fajela Tajkiya

Reputation: 694

How to get all functions defined in a .ps1 file?

I have some functions defined in a .ps1 file, which I can import them by a dot operator (. .\script.ps1). After that, I can use these functions in my powershell terminal. If it's a module, I could use the gcm -module ... command to get all commands from the module. But here it's a file, not a module. Is there a way for me to list all functions defined in the file? Like gcm -file "script.ps1".

Upvotes: 4

Views: 902

Answers (2)

forumulator
forumulator

Reputation: 875

A more advanced use case is when you want to find a Command (i.e function with CmdLetBinding) defined in the current script, by name:

# eg. C:\Users\username\scriptName.ps1
$MyScriptPath = $MyInvocation.MyCommand.Definition.ToString()

# Filter the commands available in the current context.
$Cmd = Get-Command -Type Function |
    Where-Object { $_.ScriptBlock.Ast.Body.ParamBlock.Attributes.TypeName.Name -eq 'CmdLetBinding' } |
        Where-Object { $_.ScriptBlock.File -eq $MyScriptPath } |
            Where-Object { $_.Name -eq $CommandName }

This should give you a list of FunctionInfo objects that have all the metadata about the commands, including the ScriptBlock. After finding/validating, you can execute the command simply using & $CommandName

Upvotes: 1

mklement0
mklement0

Reputation: 438208

You can achieve this indirectly, by querying the .File property of the .ScriptBlock property of function objects (System.Management.Automation.FunctionInfo):

  • To match by script file name only:

    Get-Command -Type Function | 
      Where-Object { $_.ScriptBlock.File -like '*[\/]script.ps1' } | 
      ForEach-Object Name
    
  • To avoid ambiguity, you should match against the full script path, not just the file name, e.g.:

    Get-Command -Type Function | 
      Where-Object { $_.ScriptBlock.File -eq 'C:\path\to\script.ps1' } | 
      ForEach-Object Name
    
    • Note that .File always reports the path as a file-system-native one, even if you dot-sourced the script via a PowerShell-only drive. When in doubt, use Convert-Path on a path in order to convert it to a file-system-native one.

Santiago Squarzon points to an interesting variation of your task: Get the list of all functions directly from a script file (.ps1), irrespective of whether the script has been dot-sourced or not (i.e., irrespective of whether the functions have (already) been defined in the session):

# Returns the names of all functions defined in specified script
(Get-Command 'C:\path\to\script.ps1').ScriptBlock.Ast.FindAll(
  { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] },
  $false # parameter `searchNestedScriptBlocks`
).Name

See also:

Upvotes: 6

Related Questions