Skip to content

Commit b42bcf9

Browse files
committed
[pwsh profile] Refactor profile generation.
Contributes to #1.
1 parent dc59784 commit b42bcf9

File tree

2 files changed

+146
-65
lines changed

2 files changed

+146
-65
lines changed

PowerShell/Profile/newProfile.ps1

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# Copyright (c) 2023 Matthias Wolf, Mawosoft.
2+
3+
<#
4+
.SYNOPSIS
5+
Creates a new Powershell user profile.
6+
.DESCRIPTION
7+
Creates a new Powershell user profile depending on the installed software.
8+
.OUTPUTS
9+
[FileInfo] objects of the profile files if a scope has been specified.
10+
[string] Profile source code if no scope has been specified.
11+
.NOTES
12+
- Currently only creates an AllHosts script.
13+
- Currently no special handling of PowerShell Desktop (5.1) vs. Core
14+
#>
15+
16+
#Requires -Version 5.1
17+
18+
using namespace System
19+
using namespace System.IO
20+
21+
[CmdletBinding(SupportsShouldProcess)]
22+
[OutputType([System.IO.FileInfo], [string])]
23+
param(
24+
# The user scope of the profile to create. The script picks the host scope itself.
25+
[ValidateSet('AllUsers', 'CurrentUser')]
26+
[string]$Scope,
27+
28+
# Force overwriting existing scripts
29+
[switch]$Force
30+
)
31+
32+
Set-StrictMode -Version 3.0
33+
34+
# Get content from source files
35+
function Get-SourceContent {
36+
[OutputType([string])]
37+
param(
38+
# The directory containing the source files
39+
[Parameter(Mandatory, Position = 0)]
40+
[ValidateNotNullOrEmpty()]
41+
[string]$Path
42+
)
43+
# TODO Support a config file (e.g. '.filelist') to determine order and inclusions/exclusions.
44+
[FileInfo[]]$files = Get-ChildItem $Path -Filter '*.ps1'
45+
Write-Verbose 'Source Files:'
46+
$files | Out-String | Write-Verbose
47+
$files | Get-Content -Raw
48+
}
49+
50+
[string]$scriptGetProfileHelp = {
51+
<#
52+
.SYNOPSIS
53+
Gets help overview of profile functions and aliases
54+
.OUTPUTS
55+
Objects with Command and Parameters properties.
56+
#>
57+
function Get-ProfileHelp {
58+
[CmdletBinding()]
59+
[Alias('gprh')]
60+
[OutputType([psobject])]
61+
param()
62+
$Aliases = @('%ALIASES%')
63+
$Functions = @('%FUNCTIONS%')
64+
$Aliases | Get-Command -ListImported | Select-Object @{n = 'Command'; e = 'DisplayName' }, @{n = 'Parameters'; e = '''''' }
65+
$Functions | Get-Command -ListImported | Select-Object @{n = 'Command'; e = 'Name' }, @{n = 'Parameters'; e = { $_.ParameterSets -join [System.Environment]::NewLine } }
66+
}
67+
}.ToString()
68+
69+
[object[]]$contentAllHosts = Get-SourceContent -Path "$PSScriptRoot/Common"
70+
71+
if (Test-Path 'env:VBOX_MSI_INSTALL_PATH' -PathType Container) {
72+
$contentAllHosts += Get-SourceContent -Path "$PSScriptRoot/VirtualBoxHost"
73+
}
74+
75+
[string]$vstudioPath = Join-Path $env:ProgramFiles 'Microsoft Visual Studio'
76+
if (Test-Path $vstudioPath -PathType Container) {
77+
[string]$vstudioPath2 = Join-Path $vstudioPath '2022\Community\Common7'
78+
if (-not (Test-Path -Path (Join-Path $vstudioPath2 'IDE\devenv.exe') -PathType Leaf) -or
79+
-not (Test-Path -Path (Join-Path $vstudioPath2 'Tools\VsDevCmd.bat') -PathType Leaf)) {
80+
throw "The path '$vstudioPath' exists, but required files below are missing.`n" +
81+
'If the edition in use has changed, the profile source code needs to be updated.'
82+
}
83+
$contentAllHosts += Get-SourceContent -Path "$PSScriptRoot/Developer"
84+
}
85+
86+
[object[]]$contentCurrentHost = @()
87+
88+
[string]$nl = [Environment]::NewLine
89+
[string]$scriptAllHosts = $contentAllHosts -join $nl
90+
[string]$scriptCurrentHost = $contentCurrentHost -join $nl
91+
92+
[psmoduleinfo]$tempModule = $null
93+
[powershell]$posh = $null
94+
try {
95+
$posh = [powershell]::Create($Host.Runspace.InitialSessionState).AddScript((
96+
@(
97+
"New-Module -ScriptBlock {$nl"
98+
$scriptAllHosts
99+
$scriptGetProfileHelp
100+
$scriptCurrentHost
101+
"${nl}Export-ModuleMember -Function * -Alias * $nl}$nl"
102+
) -join ''
103+
))
104+
$result = $posh.Invoke()
105+
if ($posh.HadErrors -or -not $result -or $result.Count -ne 1) {
106+
throw 'Failed to generate a temporary module for profile sources.'
107+
}
108+
$tempModule = $result[0]
109+
}
110+
finally {
111+
if ($posh) { $posh.Dispose() }
112+
}
113+
114+
$scriptGetProfileHelp = $scriptGetProfileHelp.Replace('%ALIASES%',
115+
($tempModule.ExportedAliases.Values.Name | Sort-Object) -join "', '")
116+
$scriptGetProfileHelp = $scriptGetProfileHelp.Replace('%FUNCTIONS%',
117+
($tempModule.ExportedFunctions.Values.Name | Sort-Object) -join "', '")
118+
$scriptAllHosts += $nl + $scriptGetProfileHelp
119+
120+
if ($Scope) {
121+
[string]$profilePath = $PROFILE.$("${Scope}AllHosts")
122+
if ((Test-Path $profilePath -PathType Leaf) -and
123+
$scriptAllHosts.Equals((Get-Content $profilePath -Raw), [StringComparison]::Ordinal)) {
124+
Write-Verbose "'$profilePath' is already up-to-date."
125+
}
126+
else {
127+
New-Item -Path $profilePath -Value $scriptAllHosts -Force:$Force
128+
}
129+
130+
$profilePath = $PROFILE.$("${Scope}CurrentHost")
131+
if ($scriptCurrentHost) {
132+
if ((Test-Path $profilePath -PathType Leaf) -and
133+
$scriptCurrentHost.Equals((Get-Content $profilePath -Raw), [StringComparison]::Ordinal)) {
134+
Write-Verbose "'$profilePath' is already up-to-date."
135+
}
136+
else {
137+
New-Item -Path $profilePath -Value $scriptCurrentHost -Force:$Force
138+
}
139+
}
140+
}
141+
else {
142+
$scriptAllHosts
143+
if ($scriptCurrentHost) {
144+
$scriptCurrentHost
145+
}
146+
}

PowerShellProfile/newProfile.ps1

Lines changed: 0 additions & 65 deletions
This file was deleted.

0 commit comments

Comments
 (0)