Referencing powershell functions from script modules - powershell

Is there a shorthand I can write in PowerShell whereby I can only reference my own functions from modules that I have loaded?
For Example:
I have module that I have loaded by doing
Import-Module Worktasks
Now as the module gets bigger I will start to forget about some of the earlier functions that I wrote. I can, of course, do something like this:
(Get-Module -Name worktasks | % ExportedCommands).Values.Name
But this will only list the functions that I have wrote but not their parameters. So it would be nice if I could narrow down the results pulled by Intellisense if I could directly reference functions/cmdlets from individual modules in my code.
I am using PowerShell 4.0 in my environment.
Thanks.

You can get the functions from a specific module, e.g. worktasks, like this:
(Get-Module -Name worktasks).ExportedCommands.Values
By default you'll get a limited amount of information but there is more. If you select everything, then you'll see more information including the parameter sets:
(Get-Module -Name worktasks).ExportedCommands.Values | select *
If you just want the names and the parameter sets, then this will do just that:
(Get-Module -Name worktasks).ExportedCommands.Values | select Name, ParameterSets

Related

Get all references to a given PowerShell module

Is there a way to find a list of script files that reference a given module (.psm1)? In other words, get all files that, in the script code, use at least 1 of the cmdlets defined in the module.
Obviously because of PowerShell 3.0 and above, most of my script files don't have an explicit Import-Module MODULE_NAME in the code somewhere, so I can't use that text to search on.
I know I can use Get-ChildItem -Path '...' -Recurse | Select-String 'TextToSearchFor' to search for a particular string inside of files, but that's not the same as searching for any reference to any cmdlet of a module. I could do a search for every single cmdlet in my module, but I was wondering if there is a better way.
Clarification: I'm only looking inside of a controlled environment where I have all the scripts in one file location.
Depending on the scenario, the callstack could be interesting to play around with. In that case you need to modify the functions which you want to find out about to gather information about the callstack at runtime and log it somewhere. Over time you might have enough logs to make some good assumptions.
function yourfunction {
$stack = Get-PSCallStack
if ($stack.Count -gt 1) {
$stack[1] # log this to a file or whatever you need
}
}
This might not work at all in your scenario, but I thought I throw it in there as an option.

How to pipe objects to a specific parameter

I want to list all my PowerShell functions from one directory. The following command works:
Get-ChildItem -Path ($env:USERPROFILE + "\somewhere\*.psm1") -Recurse | ForEach-Object {Get-Command -Module $_.BaseName}
Now I tried to pipe the output from Get-ChildItem directly to the cmdlet Get-Command. Something like this, which does not work:
Get-ChildItem -Path ($env:USERPROFILE + "\somewhere\*.psm1") -Recurse | Get-Command -Module {$_.BaseName}
Obviously, I do not really understand how to pipe the object from Get-ChildItem in the correct way to the parameter -Module in Get-Command.
I have two questions:
Do you have a hint how to pipe correctly?
Is it possible to pipe to a specific parameter like -Module or is the object always handed over to one default parameter?
Parameters can be bound in four different ways:
By location in the argument list, e.g., Get-ChildItem C:\ (only certain parameters)
By name in the argument list, e.g. Get-ChildItem -Path C:\
By value from the pipeline, e.g. 1..5 | Get-Random (only certain parameters)
By name from the pipeline, e.g. 'C:\Windows' | Get-ChildItem (only certain parameters)
You can inspect the various ways of parameter binding via Get-Help <command> -Parameter *. You can then see that Get-Command allows the Module parameter to be bound only by property name:
-Module [<String[]>]
Specifies an array of modules. ...
Required? false
Position? named
Default value none
Accept pipeline input? True (ByPropertyName)
Accept wildcard characters? false
So the input has to be an object that has a Module property, to allow binding. In your case you thus need an additional step in between:
Get-ChildItem -Path ($env:USERPROFILE + "\somewhere\*.psm1") -Recurse |
Select-Object #{l='Module';e={$_.Basename}} |
Get-Command
Now, this instance here is something that's a bit annoying, since the Module parameter is bound by property name, but most things don't give you an object with a Module property. Heck, even Get-Module doesn't have that, since the returned object uses Name as the property name, so you can't even do
Get-Module | Get-Command
However, in many other places (notably concerning paths) work very well automatically. And if you can control your input objects, e.g. when reading from CSV or other data sources, you can end up with rather nice and concise code.
EDIT: Ansgar Wiechers notes that, while this should work, it doesn't, actually. This may be a shortfall of PowerShell's parameter binding algorithm (which is quite complex, as seen above, and we never got it to work correctly in Pash either), or maybe the Get-Command cmdlet has parameters described in a way that simply cannot allow binding because of reasons.

format list of synopsis for a custom list of functions

I have a powershell script containing several functions representing tasks. I would like to format a list of those functions with for each function its name and the synopsis provided in the documentation.
For one function Foo:
Get-Help Foo | Format-Table -Property Name, Synopsis
I don't know how to make it work with multiple functions. I am having troubles with the power syntax. I don't know how to declare a list of function because Foo, Bar is a syntax error. I also tried to list the names of the function as strings and convert those to the corresponding objects but I failed to do so.
How to print the name and synopsis for a custom list of functions?
As you figured out yourself, the Get-Help (alias help) cmdlet doesnt expose a parameter set with multiple -name parameters. However, You can define an array of your functions, iterate over it and call the Get-Help for each of them. Example:
#('Get-Content', 'Get-ChildItem') | foreach { help $_ } | Format-Table -Property Name, Synopsis
Output:
Name Synopsis
---- --------
Get-Content Gets the content of the item at the specified location.
Get-ChildItem Gets the items and child items in one or more specified locations.

Calling all functions with certain signature

I have a module (psm1 file), where I have a set of function. I need to call all functions in that module, which accept one parameter (an array of PSToken). Obviously, I can directly call all functions, but I need that changes in the module, didn't require changes in the calling script. How can I do this?
You can use the Get-Command commandlet to iterate over the functions in a given module, and then call each function using dot-sourcing:
Import-Module MyPowershellModule
$arrPsToken = #($token1, token2, token3)
Get-Command -Module MyPowershellModule |
Select-Object -ExpandProperty Name |
ForEach-Object {
. "$_" $arrPsToken
}
Keep in mind that this code assumes that all functions have the same signature, which is risky.

PowerShell: programmatically access script documentation

Is there a way to programmatically load the documentation of a .ps1 script file outside of commands like get-help? In other words, can text defined under .SYNOPSIS, .DESCRIPTION, etc. be accessed programmatically other than filtering the string output of get-help itself?
Among other things, I'm trying to find where I have gaps in documentation coverage in my script library. I'd also like to be able to display lists of certain scripts with their synopsis attached.
Yes, those are all accessible. Get-Help returns (just like any other cmdlet) an object, and the default rendering of that object is what you see in the console.
However, if you pump get-help's output through format-list, like this:
get-help get-childitem | format-list
You'll get a list of name-value pairs of the properties. To get the synopsis, you can do the following:
get-help get-childitem |select-object -property synopsis
And the output:
Synopsis
--------
Gets the files and folders in a file system drive.
If your .ps1 file has no cmdlets defined in it (your comment-based help covers the whole script), get-help file.ps1|select synopsis should work. Otherwise, you'll need to "dot-source" the files to load the cmdlet definitions into memory, then use get-help as above.