Last active
March 8, 2023 12:52
-
-
Save jdhitsolutions/65070cd51b5cfb572bc6375f67bcbc3d to your computer and use it in GitHub Desktop.
A proof of concept to add and get PowerShell meta data information
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<!-- | |
format type data generated 01/27/2020 10:30:02 by BOVINE320\Jeff | |
--> | |
<Configuration> | |
<ViewDefinitions> | |
<View> | |
<!--Created 01/27/2020 10:30:02 by BOVINE320\Jeff--> | |
<Name>default</Name> | |
<ViewSelectedBy> | |
<TypeName>PSFunctionInfo</TypeName> | |
</ViewSelectedBy> | |
<TableControl> | |
<!--Delete the AutoSize node if you want to use the defined widths.--> | |
<!-- <AutoSize /> --> | |
<TableHeaders> | |
<TableColumnHeader> | |
<Label>Name</Label> | |
<Width>35</Width> | |
<Alignment>left</Alignment> | |
</TableColumnHeader> | |
<TableColumnHeader> | |
<Label>Version</Label> | |
<Width>10</Width> | |
<Alignment>left</Alignment> | |
</TableColumnHeader> | |
<TableColumnHeader> | |
<Label>Source</Label> | |
<Width>30</Width> | |
<Alignment>left</Alignment> | |
</TableColumnHeader> | |
<TableColumnHeader> | |
<Label>Module</Label> | |
<Width>30</Width> | |
<Alignment>left</Alignment> | |
</TableColumnHeader> | |
</TableHeaders> | |
<TableRowEntries> | |
<TableRowEntry> | |
<TableColumnItems> | |
<!-- | |
By default the entries use property names, but you can replace them with scriptblocks. | |
<ScriptBlock>$_.foo /1mb -as [int]</ScriptBlock> | |
--> | |
<TableColumnItem> | |
<PropertyName>Name</PropertyName> | |
</TableColumnItem> | |
<TableColumnItem> | |
<PropertyName>Version</PropertyName> | |
</TableColumnItem> | |
<TableColumnItem> | |
<PropertyName>Source</PropertyName> | |
</TableColumnItem> | |
<TableColumnItem> | |
<PropertyName>Module</PropertyName> | |
</TableColumnItem> | |
</TableColumnItems> | |
</TableRowEntry> | |
</TableRowEntries> | |
</TableControl> | |
</View> | |
</ViewDefinitions> | |
</Configuration> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define an object class for the Get-PScriptInfo commmand | |
class PSFunctionInfo { | |
[string]$Name | |
[version]$Version | |
[string]$Description | |
[string]$Author | |
[string]$Source | |
[string]$Module | |
[string]$CompanyName | |
[string]$Copyright | |
[guid]$Guid | |
[string[]]$Tags | |
[datetime]$LastUpdate | |
[string]$Commandtype | |
PSFunctionInfo($Name, $Source) { | |
$this.Name = $Name | |
$this.Source = $Source | |
} | |
PSFunctionInfo($Name,$Author, $Version,$Source,$Description,$Module,$CompanyName,$Copyright,$Tags,$Guid,$LastUpdate,$Commandtype) { | |
$this.Name = $Name | |
$this.author = $Author | |
$this.Version = $Version | |
$this.Source = $Source | |
$this.Description = $Description | |
$this.Module = $Module | |
$this.CompanyName = $CompanyName | |
$this.Copyright = $Copyright | |
$this.Tags = $Tags | |
$this.guid = $Guid | |
$this.LastUpdate = $LastUpdate | |
$this.CommandType = $Commandtype | |
} | |
} | |
Function New-PSFunctionInfo { | |
#insert some metadata into a function | |
<# PSFunctionInfo | |
Version 1.1.0 | |
Author Jeffery Hicks | |
CompanyName JDH Information Technology Solutions, Inc. | |
Copyright 2020 | |
Description Create function metadata | |
Guid 23fa4b13-d303-4d2f-8b99-4d3038db3365 | |
Tags Function,metadata | |
LastUpdate 01/25/2020 17:01:40 | |
Source C:\scripts\PSFunctionInfo.ps1 | |
#> | |
[cmdletbinding(SupportsShouldProcess)] | |
Param( | |
[Parameter(Position = 0, Mandatory, HelpMessage = "Specify name of the function")] | |
[ValidateNotNullOrEmpty()] | |
[string]$Name, | |
[Parameter(Mandatory, HelpMessage = "Specify the path that contains the function")] | |
[ValidateNotNullOrEmpty()] | |
[ValidateScript( {Test-Path $_})] | |
[string]$Path, | |
[string]$Author = [System.Environment]::UserName, | |
[string]$CompanyName, | |
[string]$Copyright, | |
[string]$Description, | |
[string]$Version = "1.0.0", | |
[guid]$Guid = $(([guid]::NewGuid()).guid), | |
[string[]]$Tags, | |
[datetime]$Updated = $(Get-Date), | |
[Parameter(HelpMessage = "Copy the metadata to the clipboard. The file is left untouched.")] | |
[alias("clip")] | |
[switch]$ToClipboard | |
) | |
Begin { | |
Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting $($myinvocation.mycommand)" | |
} #begin | |
Process { | |
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Processing $Name in $Path with this metadata" | |
$info = @" | |
<# PSFunctionInfo | |
Version $Version | |
Author $Author | |
CompanyName $CompanyName | |
Copyright $Copyright | |
Description $Description | |
Guid $Guid | |
Tags $($Tags -join ",") | |
LastUpdate $Updated | |
Source $(Convert-Path $Path) | |
#> | |
"@ | |
Write-Verbose $info | |
if ($ToClipboard) { | |
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Copying to metadata to clipboard" | |
if ($pscmdlet.shouldprocess("function metadata", "Copy to clipboard")) { | |
Set-Clipboard -value $info | |
} | |
} | |
else { | |
#get the contents of the script file | |
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting the file contents" | |
$c = Get-Content -Path $path | |
#find the line that begins the function | |
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Finding the line containing Function $Name" | |
$m = $c | Select-String "Function $Name" | |
if ($m.Line) { | |
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Found on line $($m.linenumber)" | |
$ln = $m.LineNumber - 1 | |
#create a temporary file | |
$tmp = [System.IO.Path]::GetTempFileName() | |
#copy lines of the file up to the function definition line | |
$c[0..$ln] | Out-File -FilePath $tmp -whatIf:$false | |
#add the function info metadata | |
$Info | Out-File -FilePath $tmp -Append -whatif:$False | |
#go to the next line | |
$ln++ | |
#copy the rest of the file to the temp file | |
$c[$ln..($c.Length)] | Out-File -FilePath $tmp -Append -whatif:$false | |
#copy the temp file to the new file | |
if ($pscmdlet.shouldprocess($Path, "Update function info for $Name")) { | |
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Writing updated file" | |
Copy-Item -Path $tmp -Destination $path -Force | |
} | |
} | |
else { | |
Write-Warning "Could not find the function $name in $Path." | |
} | |
} #else process the file | |
} #process | |
End { | |
#clean up the temp file | |
If ($tmp -AND (Test-Path $tmp)) { | |
Remove-Item $tmp -whatif:$False | |
} | |
Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending $($myinvocation.mycommand)" | |
} #end | |
} #close New-PSFunctionInfo | |
Function Get-PSFunctionInfo { | |
#get metadata from loaded functions | |
<# PSFunctionInfo | |
Version 2.1.0 | |
Author Jeffery Hicks | |
CompanyName JDH Information Technology Solutions, Inc. | |
Copyright 2020 | |
Description get function metadata | |
Guid 79fba8b7-6323-4ffa-abf8-25537ef897a3 | |
Tags Function,metadata | |
LastUpdate 1/27/2020 12:23:52 PM | |
Source C:\scripts\PSFunctionInfo.ps1 | |
#> | |
[cmdletbinding()] | |
[outputtype("PSFunctionInfo")] | |
Param( | |
[Parameter(Position = 0, HelpMessage = "Specify the name of a function. The default is all",ValueFromPipeline,ValueFromPipelineByPropertyName)] | |
[string]$Name = "*" | |
) | |
Begin { | |
Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting $($myinvocation.mycommand)" | |
#a regex pattern that will be used to parse the metadaa from the function definition | |
[regex]$rx = "(?<property>\w+)\s+(?<value>.*)" | |
} #begin | |
Process { | |
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting loaded function(s): $Name" | |
$functions = Get-ChildItem -path Function:\$Name | |
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Found $($functions.count) functions" | |
Foreach ($fun in $functions) { | |
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Processing $($fun.name)" | |
$definition = $fun.definition -split "`n" | |
$m = $definition | Select-String -Pattern "#(\s+)?PSFunctionInfo" | |
if ($m.count -gt 1) { | |
Write-Warning "Multiple matches found for PSFunctionInfo. Will only process the first one." | |
} | |
if ($m) { | |
#get the starting line number | |
$i = $m[0].LineNumber | |
$meta = While ($definition[$i] -notmatch "#\>") { | |
$raw = $definition[$i] | |
if ($raw -match "\w+") { | |
$raw | |
} | |
$i++ | |
} | |
#Define a hashtable that will eventually become a custom object | |
$h = @{ | |
Name = $fun.name | |
CommandType = $fun.CommandType | |
Module = $fun.Module | |
} | |
#parse the metadata using regular expressions | |
for ($i = 0; $i -lt $meta.count; $i++) { | |
$groups = $rx.Match($meta[$i]).groups | |
$h.add($groups[1].value, $groups[2].value.trim()) | |
} | |
#check for required properties | |
if (-Not ($h.ContainsKey("Source"))) { | |
$h.add("Source","") | |
} | |
if (-Not ($h.ContainsKey("version"))) { | |
$h.add("Version", "") | |
} | |
$h | Out-String | Write-Verbose | |
#write the custom object to the pipeline | |
$fi = New-Object -typename PSFunctionInfo -ArgumentList $h.name,$h.version | |
#update the object with hash table properties | |
foreach ($key in $h.keys) { | |
Write-Verbose "Updating $key" | |
$fi.$key = $h.$key | |
} | |
$fi | |
#clear the variable so it doesn't get reused | |
Remove-Variable m,h | |
} #if metadata found | |
else { | |
#insert the custom type name and write the object to the pipeline | |
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] No function metadata found for $($fun.name)." | |
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Creating a PSFunctionInfo object " | |
$fi = New-Object PSFunctionInfo -ArgumentList $fun.name,$fun.source | |
$fi.version = $fun.version | |
$fi.module = $fun.Module | |
$fi.Commandtype = $fun.CommandType | |
$fi.Description = $fun.Description | |
$fi | |
} | |
} #foreach | |
} #process | |
End { | |
Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending $($myinvocation.mycommand)" | |
} #end | |
} #close Get-PSFunctionInfo | |
Update-FormatData $PSScriptRoot\PSFunctionInfo.format.ps1xml | |
Update-TypeData -appendpath $PSScriptRoot\PSFunctionInfo.types.ps1xml | |
<# | |
PS C:\> Get-PSFunctionInfo get* | Where author | |
Name Version Source Module | |
---- ------- ------ ------ | |
Get-QOTD 1.0.0 C:\scripts\Get-QOTD.ps1 | |
Get-Status 1.0.0 C:\scripts\getstat.ps1 | |
Get-UTCString 1.0.0 C:\scripts\JDH-Functions.ps1 | |
Get-DiskFree 1.0.0 C:\scripts\JDH-Functions.ps1 | |
Get-LastBoot 1.0.0 C:\scripts\JDH-Functions.ps1 | |
Get-MyFunctions 1.0.0 C:\scripts\JDH-Functions.ps1 | |
Get-PSFunctionInfo 2.1.0 C:\scripts\PSFunctionInfo.ps1 | |
PS C:\> get-psfunctioninfo get-qotd | select * | |
Name : Get-QOTD | |
Version : 1.0.0 | |
Source : C:\scripts\Get-QOTD.ps1 | |
CompanyName : JDH IT Solutions | |
Copyright : 2020 | |
Description : Get a quote of the day | |
LastUpdate : 1/27/2020 11:46:19 AM | |
Module : | |
Author : Jeff | |
Guid : 16b5d672-4778-46d9-bbe5-08e7860e4e8a | |
Tags : {Web,profile} | |
Commandtype : Function | |
PS C:\> get-psfunctioninfo get-f* | |
Name Version Source Module | |
---- ------- ------ ------ | |
Get-FileHash 3.1.0.0 Microsoft.PowerShell.Utility Microsoft.PowerShell.Utility | |
Get-Foo 1.0.0 d:\temp\foo.ps1 | |
#> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8" ?> | |
<Types> | |
<Type> | |
<Name>PSFunctionInfo</Name> | |
<Members> | |
<PropertySet> | |
<Name>AuthorInfo</Name> | |
<ReferencedProperties> | |
<Name>Name</Name> | |
<Name>Version</Name> | |
<Name>Source</Name> | |
<Name>CompanyName</Name> | |
<Name>Copyright</Name> | |
<Name>Description</Name> | |
<Name>LastUpdate</Name> | |
</ReferencedProperties> | |
</PropertySet> | |
<PropertySet> | |
<Name>DefaultDisplayPropertySet</Name> | |
<ReferencedProperties> | |
<Name>Name</Name> | |
<Name>Version</Name> | |
<Name>Source</Name> | |
<Name>Module</Name> | |
</ReferencedProperties> | |
</PropertySet> | |
</Members> | |
</Type> | |
</Types> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The purpose of this code is to provide a way to get version and other metadata information for functions loaded into your PowerShell session that may not belong to a module. I have a number of stand-alone functions and I'd like to have version and source information. The code isn't concerned with loading, running or finding functions. It queries whatever is in the Function: psdrive. if the function belongs to a module, then I'll use the module version and source.