PSToolLauncher.psm1
|
#Requires -Version 5.1 using namespace System.IO; using namespace System.Management.Automation; # +----------------------------------------------------------------------------------------------------------- # | Public functions # | <# #> function Open-Tool { [CmdletBinding(PositionalBinding = $false)] param( [Parameter(Position = 0, Mandatory)] [string] $ToolKey, [Parameter(ValueFromRemainingArguments)] $Arguments ) process { Write-Verbose 'BEGIN: Open-Tool'; try { $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 'OK: Open-Tool'; } catch { Write-Verbose 'ERROR: Open-Tool'; throw; } finally { Write-Verbose 'END: Open-Tool'; } } } function Open-NotepadPlusPlus { [CmdletBinding(PositionalBinding = $false)] param( [Parameter(ValueFromRemainingArguments)] $Arguments ) process { Write-Verbose 'EXECUTING Open-NotepadPlusPlus.'; Open-Tool -ToolKey $KeyNotepadPlusPlus -Arguments $Arguments; } } function Open-SqlAdmin { [CmdletBinding(PositionalBinding = $false)] param( [Parameter(ValueFromRemainingArguments)] $Arguments ) process { Write-Verbose 'EXECUTING Open-SqlAdmin.'; Open-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 ) process { Write-Verbose 'BEGIN: Find-ToolFile'; try { $exeNameList = $ExecutableNames -join ', '; $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 'OK: Find-ToolFile'; } catch { Write-Verbose 'ERROR: Find-ToolFile'; throw; } finally { Write-Verbose 'END: Find-ToolFile'; } } } function Get-ProgramFilesDirectory { [CmdletBinding(PositionalBinding = $false)] [OutputType([DirectoryInfo])] param() process { Write-Verbose 'BEGIN: Get-ProgramFilesDirectory'; try { $toolDirs = Get-ChildItem -Path Env:ProgramFiles* ` | Select-Object -ExpandProperty Value; # return $toolDirs | Select-Object -Unique ` | Get-Item -ErrorAction SilentlyContinue; Write-Verbose 'OK: Get-ProgramFilesDirectory'; } catch { Write-Verbose 'ERROR: Get-ProgramFilesDirectory'; throw; } finally { Write-Verbose 'END: Get-ProgramFilesDirectory'; } } } function Get-ToolInstallation { [CmdletBinding(PositionalBinding = $false)] [OutputType('PSToolLauncher.Installation')] param( [Parameter(Position = 0, Mandatory)] [string] $ToolKey, [Parameter()] [switch] $Force ) process { Write-Verbose 'BEGIN: Get-ToolInstallation'; try { 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 'OK: Get-ToolInstallation'; } catch { Write-Verbose 'ERROR: Get-ToolInstallation'; throw; } finally { Write-Verbose 'END: Get-ToolInstallation'; } } } function Get-ToolVersion { [CmdletBinding(PositionalBinding = $false)] [OutputType('PSToolLauncher.ToolVersion')] param( [Parameter(Position = 0, Mandatory, ValueFromPipeline)] [FileInfo[]] $ToolFiles ) process { Write-Verbose 'BEGIN: Get-ToolVersion'; try { $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 'OK: Get-ToolVersion'; } catch { Write-Verbose 'ERROR: Get-ToolVersion'; throw; } finally { Write-Verbose 'END: Get-ToolVersion'; } } } function New-ToolDefinition { [CmdletBinding(SupportsShouldProcess, 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 ) process { Write-Verbose 'BEGIN: New-ToolDefinition'; try { Write-Verbose "Creating ToolDefinition for '$ToolName'."; if($PSCmdlet.ShouldProcess($ToolDefinition.$KeyToolName)) { 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 'OK: New-ToolDefinition'; } catch { Write-Verbose 'ERROR: New-ToolDefinition'; throw; } finally { Write-Verbose 'END: New-ToolDefinition'; } } } function New-ToolInstallation { [CmdletBinding(SupportsShouldProcess, PositionalBinding = $false)] [OutputType('PSToolLauncher.Installation')] param( [Parameter(Position = 0, Mandatory)] [PSTypeName('PSToolLauncher.Definition')] [object] $ToolDefinition, [Parameter(Mandatory)] [PSTypeName('PSToolLauncher.ToolVersion')] [object[]] $ToolVersions ) process { Write-Verbose 'BEGIN: New-ToolInstallation'; try { Write-Verbose "Creating tool installation information for '$($ToolDefinition.$KeyToolName)'."; if($PSCmdlet.ShouldProcess($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 'OK: New-ToolInstallation'; } catch { Write-Verbose 'ERROR: New-ToolInstallation'; throw; } finally { Write-Verbose 'END: New-ToolInstallation'; } } } function Get-NotepadPlusPlusProductDirectory { [CmdletBinding(PositionalBinding = $False)] [OutputType([DirectoryInfo])] param() process { Write-Verbose 'BEGIN: Get-NotepadPlusPlusProductDirectory'; try { Get-ProgramFilesDirectory ` | ForEach-Object { $productDir = Join-Path $_ 'Notepad++'; # return Get-Item -Path $productDir -ErrorAction SilentlyContinue; } Write-Verbose 'OK: Get-NotepadPlusPlusProductDirectory'; } catch { Write-Verbose 'ERROR: Get-NotepadPlusPlusProductDirectory'; throw; } finally { Write-Verbose 'END: Get-NotepadPlusPlusProductDirectory'; } } } function Get-SqlAdminProductDirectory { [CmdletBinding(PositionalBinding = $False)] [OutputType([DirectoryInfo])] param() process { Write-Verbose 'BEGIN: Get-SqlAdminProductDirectory'; try { 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 'OK: Get-SqlAdminProductDirectory'; } catch { Write-Verbose 'ERROR: Get-SqlAdminProductDirectory'; throw; } finally { Write-Verbose 'END: 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 "Open-$($toolDef.$KeyNounPrefix)" -Force; $PublicAliases += $alias; } }; $PublicFunctions = @( 'Open-NotepadPlusPlus', 'Open-SqlAdmin', 'Open-Tool' ); if($DebugPreference -ne 'SilentlyContinue') { Write-Debug '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; |