Commands/Get-Demo.ps1
function Get-Demo { <# .SYNOPSIS Gets Demos .DESCRIPTION Gets PowerShell Demos. Demos located in ShowDemo and all modules that tag ShowDemo will be automatically discovered. .LINK Import-Demo .EXAMPLE Get-Demo #> [CmdletBinding(DefaultParameterSetName='LoadedDemos')] param( # The name of the demo [Parameter(ValueFromPipelineByPropertyName,ParameterSetName='LoadedDemos')] [string] $DemoName, # The path to the demo file. [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='DemoFile')] [Alias('FullName', 'DemoFile', 'File', 'Source')] $DemoPath, # A Demo Script block. [Parameter(Mandatory,ValueFromPipeline,ParameterSetName='DemoScript')] [scriptblock] $DemoScript ) begin { $myModule = $MyInvocation.MyCommand.ScriptBlock.Module } process { if ($PSCmdlet.ParameterSetName -in 'DemoFile', 'DemoScript') { Import-Demo @psboundParameters return } $filePaths = @( if ($myModule) { $moduleRelationships = @( $MyModuleName, $myModule = if ($myModule -is [string]) { $myModule, (Get-Module $myModule) } elseif ($myModule -is [Management.Automation.PSModuleInfo]) { $myModule.Name, $myModule } else { Write-Error "$myModule must be a [string] or [Management.Automation.PSModuleInfo]" } #region Search for Module Relationships if ($myModule -and $MyModuleName) { foreach ($loadedModule in Get-Module) { # Walk over all modules. if ( # If the module has PrivateData keyed to this module $loadedModule.PrivateData.$myModuleName ) { # Determine the root of the module with private data. $relationshipData = $loadedModule.PrivateData.$myModuleName [PSCustomObject][Ordered]@{ PSTypeName = 'Module.Relationship' Module = $myModule RelatedModule = $loadedModule PrivateData = $loadedModule.PrivateData.$myModuleName } } elseif ($loadedModule.PrivateData.PSData.Tags -contains $myModuleName) { [PSCustomObject][Ordered]@{ PSTypeName = 'Module.Relationship' Module = $myModule RelatedModule = $loadedModule PrivateData = @{} } } } } #endregion Search for Module Relationships ) foreach ($relationship in $moduleRelationships) { $relationship.RelatedModule | Split-Path } } else { $PSScriptRoot } ) $allDemoFiles = @($( # Collect all items into an input collection $inputCollection = @(($filePaths |& { param([switch]$IncludeApplications) process { $inObj = $_ # Since we're looking for commands, pass them thru directly if ($inObj -is [Management.Automation.CommandInfo]) { $inObj } # If the input object is ps1 fileinfo elseif ($inObj -is [IO.FileInfo] -and $inObj.Extension -eq '.ps1') { # get that exact command. $ExecutionContext.SessionState.InvokeCommand.GetCommand($inObj.Fullname, 'ExternalScript') } # If the input is a string or path elseif ($pathItem -is [IO.FileInfo] -and $IncludeApplications) { $ExecutionContext.SessionState.InvokeCommand.GetCommand($pathItem.FullName, 'Application') } elseif ($inObj -is [string] -or $inObj -is [Management.Automation.PathInfo]) { # resolve it foreach ($resolvedPath in $ExecutionContext.SessionState.Path.GetResolvedPSPathFromPSPath("$inObj")) { # and get the literal item $pathItem = Get-item -LiteralPath $resolvedPath # if it is a .ps1 fileinfo if ($pathItem -is [IO.FileInfo] -and $pathItem.Extension -eq '.ps1') { # get that exact command $ExecutionContext.SessionState.InvokeCommand.GetCommand($pathItem.FullName, 'ExternalScript') } elseif ($pathItem -is [IO.FileInfo] -and $IncludeApplications) { $ExecutionContext.SessionState.InvokeCommand.GetCommand($pathItem.FullName, 'Application') } elseif ($pathItem -is [IO.DirectoryInfo]) { # Otherwise, get all files beneath the path foreach ($pathItem in @(Get-ChildItem -LiteralPath $pathItem -File -Recurse)) { # that are .ps1 if ($pathItem.Extension -eq '.ps1') { # and return them directly. $ExecutionContext.SessionState.InvokeCommand.GetCommand($pathItem.FullName, 'ExternalScript') } elseif ($IncludeApplications) { $ExecutionContext.SessionState.InvokeCommand.GetCommand($pathItem.FullName, 'Application') } } } } } } })) # Since filtering conditions have been passed, we must filter item-by-item $filteredCollection = :nextItem foreach ($item in $inputCollection) { # we set $this, $psItem, and $_ for ease-of-use. $this = $_ = $psItem = $item if (-not $( $_.Name -match '^(?>demo|walkthru)\.ps1$' -or $_.Name -match '\.(?>demo|walkthru)\.ps1$' )) { continue nextItem } $item } # Walk over each item in the filtered collection foreach ($item in $filteredCollection) { # we set $this, $psItem, and $_ for ease-of-use. $this = $_ = $psItem = $item if ($item.pstypenames.insert -and $item.pstypenames -notcontains 'demofiles') { $item.pstypenames.insert(0, 'demofiles') } $item } )) if ($filePaths -ne $pwd) { $currentDirectoryDemos = Get-ChildItem -Filter *.ps1 -Path $pwd | Where-Object { $_.Name -match '^(?>demo|walkthru)\.ps1$' -or $_.Name -match '\.(?>demo|walkthru)\.ps1$' } $allDemoFiles += @( $( # Collect all items into an input collection $inputCollection = @(($currentDirectoryDemos |& { param([switch]$IncludeApplications) process { $inObj = $_ # Since we're looking for commands, pass them thru directly if ($inObj -is [Management.Automation.CommandInfo]) { $inObj } # If the input object is ps1 fileinfo elseif ($inObj -is [IO.FileInfo] -and $inObj.Extension -eq '.ps1') { # get that exact command. $ExecutionContext.SessionState.InvokeCommand.GetCommand($inObj.Fullname, 'ExternalScript') } # If the input is a string or path elseif ($pathItem -is [IO.FileInfo] -and $IncludeApplications) { $ExecutionContext.SessionState.InvokeCommand.GetCommand($pathItem.FullName, 'Application') } elseif ($inObj -is [string] -or $inObj -is [Management.Automation.PathInfo]) { # resolve it foreach ($resolvedPath in $ExecutionContext.SessionState.Path.GetResolvedPSPathFromPSPath("$inObj")) { # and get the literal item $pathItem = Get-item -LiteralPath $resolvedPath # if it is a .ps1 fileinfo if ($pathItem -is [IO.FileInfo] -and $pathItem.Extension -eq '.ps1') { # get that exact command $ExecutionContext.SessionState.InvokeCommand.GetCommand($pathItem.FullName, 'ExternalScript') } elseif ($pathItem -is [IO.FileInfo] -and $IncludeApplications) { $ExecutionContext.SessionState.InvokeCommand.GetCommand($pathItem.FullName, 'Application') } elseif ($pathItem -is [IO.DirectoryInfo]) { # Otherwise, get all files beneath the path foreach ($pathItem in @(Get-ChildItem -LiteralPath $pathItem -File -Recurse)) { # that are .ps1 if ($pathItem.Extension -eq '.ps1') { # and return them directly. $ExecutionContext.SessionState.InvokeCommand.GetCommand($pathItem.FullName, 'ExternalScript') } elseif ($IncludeApplications) { $ExecutionContext.SessionState.InvokeCommand.GetCommand($pathItem.FullName, 'Application') } } } } } } })) # Walk over each item in the filtered collection foreach ($item in $inputCollection) { # we set $this, $psItem, and $_ for ease-of-use. $this = $_ = $psItem = $item if ($item.pstypenames.insert -and $item.pstypenames -notcontains 'demofiles') { $item.pstypenames.insert(0, 'demofiles') } $item } ) ) } $allDemoFiles | Where-Object Name -like "*$demoName*" | Import-Demo } } |