1111 Version: 1.0.0
1212 Description: Description goes here
1313#>
14+ # NOW import the module
15+ Remove-Module VSCode- Updater - ErrorAction SilentlyContinue
1416Import-Module " $PSScriptRoot \..\VSCode-Updater.psd1" - Force
17+ # Load output helpers (this defines _out)
18+ . " $PSScriptRoot \..\Private\OutputHelpers.ps1"
19+ . " $PSScriptRoot \..\Private\Write-Log.ps1"
20+
1521
1622function Get-SelectedVersionName {
1723 [CmdletBinding ()]
@@ -31,6 +37,105 @@ function Get-SelectedVersionName {
3137
3238 return $null
3339}
40+ function Clear-Terminal {
41+ $window.Dispatcher.Invoke ({
42+ $txtCommandOutput.Document.Blocks.Clear ()
43+ })
44+ }
45+ function Confirm-SetupAppRunning {
46+ $proc = Get-Process - Name " SetupApp" - ErrorAction SilentlyContinue
47+
48+ if (-not $proc ) {
49+ Write-TaskViewerLine " SetupApp missing — restarting..." " Yellow"
50+
51+ try {
52+ Start-Process " C:\Path\To\SetupApp.exe"
53+ Write-TaskViewerLine " SetupApp restarted successfully." " LightGreen"
54+ }
55+ catch {
56+ Write-TaskViewerLine " Failed to restart SetupApp: $_ " " Red"
57+ }
58+ }
59+ }
60+ function Invoke-StreamingCommand {
61+ param ([string ]$Command )
62+
63+ Clear-Terminal
64+ Write-TerminalLine " Running: $Command " " LightBlue"
65+
66+ $psi = New-Object System.Diagnostics.ProcessStartInfo
67+ $psi.FileName = " powershell.exe"
68+ $psi.Arguments = " -NoLogo -NoProfile -Command $Command "
69+ $psi.RedirectStandardOutput = $true
70+ $psi.RedirectStandardError = $true
71+ $psi.UseShellExecute = $false
72+ $psi.CreateNoWindow = $true
73+
74+ $proc = New-Object System.Diagnostics.Process
75+ $proc.StartInfo = $psi
76+
77+ # Hook stdout
78+ $proc.add_OutputDataReceived ({
79+ if ($_.Data ) {
80+ Write-TerminalLine $_.Data " White"
81+ }
82+ })
83+
84+ # Hook stderr
85+ $proc.add_ErrorDataReceived ({
86+ if ($_.Data ) {
87+ Write-TerminalLine $_.Data " Red"
88+ }
89+ })
90+
91+ $proc.Start ()
92+ $proc.BeginOutputReadLine ()
93+ $proc.BeginErrorReadLine ()
94+
95+ # Optional: wait for completion without blocking UI
96+ Start-Job - ScriptBlock {
97+ $proc.WaitForExit ()
98+ $window.Dispatcher.Invoke ({
99+ Write-TerminalLine " Process exited with code $ ( $proc.ExitCode ) " " LightGray"
100+ })
101+ }
102+ }
103+ function Show-DashboardInTerminal {
104+ $info = Get-VSCodeDashboard
105+
106+ Write-TerminalLine " === Dashboard ===" " LightGray"
107+
108+ if ($info ) {
109+ Write-TerminalLine " Installed Versions: $ ( $info.InstalledVersions ) " " White"
110+ Write-TerminalLine " Version Count: $ ( $info.VersionCount ) " " White"
111+ Write-TerminalLine " Active Version: $ ( $info.ActiveVersion ) " " Green"
112+ Write-TerminalLine " Cache Path: $ ( $info.CachePath ) " " Yellow"
113+ Write-TerminalLine " LastUpdateLog: $ ( $info.LastUpdateLog ) " " White"
114+ }
115+ else {
116+ Write-TerminalLine " Dashboard: No information available." " Red"
117+ }
118+
119+ Write-TerminalLine " =================" " LightGray"
120+ }
121+ function Show-VSCodeSymlinkInfo {
122+ $info = Get-VSCodeSymlinkInfo
123+
124+ Write-TerminalLine " === VSCode Symlink Info ===" " LightGray"
125+
126+ if ($info ) {
127+ Write-TerminalLine " Active Version: $ ( $info.ActiveVersion ) " " LightGreen"
128+ Write-TerminalLine " Target Path: $ ( $info.TargetPath ) " " White"
129+ Write-TerminalLine " Valid: $ ( $info.IsValid ) " " LightBlue"
130+ Write-TerminalLine " Last Update: $ ( $info.LastUpdateResult ) " " Yellow"
131+ Write-TerminalLine " Fallback Reason:$ ( $info.LastFallbackReason ) " " Red"
132+ }
133+ else {
134+ Write-TerminalLine " No symlink information found." " Red"
135+ }
136+
137+ Write-TerminalLine " =============================" " LightGray"
138+ }
34139
35140function Start-VSCodeUpdaterGUI {
36141
@@ -39,6 +144,7 @@ function Start-VSCodeUpdaterGUI {
39144 Add-Type - AssemblyName PresentationCore
40145 Add-Type - AssemblyName WindowsBase
41146
147+ $script :SafeMode = $false
42148
43149 # Resolve XAML path relative to the Public folder
44150 $xamlPath = Join-Path $PSScriptRoot " VSCodeUpdaterGUI.xaml"
@@ -58,21 +164,37 @@ function Start-VSCodeUpdaterGUI {
58164 $stream.Position = 0
59165
60166 $reader = [System.Xml.XmlReader ]::Create($stream )
61- $window = [Windows.Markup.XamlReader ]::Load($reader )
167+ $global : window = [Windows.Markup.XamlReader ]::Load($reader )
62168
63169 $dgVersions = $window.FindName (" DgVersions" )
64170
65171 # Bind controls
66- $btnUpdate = $window.FindName (" BtnUpdate" )
67- $btnRollback = $window.FindName (" BtnRollback" )
68- $btnSwitch = $window.FindName (" BtnSwitch" )
69- $txtStatus = $window.FindName (" TxtStatus" )
70- $txtLog = $window.FindName (" TxtLog" )
71- $txtActiveVersion = $window.FindName (" TxtActiveVersion" )
72- $txtSymlinkTarget = $window.FindName (" TxtSymlinkTarget" )
73- $txtSymlinkValid = $window.FindName (" TxtSymlinkValid" )
74- $txtLastUpdate = $window.FindName (" TxtLastUpdate" )
75- $txtFallbackReason = $window.FindName (" TxtFallbackReason" )
172+ $script :btnUpdate = $window.FindName (" BtnUpdate" )
173+ $script :btnRollback = $window.FindName (" BtnRollback" )
174+ $script :btnSwitch = $window.FindName (" BtnSwitch" )
175+ $script :txtStatus = $window.FindName (" TxtStatus" )
176+ $script :txtLog = $window.FindName (" TxtLog" )
177+ $global :txtCommandOutput = $window.FindName (" TxtCommandOutput" )
178+ $script :txtActiveVersion = $window.FindName (" TxtActiveVersion" )
179+ $script :txtSymlinkTarget = $window.FindName (" TxtSymlinkTarget" )
180+ $script :txtSymlinkValid = $window.FindName (" TxtSymlinkValid" )
181+ $script :txtLastUpdate = $window.FindName (" TxtLastUpdate" )
182+ $script :txtFallbackReason = $window.FindName (" TxtFallbackReason" )
183+ $script :btnValidateSymlink = $window.FindName (" BtnValidateSymlink" )
184+ $script :btnSafeMode = $window.FindName (" BtnSafeMode" )
185+ $script :btnDashboard = $window.FindName (" BtnDashboard" )
186+ $script :btnPauseLog = $window.FindName (" BtnPauseLog" )
187+ $script :btnSearchLog = $window.FindName (" BtnSearchLog" )
188+ $script :chkAutoScroll = $window.FindName (" ChkAutoScroll" )
189+ $script :txtSearchLog = $window.FindName (" TxtSearchLog" )
190+ $script :txtTaskViewer = $window.FindName (" TxtTaskViewer" ) # if present
191+ $script :btnRestartSetup = $window.FindName (" BtnRestartSetup" )
192+ $script :chkSafeMode = $window.FindName (" ChkSafeMode" )
193+ # Default Safe Mode state on load
194+ $script :SafeMode = $true
195+ $chkSafeMode.IsChecked = $true
196+
197+ $txtTaskViewer.Document = New-Object System.Windows.Documents.FlowDocument
76198
77199 $info = Get-VSCodeSymlinkInfo
78200 $window.Resources [" ActiveVersionName" ] = $info.ActiveVersion
@@ -95,14 +217,22 @@ function Start-VSCodeUpdaterGUI {
95217 if (Test-Path $LogFile ) {
96218 try {
97219 $txtLog.Text = (Get-Content $LogFile - Tail 200 ) -join " `r`n "
98- $txtLog.ScrollToEnd ()
220+
221+ if ($chkAutoScroll.IsChecked ) {
222+ $txtLog.ScrollToEnd ()
223+ }
99224 }
100225 catch {
101226 # Ignore transient file locks
102227 }
103228 }
104229 })
105230 $timer.Start ()
231+ $taskTimer = New-Object Windows.Threading.DispatcherTimer
232+ $taskTimer.Interval = [TimeSpan ]::FromSeconds(5 )
233+ $taskTimer.Add_Tick ({ Update-TaskViewerStatus })
234+ $taskTimer.Start ()
235+
106236 # --------------------------------
107237
108238 # Load version list
@@ -131,7 +261,10 @@ function Start-VSCodeUpdaterGUI {
131261 $btnUpdate.Add_Click ({
132262 $result = Update-VSCode
133263 $txtStatus.Text = " Update completed: $result "
134- Update-VersionList
264+ })
265+
266+ $btnRestartSetup.Add_Click ({
267+ Confirm-SetupAppRunning
135268 })
136269
137270 $btnRollback.Add_Click ({
@@ -161,6 +294,7 @@ function Start-VSCodeUpdaterGUI {
161294 $result = Test-VSCodeSymlink
162295 $txtStatus.Text = " Symlink validation: $result "
163296 Update-SymlinkInfo
297+ Show-VSCodeSymlinkInfo
164298 }
165299 catch {
166300 $txtStatus.Text = " Symlink validation failed: $_ "
@@ -171,26 +305,23 @@ function Start-VSCodeUpdaterGUI {
171305 # Start Safe Mode
172306 # -----------------------------
173307 $btnSafeMode.Add_Click ({
174- try {
175- Start-VSCodeSafeMode
176- $txtStatus.Text = " VS Code launched in Safe Mode."
177- }
178- catch {
179- $txtStatus.Text = " Safe Mode launch failed: $_ "
180- }
308+ Start-VSCodeSafeMode
309+ })
310+ $chkSafeMode.Add_Checked ({
311+ $script :SafeMode = $true
312+ _out " SAFE MODE ENABLED" " Yellow"
313+ })
314+
315+ $chkSafeMode.Add_Unchecked ({
316+ $script :SafeMode = $false
317+ _out " SAFE MODE DISABLED" " Yellow"
181318 })
182319
183320 # -----------------------------
184321 # Open Dashboard
185322 # -----------------------------
186323 $btnDashboard.Add_Click ({
187- try {
188- Get-VSCodeDashboard
189- $txtStatus.Text = " Dashboard opened."
190- }
191- catch {
192- $txtStatus.Text = " Dashboard failed to open: $_ "
193- }
324+ Show-DashboardInTerminal
194325 })
195326
196327 # -----------------------------
@@ -246,24 +377,106 @@ function Start-VSCodeUpdaterGUI {
246377
247378 $window.Add_Closed ({
248379 $timer.Stop ()
380+ $taskTimer.Stop ()
381+ })
382+ $window.Add_Loaded ({
383+ if ($chkSafeMode.IsChecked ) {
384+ _out " SAFE MODE ENABLED" " Yellow"
385+ }
249386 })
250- function Update-SymlinkInfo {
251- $info = Get-VSCodeSymlinkInfo
252-
253- $txtActiveVersion.Text = " Active Version: $ ( $info.ActiveVersion ) "
254- $txtSymlinkTarget.Text = " Symlink Target: $ ( $info.TargetPath ) "
255- $txtSymlinkValid.Text = " Symlink Status: " + ($info.IsValid ? " Valid" : " Broken" )
256- $txtLastUpdate.Text = " Last Update: $ ( $info.LastUpdateResult ) "
257- $txtFallbackReason.Text = " Fallback Reason: $ ( $info.LastFallbackReason ) "
258- }
259-
260- # Helper: refresh version list
261- function Update-VersionList {
262- $dgVersions.ItemsSource = Get-VSCodeVersions
263- }
264387
265388 # Show window
266389 $window.ShowDialog () | Out-Null
267390}
391+ function Update-TaskViewer {
392+ param ([string ]$Text )
393+
394+ $window.Dispatcher.Invoke ({
395+ $txtTaskViewer.AppendText (" $Text `n " )
396+ $txtTaskViewer.ScrollToEnd ()
397+ })
398+ }
399+ function Update-TaskViewerStatus {
400+ $proc = Get-Process - Name " SetupApp" - ErrorAction SilentlyContinue
401+
402+ # Clear previous output
403+ $window.Dispatcher.Invoke ({
404+ $txtTaskViewer.Document.Blocks.Clear ()
405+ })
406+
407+ if ($proc ) {
408+ Write-TaskViewerLine " SetupApp: Running (PID $ ( $proc.Id ) )" " LightGreen"
409+
410+ # CPU is cumulative; WorkingSet64 is live memory
411+ Write-TaskViewerLine (" CPU Time: {0:N2} sec" -f $proc.CPU ) " White"
412+ Write-TaskViewerLine (" Memory: {0:N2} MB" -f ($proc.WorkingSet64 / 1 MB )) " White"
413+
414+ # Status classification
415+ if ($proc.WorkingSet64 -gt 50 MB ) {
416+ Write-TaskViewerLine " Status: Busy" " Yellow"
417+ }
418+ else {
419+ Write-TaskViewerLine " Status: Idle" " LightBlue"
420+ }
421+ }
422+ else {
423+ Write-TaskViewerLine " SetupApp: Not running" " Red"
424+ }
425+
426+ Write-TaskViewerLine (" Last check: {0}" -f (Get-Date - Format " HH:mm:ss" )) " Gray"
427+ }
428+ function Update-Terminal {
429+ param ([string ]$Text )
430+
431+ $txtCommandOutput.AppendText ($Text + " `n " )
432+ $txtCommandOutput.CaretPosition = $txtCommandOutput.Document.ContentEnd
433+ $txtCommandOutput.ScrollToEnd ()
434+ }
435+ function Update-SymlinkInfo {
436+ $info = Get-VSCodeSymlinkInfo
437+
438+ $txtActiveVersion.Text = " Active Version: $ ( $info.ActiveVersion ) "
439+ $txtSymlinkTarget.Text = " Symlink Target: $ ( $info.TargetPath ) "
440+ $txtSymlinkValid.Text = " Symlink Status: " + ($info.IsValid ? " Valid" : " Broken" )
441+ $txtLastUpdate.Text = " Last Update: $ ( $info.LastUpdateResult ) "
442+ $txtFallbackReason.Text = " Fallback Reason: $ ( $info.LastFallbackReason ) "
443+ }
444+
445+ # Helper: refresh version list
446+ function Update-VersionList {
447+ $dgVersions.ItemsSource = Get-VSCodeVersions
448+ }
449+ function Write-Colored {
450+ param (
451+ [string ]$Text ,
452+ [string ]$Color = " White"
453+ )
454+
455+ $run = New-Object System.Windows.Documents.Run
456+ $run.Text = $Text + " `n "
457+ $run.Foreground = $Color
458+
459+ $txtCommandOutput.Document.Blocks.Add ($run )
460+ $txtCommandOutput.CaretPosition = $txtCommandOutput.Document.ContentEnd
461+ $txtCommandOutput.ScrollToEnd ()
462+ }
463+ function Write-TaskViewerLine {
464+ param (
465+ [string ]$Text ,
466+ [string ]$Color = " White"
467+ )
468+
469+ $window.Dispatcher.Invoke ({
470+ $paragraph = New-Object System.Windows.Documents.Paragraph
471+ $run = New-Object System.Windows.Documents.Run
472+
473+ $run.Text = $Text
474+ $run.Foreground = $Color
475+
476+ $paragraph.Inlines.Add ($run )
477+ $txtTaskViewer.Document.Blocks.Add ($paragraph )
478+ $txtTaskViewer.ScrollToEnd ()
479+ })
480+ }
268481
269482Start-VSCodeUpdaterGUI
0 commit comments