Skip to content

Commit 9318dcd

Browse files
xpp-lens 1.4.2
xpp-lens 1.4.2
2 parents 22bea1d + bf71c46 commit 9318dcd

7 files changed

Lines changed: 128 additions & 3 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@
33
All notable changes to xpp-lens (called xpp-graft up to 1.2.0). Versions follow `<Version>` in
44
`src/XppLens/XppLens.csproj`; release tags are `vX.Y.Z`.
55

6+
## 1.4.2
7+
8+
### Fixed
9+
- An installation by `install.ps1` (the ZIP package, and every update from a version before 1.3.0) left `xpplens`
10+
off the PATH ("The term 'xpplens' is not recognized"), with no Start menu entries and no entry in Windows' installed
11+
apps. `install.ps1` now does what the setup program does: the program folder on the user's PATH (kept as
12+
`REG_EXPAND_SZ`, so `%VAR%` entries keep working; new terminals see it at once), the same Start menu entries with
13+
the icon, and an installed-apps entry that runs `uninstall.ps1`. When the setup program installed xpp-lens for the
14+
user, its entries stay; the setup program replaces those of `install.ps1` when it takes a folder over.
15+
`uninstall.ps1` removes the PATH entry, and the Start menu and installed-apps entries `install.ps1` made.
16+
617
## 1.4.1
718

819
### Fixed

‎README.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ powershell -ExecutionPolicy Bypass -File .\dist\xpp-lens\install.ps1 -Languages
4242
```
4343

4444
The installer copies the files to `C:\Tools\xpp-lens`, detects `PackagesLocalDirectory` (from the AOS `web.config`
45-
or the folder layout), writes the configuration, registers the server in Claude Desktop and Claude Code, and finally
45+
or the folder layout), writes the configuration, registers the server in Claude Desktop and Claude Code, and — like
46+
the setup program — puts `xpplens` on your PATH, adds the Start menu entries and an entry in Windows' installed apps
47+
(when the setup program installed xpp-lens for you, its own entries stay), installs the skills, and finally
4648
builds the index (custom models take about a minute, the Microsoft standard 20–90 minutes once, depending on the disk).
4749
Claude may stay open: start a new session afterwards (or restart Claude Desktop) to load the server.
4850

‎README.pl.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ powershell -ExecutionPolicy Bypass -File .\dist\xpp-lens\install.ps1 -Languages
4242
```
4343

4444
Instalator kopiuje pliki do `C:\Tools\xpp-lens`, wykrywa `PackagesLocalDirectory` (z `web.config` AOS-a albo
45-
układu katalogów), zapisuje konfigurację, rejestruje serwer w Claude Desktop i Claude Code, a na końcu buduje indeks
45+
układu katalogów), zapisuje konfigurację, rejestruje serwer w Claude Desktop i Claude Code, a tak jak program
46+
instalacyjny dopisuje `xpplens` do PATH, dodaje skróty w menu Start i wpis w „Aplikacjach” Windows (gdy xpp-lens
47+
zainstalował u ciebie program instalacyjny, zostają jego wpisy), instaluje skille, a na końcu buduje indeks
4648
(modele własne ok. minuty, standard Microsoftu jednorazowo 20–90 minut, zależnie od dysku). Claude może zostać
4749
otwarty: po instalacji zacznij nową sesję (albo uruchom ponownie Claude Desktop), żeby wczytał serwer.
4850

‎install.ps1‎

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,86 @@ else {
130130
$exe = Join-Path $InstallDir 'bin\xpplens.exe'
131131
Say "done: $exe"
132132

133+
# The program folder on the user's PATH, as the setup program does: "xpplens" then works in any new terminal.
134+
# Read and written raw (REG_EXPAND_SZ), so entries such as %USERPROFILE%\... keep expanding.
135+
$binFull = (Resolve-Path $binDst).Path.TrimEnd('\')
136+
$envKey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Environment', $true)
137+
try {
138+
$rawPath = [string]$envKey.GetValue('Path', '', [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
139+
$items = @($rawPath -split ';' | Where-Object { $_ })
140+
if ($items | Where-Object { [Environment]::ExpandEnvironmentVariables($_).TrimEnd('\') -ieq $binFull }) {
141+
Say "already on your PATH: $binFull"
142+
}
143+
else {
144+
$envKey.SetValue('Path', (@($items) + $binFull) -join ';', [Microsoft.Win32.RegistryValueKind]::ExpandString)
145+
# Tell Explorer, so terminals opened from now on see it (WM_SETTINGCHANGE "Environment").
146+
Add-Type -Namespace XppLensSetup -Name Native -MemberDefinition @'
147+
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
148+
public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint msg, UIntPtr wParam, string lParam, uint flags, uint timeout, out UIntPtr result);
149+
'@
150+
$ignored = [UIntPtr]::Zero
151+
[void][XppLensSetup.Native]::SendMessageTimeout([IntPtr]0xffff, 0x1A, [UIntPtr]::Zero, 'Environment', 2, 5000, [ref]$ignored)
152+
$env:Path = "$env:Path;$binFull"
153+
Say "added to your PATH: $binFull (open a new terminal to use 'xpplens')"
154+
}
155+
}
156+
finally {
157+
$envKey.Close()
158+
}
159+
160+
# Start menu entries and an entry in Windows' installed apps, as the setup program makes them. When the setup
161+
# program installed xpp-lens for this user, its own entries stay (they are the same, and its uninstaller owns
162+
# them); the setup program removes these when it takes over a folder installed by this script.
163+
$setupKey = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\{B3C9E031-73CD-4356-AC30-B8EC91C3C528}_is1'
164+
if (Test-Path $setupKey) {
165+
Say "Start menu and installed apps: kept from the setup program ($((Get-ItemProperty $setupKey).InstallLocation))"
166+
}
167+
else {
168+
$pl = if ($SkillsLanguage) { $SkillsLanguage -eq 'pl' } else { (Get-UICulture).TwoLetterISOLanguageName -eq 'pl' }
169+
# The setup program's names (Polish without diacritics in this ASCII script: "sprawdz" gets its z-acute here).
170+
$names = if ($pl) {
171+
@{ status = 'xpp-lens - status'; build = 'xpp-lens - aktualizacja indeksu'; update = "xpp-lens - sprawd$([char]0x17A) aktualizacje"
172+
uninstall = 'Odinstaluj xpp-lens'; console = 'Konsola z poleceniami xpplens' }
173+
}
174+
else {
175+
@{ status = 'xpp-lens - status'; build = 'xpp-lens - update the index'; update = 'xpp-lens - check for updates'
176+
uninstall = 'Uninstall xpp-lens'; console = 'Console with the xpplens commands' }
177+
}
178+
$group = Join-Path ([Environment]::GetFolderPath('Programs')) 'xpp-lens'
179+
if (Test-Path $group) { Remove-Item $group -Recurse -Force }
180+
New-Item -ItemType Directory -Force -Path $group | Out-Null
181+
$shell = New-Object -ComObject WScript.Shell
182+
function New-Shortcut($name, $target, $arguments, $workDir, $description) {
183+
$lnk = $shell.CreateShortcut((Join-Path $group "$name.lnk"))
184+
$lnk.TargetPath = $target
185+
$lnk.Arguments = $arguments
186+
$lnk.WorkingDirectory = $workDir
187+
$lnk.IconLocation = "$exe,0"
188+
if ($description) { $lnk.Description = $description }
189+
$lnk.Save()
190+
}
191+
New-Shortcut 'xpp-lens' $env:ComSpec "/k `"title xpp-lens & set `"PATH=$binFull;%PATH%`" & xpplens help`"" $env:USERPROFILE $names.console
192+
foreach ($c in 'status', 'build', 'update') {
193+
New-Shortcut $names[$c] $env:ComSpec "/k `"`"$exe`" $c`"" $InstallDir $null
194+
}
195+
$uninstallCmd = "-NoProfile -ExecutionPolicy Bypass -File `"$(Join-Path $InstallDir 'uninstall.ps1')`""
196+
New-Shortcut $names.uninstall 'powershell.exe' $uninstallCmd $InstallDir $null
197+
198+
$appKey = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\xpp-lens'
199+
New-Item -Path $appKey -Force | Out-Null
200+
$appVersion = ([string](& $exe version)).Split(' ')[1]
201+
$sizeKb = [int]((Get-ChildItem $InstallDir -Recurse -File | Measure-Object Length -Sum).Sum / 1KB)
202+
$values = @{
203+
DisplayName = 'xpp-lens'; DisplayVersion = $appVersion; Publisher = 'WillowDev'; DisplayIcon = $exe
204+
InstallLocation = $dstFull; URLInfoAbout = 'https://github.com/willowdev-code/xpp-lens'
205+
UninstallString = "powershell.exe $uninstallCmd"
206+
}
207+
foreach ($v in $values.GetEnumerator()) { Set-ItemProperty $appKey -Name $v.Key -Value $v.Value }
208+
foreach ($v in 'NoModify', 'NoRepair') { New-ItemProperty $appKey -Name $v -Value 1 -PropertyType DWord -Force | Out-Null }
209+
New-ItemProperty $appKey -Name EstimatedSize -Value $sizeKb -PropertyType DWord -Force | Out-Null
210+
Say "Start menu entries and an entry in installed apps (xpp-lens $appVersion)"
211+
}
212+
133213
Head "2/5 PackagesLocalDirectory folder"
134214
if (-not $PackagesDir) {
135215
$found = @(& $exe detect | Where-Object { $_ -match "`t" })

‎packaging/inno/xpp-lens.iss‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ Name: "pl"; MessagesFile: "compiler:Languages\Polish.isl"
5555
[InstallDelete]
5656
; The package's copy of the skills is replaced whole, so a skill dropped from the package does not linger.
5757
Type: filesandordirs; Name: "{app}\skills"
58+
; Start menu entries of an earlier installation (install.ps1 names them in its own language): made again below.
59+
Type: filesandordirs; Name: "{group}"
5860

5961
[Files]
6062
Source: "{#Source}\*"; DestDir: "{app}"; Flags: recursesubdirs ignoreversion
@@ -414,6 +416,8 @@ var
414416
begin
415417
if CurStep <> ssPostInstall then Exit;
416418
Exe := ExpandConstant('{app}\bin\xpplens.exe');
419+
{ The installed-apps entry of install.ps1 (taken over here): this program's own entry replaces it. }
420+
RegDeleteKeyIncludingSubkeys(HKCU, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\xpp-lens');
417421
if not WasUpdate then
418422
begin
419423
Langs := Trim(LangPage.Values[0]);

‎src/XppLens/XppLens.csproj‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<AssemblyTitle>xpp-lens — X++ code index for MCP</AssemblyTitle>
2323
<Description>X++ (Dynamics 365 F&amp;O) code index served to AI assistants over MCP</Description>
2424
<Copyright>Copyright © 2026 WillowDev</Copyright>
25-
<Version>1.4.1</Version>
25+
<Version>1.4.2</Version>
2626
</PropertyGroup>
2727

2828
<ItemGroup>

‎uninstall.ps1‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,32 @@ if (Test-Path $exe) {
5757
}
5858
else { Say "$exe not found - skipping unregistration and skills" }
5959

60+
# The program folder off the user's PATH (install.ps1 and the setup program put it there).
61+
$binFull = [IO.Path]::GetFullPath((Join-Path $InstallDir 'bin')).TrimEnd('\')
62+
$envKey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Environment', $true)
63+
try {
64+
$rawPath = [string]$envKey.GetValue('Path', '', [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
65+
$items = @($rawPath -split ';' | Where-Object { $_ })
66+
$kept = @($items | Where-Object { [Environment]::ExpandEnvironmentVariables($_).TrimEnd('\') -ine $binFull })
67+
if ($kept.Count -ne $items.Count) {
68+
$envKey.SetValue('Path', $kept -join ';', [Microsoft.Win32.RegistryValueKind]::ExpandString)
69+
Say "removed from your PATH: $binFull"
70+
}
71+
}
72+
finally {
73+
$envKey.Close()
74+
}
75+
76+
# The Start menu entries and the installed-apps entry made by install.ps1 (the setup program's own go with its
77+
# uninstaller).
78+
$appKey = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\xpp-lens'
79+
if ((Test-Path $appKey) -and ([string](Get-ItemProperty $appKey).InstallLocation).TrimEnd('\') -ieq [IO.Path]::GetFullPath($InstallDir).TrimEnd('\')) {
80+
Remove-Item $appKey -Recurse -Force
81+
$group = Join-Path ([Environment]::GetFolderPath('Programs')) 'xpp-lens'
82+
if (Test-Path $group) { Remove-Item $group -Recurse -Force }
83+
Say "removed the Start menu entries and the entry in installed apps"
84+
}
85+
6086
$target = [IO.Path]::GetFullPath($InstallDir).TrimEnd('\') + '\'
6187
Get-CimInstance Win32_Process -Filter "Name='xpplens.exe'" |
6288
Where-Object { $_.ExecutablePath -and $_.ExecutablePath.StartsWith($target, [StringComparison]::OrdinalIgnoreCase) } |

0 commit comments

Comments
 (0)