# dcr-node-tray.ps1 — corre dcr-node.exe oculto con icono en la bandeja (junto a la hora) $ErrorActionPreference = 'Stop' $dir = Split-Path -Parent $MyInvocation.MyCommand.Path $exe = Join-Path $dir 'dcr-node.exe' $logFile = Join-Path $dir 'dcr-node.log' $cfgFile = Join-Path $dir 'config.json' if (-not (Test-Path $exe)) { [System.Windows.Forms.MessageBox]::Show("No se encontro $exe"); exit 1 } Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing $psi = New-Object System.Diagnostics.ProcessStartInfo $psi.FileName = $exe $psi.Arguments = '' $psi.EnvironmentVariables['DCR_SERVE'] = '127.0.0.1:7901' $psi.RedirectStandardInput = $true $psi.RedirectStandardOutput = $true $psi.RedirectStandardError = $true $psi.UseShellExecute = $false $psi.CreateNoWindow = $true $env:DCR_NODE_CONFIG = $cfgFile $psi.EnvironmentVariables['DCR_NODE_CONFIG'] = $cfgFile $proc = New-Object System.Diagnostics.Process $proc.StartInfo = $psi $log = [System.IO.StreamWriter]::new($logFile, $true); $log.AutoFlush = $true $proc.add_OutputDataReceived({ if ($args[1].Data) { $log.WriteLine('[out] ' + $args[1].Data) } }) $proc.add_ErrorDataReceived( { if ($args[1].Data) { $log.WriteLine('[err] ' + $args[1].Data) } }) [void]$proc.Start() $proc.BeginOutputReadLine(); $proc.BeginErrorReadLine() # stdin queda abierto (EOF cerraria el nodo); el cliente se conecta por fuera $ico = New-Object System.Drawing.Icon ([System.Drawing.SystemIcons]::Application, 32, 32) $ni = New-Object System.Windows.Forms.NotifyIcon $ni.Icon = $ico $ni.Text = "dcr-node (PID $($proc.Id))" $ni.Visible = $true $menu = New-Object System.Windows.Forms.ContextMenuStrip $mEstado = $menu.Items.Add("Estado") $mLog = $menu.Items.Add("Ver log") $mSalir = $menu.Items.Add("Salir") $mEstado.add_Click({ $alive = -not $proc.HasExited $ni.ShowBalloonTip(4000, 'dcr-node', ($(if($alive){"Corriendo"}else{"Detenido"})) + " | $dir", 'Info') }) $mLog.add_Click({ if (Test-Path $logFile) { Start-Process notepad.exe $logFile } }) $mSalir.add_Click({ try { if (-not $proc.HasExited) { $proc.StandardInput.Close(); $proc.Kill() } } catch {} $ni.Visible = $false [System.Windows.Forms.Application]::Exit() }) $ni.ContextMenuStrip = $menu $ni.ShowBalloonTip(3000, 'dcr-node', 'Nodo corriendo en segundo plano', 'Info') $timer = New-Object System.Windows.Forms.Timer $timer.Interval = 5000 $timer.add_Tick({ if ($proc.HasExited) { $ni.Text = "dcr-node (detenido)" } }) $timer.Start() [System.Windows.Forms.Application]::Run() $ni.Dispose()