PSToolLauncher.psm1
|
#Requires -Version 5.1 using namespace System.IO; using namespace System.Management.Automation; # +----------------------------------------------------------------------------------------------------------- # | Public functions # | <# #> function Start-Tool { [CmdletBinding(PositionalBinding = $false)] param( [Parameter(Position = 0, Mandatory)] [string] $ToolKey, [Parameter(ValueFromRemainingArguments)] $Arguments ) begin { Write-Verbose 'BEGIN Start-Tool'; } process { $toolInfo = Get-ToolInstallation $ToolKey; if($toolInfo.IsInstalled -ne $true) { throw [InvalidOperationException] "'$($toolInfo.Definition.$KeyToolName)' is not installed."; } Write-Verbose "Executing '$($toolInfo.Definition.$KeyToolName) version '$($toolInfo.DefaultVersion.Version)'."; & $toolInfo.DefaultVersion.Command $Arguments; Write-Verbose 'SUCCESS Start-Tool'; } end { Write-Verbose 'FINISH Start-Tool'; } } function Start-NotepadPlusPlus { [CmdletBinding(PositionalBinding = $false)] param( [Parameter(ValueFromRemainingArguments)] $Arguments ) process { Write-Verbose 'EXECUTING Start-NotepadPlusPlus.'; Start-Tool -ToolKey $KeyNotepadPlusPlus -Arguments $Arguments; } } function Start-SqlAdmin { [CmdletBinding(PositionalBinding = $false)] param( [Parameter(ValueFromRemainingArguments)] $Arguments ) process { Write-Verbose 'EXECUTING Start-SqlAdmin.'; Start-Tool -ToolKey $KeySqlAdmin -Arguments $Arguments; } } # +----------------------------------------------------------------------------------------------------------- # | Private functions # | function Find-ToolFile { [CmdletBinding(PositionalBinding = $false)] [OutputType([FileInfo])] param( [Parameter(Position = 0, Mandatory, ValueFromPipeline)] [DirectoryInfo[]] $ProductDirectories, [Parameter(Position = 1, Mandatory)] [string[]] $ExecutableNames, [Parameter()] [switch] $FindOnPath ) begin { Write-Verbose 'BEGIN Find-ToolFile.'; $exeNameList = $ExecutableNames -join ', '; } process { $allSearchDirectories = @(); $allSearchDirectories += $ProductDirectories; if($FindOnPath) { $allSearchDirectories += $Env:Path -split ';' ` | Select-Object -Unique ` | Get-Item -ErrorAction SilentlyContinue; } $allSearchDirectories ` | Select-Object -Unique ` | ForEach-Object { Write-Verbose "Searching product directory '$_' for executables '$exeNameList'."; # return Get-ChildItem -Path $_ -File ` | Where-Object { $ExecutableNames -contains $_.Name; } } Write-Verbose 'SUCCESS Find-ToolFile.'; } end { Write-Verbose 'FINISH Find-ToolFile.'; } } function Get-ProgramFilesDirectory { [CmdletBinding(PositionalBinding = $false)] [OutputType([DirectoryInfo])] param() begin { Write-Verbose 'BEGIN Get-ProgramFilesDirectory.'; } process { $toolDirs = Get-ChildItem -Path Env:ProgramFiles* ` | Select-Object -ExpandProperty Value; # return $toolDirs | Select-Object -Unique ` | Get-Item -ErrorAction SilentlyContinue; Write-Verbose 'SUCCESS Get-ProgramFilesDirectory.'; } end { Write-Verbose 'FINISH Get-ProgramFilesDirectory.'; } } function Get-ToolInstallation { [CmdletBinding(PositionalBinding = $false)] [OutputType('PSToolLauncher.Installation')] param( [Parameter(Position = 0, Mandatory)] [string] $ToolKey, [Parameter()] [switch] $Force ) begin { Write-Verbose 'BEGIN Get-ToolInstallation.'; } process { Write-Verbose "Retrieving tool installation information for '$ToolKey'."; if($Force -or $ToolInstallations.ContainsKey($ToolKey) -eq $false) { Write-Verbose "Acquiring installation information for '$ToolKey'."; $toolDef = $ToolDefinitions[$ToolKey]; if($null -eq $toolDef) { throw [InvalidOperation] "Tool '$ToolKey' is not a known common tool, available common tools are: (list of common tools)."; } $productDirectories = & $toolDef.$KeyGetProductDirectory; $findOnPath = $toolDef.$KeyIgnorePath -ne $true; $toolVersions = Find-ToolFile $productDirectories $toolDef.$KeyExecutableNames -FindOnPath:$findOnPath ` | Get-ToolVersion; $ToolInstallations[$ToolKey] = New-ToolInstallation -ToolDefinition $toolDef -ToolVersions $toolVersions; } # return $ToolInstallations[$ToolKey]; Write-Verbose 'SUCCESS Get-ToolInstallation.'; } end { Write-Verbose 'FINISH Get-ToolInstallation.'; } } function Get-ToolVersion { [CmdletBinding(PositionalBinding = $false)] [OutputType('PSToolLauncher.ToolVersion')] param( [Parameter(Position = 0, Mandatory, ValueFromPipeline)] [FileInfo[]] $ToolFiles ) begin { Write-Verbose 'BEGIN Get-ToolVersion.'; } process { $sortableVersionFormat = '{0}{1:D6}.{2:D6}.{3:D6}.{4:D6}.{5:D6}'; $sequenceNumber = $ToolFiles.Length; $ToolFiles | ForEach-Object { Write-Verbose "Get tool version information for executable '$_'."; $versionInfo = $_.VersionInfo; if($null -eq $versionInfo) { $exeDescription = $_.BaseName; $printableVersionNumber = 'Unknown'; $sortableProductVersion = $sortableVersionFormat -f 'X', 0, 0, 0, 0, $sequenceNumber $sortableFileVersion = $sortableVersionFormat -f 'X', 0, 0, 0, 0, $sequenceNumber } else { $exeDescription = $versionInfo.FileDescription; $printableVersionNumber = '{0:D}.{1:D}.{2:D}.{3:D}' -f $versionInfo.ProductMajorPart, ` $versionInfo.ProductMinorPart, ` $versionInfo.ProductBuildPart, ` $versionInfo.ProductPrivatePart; $sortableProductVersion = $sortableVersionFormat -f 'V', $versionInfo.ProductMajorPart, ` $versionInfo.ProductMinorPart, ` $versionInfo.ProductBuildPart, ` $versionInfo.ProductPrivatePart, ` $sequenceNumber; $sortableFileVersion = $sortableVersionFormat -f 'V', $versionInfo.FileMajorPart, ` $versionInfo.FileMinorPart, ` $versionInfo.FileBuildPart, ` $versionInfo.FilePrivatePart, ` $sequenceNumber; } Write-Verbose "Tool '$exeDescription' is version '$printableVersionNumber'."; # return New-Object PSObject -Property @{ Command = (Get-Command $_); Version = $printableVersionNumber; OrderedProductVersion = $sortableProductVersion; OrderedFileVersion = $sortableFileVersion; } ` | ForEach-Object { $_.PSTypeNames.Insert(0, 'PSToolLauncher.ToolVersion'); $_; }; $sequenceNumber--; } Write-Verbose 'SUCCESS Get-ToolVersion.'; } end { Write-Verbose 'FINISH Get-ToolVersion.'; } } function New-ToolDefinition { [CmdletBinding(PositionalBinding = $false)] [OutputType('PSToolLauncher.Definition')] param( [Parameter(Position = 0, Mandatory)] [string] $ToolName, [Parameter(Mandatory)] [string] $NounPrefix, [Parameter(Mandatory)] [string[]] $ExecutableNames, [Parameter()] [CommandInfo] $GetProductDirectory, [Parameter()] [switch] $IgnorePath, [Parameter()] [string[]] $Aliases ) begin { Write-Verbose 'BEGIN New-ToolDefinition.'; } process { Write-Verbose "Creating ToolDefinition for '$ToolName'."; if($null -eq $GetProductDirectory) { $GetProductDirectory = Get-Command -Name "Get-$($NounPrefix)ProductDirectory"; } $toolDef = New-Object PSObject -Property @{ $KeyToolName = $ToolName; $KeyNounPrefix = $NounPrefix; $KeyGetProductDirectory = $GetProductDirectory; $KeyExecutableNames = $ExecutableNames; $KeyIgnorePath = $IgnorePath -eq $true; $KeyAliases = $Aliases; }; $toolDef.PSTypeNames.Insert(0, 'PSToolLauncher.Definition'); # return $toolDef; Write-Verbose 'SUCCESS New-ToolDefinition.'; } end { Write-Verbose 'FINISH New-ToolDefinition.'; } } function New-ToolInstallation { [CmdletBinding(PositionalBinding = $false)] [OutputType('PSToolLauncher.Installation')] param( [Parameter(Position = 0, Mandatory)] [PSTypeName('PSToolLauncher.Definition')] [object] $ToolDefinition, [Parameter(Mandatory)] [PSTypeName('PSToolLauncher.ToolVersion')] [object[]] $ToolVersions ) begin { Write-Verbose 'BEGIN New-ToolInstallation.'; } process { Write-Verbose "Creating tool installation information for '$($ToolDefinition.$KeyToolName)'."; $isInstalled = $ToolVersions.Count -gt 0; $defaultVersion = $ToolVersions ` | Sort-Object -Property OrderedFileVersion, OrderedPropertVersion ` | Select-Object -First 1; # return New-Object PSObject -Property @{ Definition = $ToolDefinition; Versions = $ToolVersions; IsInstalled = $isInstalled; DefaultVersion = $defaultVersion; } ` | ForEach-Object { $_.PSTypeNames.Insert(0, 'PSToolLauncher.Installation'); $_; }; Write-Verbose 'SUCCESS New-ToolInstallation.'; } end { Write-Verbose 'FINISH New-ToolInstallation.'; } } function Get-NotepadPlusPlusProductDirectory { [CmdletBinding(PositionalBinding = $False)] [OutputType([DirectoryInfo])] param() begin { Write-Verbose 'BEGIN Get-NotepadPlusPlusProductDirectory.'; } process { Get-ProgramFilesDirectory ` | ForEach-Object { $productDir = Join-Path $_ 'Notepad++'; # return Get-Item -Path $productDir -ErrorAction SilentlyContinue; } Write-Verbose 'SUCCESS Get-NotepadPlusPlusProductDirectory.'; } end { Write-Verbose 'FINISH Get-NotepadPlusPlusProductDirectory.'; } } function Get-SqlAdminProductDirectory { [CmdletBinding(PositionalBinding = $False)] [OutputType([DirectoryInfo])] param() begin { Write-Verbose 'BEGIN Get-SqlAdminProductDirectory.'; } process { Get-ProgramFilesDirectory ` | ForEach-Object { $programFilesDir = $_; # return Get-ChildItem -Path $programFilesDir -Filter 'Microsoft SQL Server Management Studio*' ` | Get-ChildItem -Directory -Recurse; # return Get-ChildItem -Path $programFilesDir -Filter 'Microsoft SQL Server' ` | Get-ChildItem -Directory ` | Where-Object { $_.Name -match '^[1-9][0-9]*$' } ` | Get-ChildItem -Directory -Recurse; } Write-Verbose 'SUCCESS Get-SqlAdminProductDirectory.'; } end { Write-Verbose 'FINISH Get-SqlAdminProductDirectory.'; } } # ############################################## # # This section contains the function and alias # that are actually exported from this module # New-Variable -Name KeyToolName -Option Constant ` -Value 'ToolName'; New-Variable -Name KeyNounPrefix -Option Constant ` -Value 'NounPrefix'; New-Variable -Name KeyGetProductDirectory -Option Constant ` -Value 'Get-ProductDirectory'; New-Variable -Name KeyExecutableNames -Option Constant ` -Value 'ExeNames'; New-Variable -Name KeyIgnorePath -Option Constant ` -Value 'IgnorePath'; New-Variable -Name KeyAliases -Option Constant ` -Value 'Aliases'; New-Variable -Name KeyNotepadPlusPlus -Option Constant ` -Value 'notepad-plusplus'; New-Variable -Name ToolDefNotepadPlusPlus -Option Constant ` -Value (New-ToolDefinition -ToolName 'Notepad++' ` -NounPrefix 'NotepadPlusPlus' ` -ExecutableNames 'notepad++.exe' ` -Aliases '_notepad++'); New-Variable -Name KeySqlAdmin -Option Constant ` -Value 'sqladmin-ide'; New-Variable -Name ToolDefSqlAdmin -Option Constant ` -Value (New-ToolDefinition -ToolName 'SQL Server Management Studio' ` -NounPrefix 'SqlAdmin' ` -ExecutableNames 'ssms.exe', 'sqlwb.exe' ` -Aliases '_sqladmin'); New-Variable -Name ToolDefinitions -Option ReadOnly ` -Value @{ $KeyNotepadPlusPlus = $ToolDefNotepadPlusPlus; $KeySqlAdmin = $ToolDefSqlAdmin; }; New-Variable -Name ToolInstallations ` -Value @{}; $PublicAliases = @(); $ToolDefinitions.Keys ` | ForEach-Object { $toolDef = $ToolDefinitions[$_]; foreach($alias in $toolDef.$KeyAliases) { Set-Alias -Name $alias -Value "Start-$($toolDef.$KeyNounPrefix)" -Force; $PublicAliases += $alias; } }; $PublicFunctions = @( 'Start-NotepadPlusPlus', 'Start-SqlAdmin', 'Start-Tool' ); if($global:DebugMode) { Write-Host 'Adding all cmdlets for debug purposes.'; $PublicFunctions += @( 'Get-NotepadPlusPlusProductDirectory', 'Get-ProgramFilesDirectory', 'Get-SqlAdminProductDirectory', 'Get-ToolInstallation', 'Get-ToolVersion', 'Find-ToolFile', 'New-ToolDefinition', 'New-ToolInstallation' ); } Export-ModuleMember -Function $PublicFunctions ` -Alias $PublicAliases; |